{
    "macro": {
        "prefix": "macro (example)",
        "body": [
            "{",
            "  'name' '${1:euclideanDivision}'",
            "  'desc' ",
            "  <'",
            "${2:This macro returns the quotient and the remainder of a/b.}",
            "  '>",
            "  'sig' [ [ [ ${3:'a:LONG' 'b:LONG'} ] [ ${4:'q:LONG' 'r:LONG'} ] ] ] // Signature",
            "  'params' {",
            "    // Signature params description",
            "    ${5:'b' 'parameter b TOP of the stack'",
            "    'a' 'parameter a just below on the stack'",
            "    'q' 'the quotient of a/b, N-1 on the stack'",
            "    'r' 'the remainder of a/b, on the TOP of the stack'}",
            "  }",
            "  'examples' [",
            "    <'",
            "${6:10 3 @mymacros/euclideanDivision [ 'q' 'r' ] STORE",
            "'quotient is  :' \\$q TOSTRING +",
            "'remainder is :' \\$r TOSTRING +}",
            "    '>",
            "  ]",
            "} 'info' STORE",
            "",
            "<%",
            "  !\\$info INFO",
            "  SAVE 'context' STORE",
            "  <%",
            "    // Code of the actual macro",
            "    ${7:[ 'a' 'b' ] STORE",
            "    \\$a \\$b / TOLONG",
            "    \\$a \\$b %}",
            "      ",
            "  %>",
            "  <% // catch any exception",
            "    RETHROW",
            "  %>",
            "  <% // finally, restore the context",
            "    \\$context RESTORE",
            "  %> TRY",
            "%>",
            "'macro' STORE",
            "",
            "// Unit tests",
            "${8:10 3 @macro [ 'q' 'r' ] STORE",
            "\\$q 3 == ASSERT",
            "\\$r 1 == ASSERT",
            "\\$q TYPEOF 'LONG' == ASSERT",
            "\\$r TYPEOF 'LONG' == ASSERT}",
            "",
            "\\$macro"
        ],
        "description": "Macro"
    },
    "macro(empty)": {
        "prefix": "macro (empty)",
        "body": [
            "{",
            "  'name' '${1: }'",
            "  'desc' ",
            "  <'",
            "${2: }",
            "  '>",
            "  'sig' [ [ [   ] [   ] ] ] // Signature",
            "  'params' {",
            "    // Signature params description",
            "  }",
            "  'examples' [",
            "    <'",
            "",
            "    '>",
            "  ]",
            "} 'info' STORE",
            "",
            "<%",
            "  !\\$info INFO",
            "  SAVE 'context' STORE",
            "  <%",
            "    // Code of the actual macro",
            "    ${3:  }",
            "  %>",
            "  <% // catch any exception",
            "    RETHROW",
            "  %>",
            "  <% // finally, restore the context",
            "    \\$context RESTORE",
            "  %> TRY",
            "%>",
            "'macro' STORE",
            "",
            "// Unit tests",
            "",
            "\\$macro"
        ],
        "description": "Macro"
    },
    "fetchOld": {
        "prefix": "fetch (old list syntax)",
        "body": [
            "[ 'TOKEN' 'className'  { 'label0' '=value0'  'label1' '~val.' }  start timespan ] FETCH"
        ]
    },
    "fetch": {
        "prefix": "fetch",
        "body": [
            "{",
            "  'token'  ${1:\\$readToken}",
            "  'class'  '${2:~.*}'",
            "  'labels' ${3:{\\}}",
            "  'end' ${4:NOW} // timestamp or ISO8601 string",
            "  'timespan' ${5:1 h}  // timespan or start",
            "${6:  'start' NOW 1 h -  // timestamp or ISO8601 string}",
            "${7:  'count' 1000 // optional: limit to 1000 points per gts}",
            "${8:  'boundary' 1 // optional: also fetch one point before and after required timerange}",
            "${9:  'timestep'  5 s // optional: one point every 5 second. see also 'sample' for faster random selection.}",
            "${10:  'step'  10 // optional: returns one point out of 10}",
            "${11:  // see documentation for pagination, gts pagination, and more fetch options}",
            "} FETCH"
        ]
    },
    "bucketize": {
        "prefix": "bucketize",
        "body": [
            "[ ${1:gts} ${2|MACROBUCKETIZER,bucketizer.and,bucketizer.count,bucketizer.count.exclude-nulls,bucketizer.count.include-nulls,bucketizer.count.nonnull,bucketizer.first,bucketizer.join,bucketizer.join.forbid-nulls,bucketizer.last,bucketizer.max,bucketizer.max.forbid-nulls,bucketizer.mean,bucketizer.mean.circular,bucketizer.mean.circular.exclude-nulls,bucketizer.mean.exclude-nulls,bucketizer.median,bucketizer.min,bucketizer.min.forbid-nulls,bucketizer.or,bucketizer.sum,bucketizer.sum.forbid-nulls|} ${3:lastbucket} ${4:bucketspan} ${5:bucketcount} ] BUCKETIZE"
        ]
    },
    "filter": {
        "prefix": "filter",
        "body": [
            "[ ${1:gts} [${2:labels}] ${3|MACROFILTER,filter.byattr,filter.byclass,filter.bylabels,filter.bylabelsattr,filter.bymetadata,filter.last.eq,filter.last.ge,filter.last.gt,filter.last.le,filter.last.lt,filter.last.ne,filter.latencies|} ] FILTER"
        ]
    },
    "map": {
        "prefix": "map",
        "body": [
            "[ ${1:gts} ${2|MACROMAPPER,mapper.abs,mapper.add,mapper.and,mapper.ceil,mapper.count,mapper.count.exclude-nulls,mapper.count.include-nulls,mapper.count.nonnull,mapper.day,mapper.delta,mapper.dotproduct,mapper.dotproduct.positive,mapper.dotproduct.sigmoid,mapper.dotproduct.tanh,mapper.eq,mapper.eq.elev,mapper.eq.hhcode,mapper.eq.lat,mapper.eq.lon,mapper.eq.tick,mapper.exp,mapper.finite,mapper.first,mapper.floor,mapper.ge,mapper.ge.elev,mapper.ge.hhcode,mapper.ge.lat,mapper.ge.lon,mapper.ge.tick,mapper.geo.approximate,mapper.geo.clear,mapper.geo.fence,mapper.geo.outside,mapper.geo.within,mapper.gt,mapper.gt.elev,mapper.gt.hhcode,mapper.gt.lat,mapper.gt.lon,mapper.gt.tick,mapper.hdist,mapper.highest,mapper.hour,mapper.hspeed,mapper.join,mapper.join.forbid-nulls,mapper.kernel.cosine,mapper.kernel.epanechnikov,mapper.kernel.gaussian,mapper.kernel.logistic,mapper.kernel.quartic,mapper.kernel.silverman,mapper.kernel.triangular,mapper.kernel.tricube,mapper.kernel.triweight,mapper.kernel.uniform,mapper.last,mapper.le,mapper.le.elev,mapper.le.hhcode,mapper.le.lat,mapper.le.lon,mapper.le.tick,mapper.log,mapper.lowest,mapper.lt,mapper.lt.elev,mapper.lt.hhcode,mapper.lt.lat,mapper.lt.lon,mapper.lt.tick,mapper.mad,mapper.max,mapper.max.forbid-nulls,mapper.max.x,mapper.mean,mapper.mean.circular,mapper.mean.circular.exclude-nulls,mapper.mean.exclude-nulls,mapper.median,mapper.median.forbid-nulls,mapper.min,mapper.min.forbid-nulls,mapper.min.x,mapper.minute,mapper.mod,mapper.month,mapper.mul,mapper.ne,mapper.ne.elev,mapper.ne.hhcode,mapper.ne.lat,mapper.ne.lon,mapper.ne.tick,mapper.npdf,mapper.or,mapper.parsedouble,mapper.percentile,mapper.percentile.forbid-nulls,mapper.pow,mapper.product,mapper.rate,mapper.replace,mapper.rms,mapper.round,mapper.sd,mapper.sd.forbid-nulls,mapper.sd.welford,mapper.second,mapper.sigmoid,mapper.sqrt,mapper.sum,mapper.sum.forbid-nulls,mapper.tanh,mapper.tick,mapper.toboolean,mapper.todouble,mapper.tolong,mapper.tostring,mapper.truecourse,mapper.var,mapper.var.forbid-nulls,mapper.var.welford,mapper.vdist,mapper.vspeed,mapper.weekday,mapper.year|} ${3:pre} ${4:post} ${5:occurrences} ] MAP"
        ]
    },
    "map full": {
        "prefix": "map (full option)",
        "body": [
            "${1:gtsOrListOfGts}",
            "{",
            "  'mapper' ${2|MACROMAPPER,mapper.abs,mapper.add,mapper.and,mapper.ceil,mapper.count,mapper.count.exclude-nulls,mapper.count.include-nulls,mapper.count.nonnull,mapper.day,mapper.delta,mapper.dotproduct,mapper.dotproduct.positive,mapper.dotproduct.sigmoid,mapper.dotproduct.tanh,mapper.eq,mapper.eq.elev,mapper.eq.hhcode,mapper.eq.lat,mapper.eq.lon,mapper.eq.tick,mapper.exp,mapper.finite,mapper.first,mapper.floor,mapper.ge,mapper.ge.elev,mapper.ge.hhcode,mapper.ge.lat,mapper.ge.lon,mapper.ge.tick,mapper.geo.approximate,mapper.geo.clear,mapper.geo.fence,mapper.geo.outside,mapper.geo.within,mapper.gt,mapper.gt.elev,mapper.gt.hhcode,mapper.gt.lat,mapper.gt.lon,mapper.gt.tick,mapper.hdist,mapper.highest,mapper.hour,mapper.hspeed,mapper.join,mapper.join.forbid-nulls,mapper.kernel.cosine,mapper.kernel.epanechnikov,mapper.kernel.gaussian,mapper.kernel.logistic,mapper.kernel.quartic,mapper.kernel.silverman,mapper.kernel.triangular,mapper.kernel.tricube,mapper.kernel.triweight,mapper.kernel.uniform,mapper.last,mapper.le,mapper.le.elev,mapper.le.hhcode,mapper.le.lat,mapper.le.lon,mapper.le.tick,mapper.log,mapper.lowest,mapper.lt,mapper.lt.elev,mapper.lt.hhcode,mapper.lt.lat,mapper.lt.lon,mapper.lt.tick,mapper.mad,mapper.max,mapper.max.forbid-nulls,mapper.max.x,mapper.mean,mapper.mean.circular,mapper.mean.circular.exclude-nulls,mapper.mean.exclude-nulls,mapper.median,mapper.median.forbid-nulls,mapper.min,mapper.min.forbid-nulls,mapper.min.x,mapper.minute,mapper.mod,mapper.month,mapper.mul,mapper.ne,mapper.ne.elev,mapper.ne.hhcode,mapper.ne.lat,mapper.ne.lon,mapper.ne.tick,mapper.npdf,mapper.or,mapper.parsedouble,mapper.percentile,mapper.percentile.forbid-nulls,mapper.pow,mapper.product,mapper.rate,mapper.replace,mapper.rms,mapper.round,mapper.sd,mapper.sd.forbid-nulls,mapper.sd.welford,mapper.second,mapper.sigmoid,mapper.sqrt,mapper.sum,mapper.sum.forbid-nulls,mapper.tanh,mapper.tick,mapper.toboolean,mapper.todouble,mapper.tolong,mapper.tostring,mapper.truecourse,mapper.var,mapper.var.forbid-nulls,mapper.var.welford,mapper.vdist,mapper.vspeed,mapper.weekday,mapper.year|}",
            "  'pre' {3:pre} // tick number when positive, time span when negative",
            "  'post' {3:post} // tick number when positive, time span when negative",
            "  // 'occurences' {4:occurrences} // when positive, start from the oldest tick. When negative, starts from the oldest tick and go in reverse order. Defaults to 0, all ticks.",
            "  // 'step' {4:step} // The step size in number of ticks. defaults to 1.",
            "  // 'override' overrideTickBOOLEAN // If set to true, the tick value returned by the mapper is used to update the current tick. Defaults to false.",
            "  // 'ticks' outputTicksLIST // If non null, it sets the list of ticks that is traversed to anchor the sliding windows",
            "} MAP"
        ]
    },
    "reduce": {
        "prefix": "reduce",
        "body": [
            "[ ${1:gts} [${2:labels}] ${3|MACROREDUCER,reducer.and,reducer.and.exclude-nulls,reducer.argmax,reducer.argmin,reducer.count,reducer.count.exclude-nulls,reducer.count.include-nulls,reducer.count.nonnull,reducer.join,reducer.join.forbid-nulls,reducer.join.nonnull,reducer.join.urlencoded,reducer.max,reducer.max.forbid-nulls,reducer.max.nonnull,reducer.mean,reducer.mean.circular,reducer.mean.circular.exclude-nulls,reducer.mean.exclude-nulls,reducer.median,reducer.min,reducer.min.forbid-nulls,reducer.min.nonnull,reducer.or,reducer.or.exclude-nulls,reducer.sd,reducer.sd.forbid-nulls,reducer.shannonentropy.0,reducer.shannonentropy.1,reducer.sum,reducer.sum.forbid-nulls,reducer.sum.nonnull,reducer.var,reducer.var.forbid-nulls|} ] REDUCE"
        ]
    },
    "apply": {
        "prefix": "apply",
        "body": [
            "[ ${1:gts} [${2:labels}] ${3|OP,op.add,op.add.ignore-nulls,op.and,op.and.ignore-nulls,op.div,op.eq,op.ge,op.gt,op.le,op.lt,op.mask,op.mul,op.mul.ignore-nulls,op.ne,op.negmask,op.or,op.or.ignore-nulls,op.sub|} ] APPLY"
        ],
        "description": "Apply framework"
    },
    "ift": {
        "prefix": "ift",
        "body": [
            "<% ${1:condition} %>",
            "<% ${2:action_if_true} %>",
            "IFT"
        ],
        "description": "If statement"
    },
    "ifte": {
        "prefix": "ifte",
        "body": [
            "<% ${1:condition} %>",
            "<% ${2:action_if_true} %>",
            "<% ${3:action_if_false} %>",
            "IFTE"
        ],
        "description": "If then else statement"
    },
    "switch": {
        "prefix": "switch",
        "body": [
            "<% ${1:case_1} %> <% ${2:action_1} %>",
            "<% ${3:case_2} %> <% ${4:action_2} %>",
            "<% ${5:case_3} %> <% ${6:action_3} %>",
            "<% ${7:default} %>",
            "${8:number_of_cases}",
            "SWITCH"
        ],
        "description": "Switch statement"
    },
    "try": {
        "prefix": "try",
        "body": [
            "<% ${1:try} %>",
            "<% ${2:catch} %>",
            "<% ${3:finally} %>",
            "TRY"
        ],
        "description": "Try/Catch statement"
    },
    "while": {
        "prefix": "while",
        "body": [
            "<% ${1:condition} %>",
            "<% ${2:action_while_true} %>",
            "WHILE"
        ],
        "description": "While loop"
    },
    "until": {
        "prefix": "until",
        "body": [
            "<% ${1:action_until_true} %>",
            "<% ${2:condition} %>",
            "UNTIL"
        ],
        "description": "Until loop"
    },
    "for": {
        "prefix": "for",
        "body": [
            "${1:initial_value} ${2:final_value}",
            "<% ${3:action} %>",
            "FOR"
        ],
        "description": "For loop"
    },
    "foreach": {
        "prefix": "foreach",
        "body": [
            "${1:object}",
            "<% ",
            "  //[ 'key' 'value' ] STORE // object is a map",
            "  //[ 'value' ] STORE // object is a list",
            "  ${2:action}",
            "%>",
            "FOREACH"
        ],
        "description": "Foreach loop"
    },
    "forstep": {
        "prefix": "forstep",
        "body": [
            "${1:initial_value} ${2:final_value} <% ${3:1 +} %>",
            "<% ${4:action} %>",
            "FORSTEP"
        ],
        "description": "Forstep loop"
    },
    "shm": {
        "prefix": "shm",
        "body": [
            "<%",
            "  <%",
            "    //try to read data from SHared Memory",
            "    'gtsList' SHMLOAD DROP",
            "  %>",
            "  <%",
            "    //when not found, store data in SHM",
            "    ${1:[ \\$token 'classname' {\\} NOW 365 d ] FETCH} 'gtsList' SHMSTORE",
            "  %>",
            "  <%",
            "    //finally, load the reference from SHM and store it ",
            "    'gtsList' SHMLOAD 'gtsList' STORE",
            "  %> TRY",
            "",
            "  //analytics on \\$gtsList",
            "  ${2:\\$gtsList}",
            "",
            "",
            "",
            "%> 'myMutex' MUTEX //prevent a concurrent execution on the same SHM data"
        ],
        "description": "Keep fetched data in RAM. You need to enable the SHM extension."
    },
    "tokengen": {
        "prefix": "tokengen",
        "body": [
            "'myapp' 'applicationName' STORE",
            "NOW 1 ADDYEARS MSTU / 'expiryDate' STORE",
            "UUID 'ownerAndProducer' STORE",
            "",
            "{",
            "  'id' 'TokenRead'",
            "  'type' 'READ'",
            "  'application' \\$applicationName ",
            "  'owner'  \\$ownerAndProducer",
            "  'issuance' NOW MSTU /",
            "  'expiry' \\$expiryDate",
            "  'labels' { }   ",
            "  'attributes' {",
            "      // '.cap:maxops'  10e9 TOLONG TOSTRING // capability to raise maxops to 10 billions of operations",
            "      // '.cap:tokengen'  ''                 // capability to use TOKENGEN within WarpScript",
            "      // '.cap:http' ''                      // capability to use HTTP",
            "   } ",
            "  'owners' [ \\$ownerAndProducer ]",
            "  'producers' [ \\$ownerAndProducer ]",
            "  'applications' [ \\$applicationName ]  ",
            "} TOKENGEN",
            "",
            "{",
            "  'id' 'TokenWrite'",
            "  'type' 'WRITE'",
            "  'application' \\$applicationName ",
            "  'owner'  \\$ownerAndProducer",
            "  'producer' \\$ownerAndProducer",
            "  'issuance' NOW MSTU /",
            "  'expiry' \\$expiryDate",
            "  'labels' { }   ",
            "  'attributes' { } ",
            "} TOKENGEN",
            ""
        ]
    },
    "newgts01": {
        "prefix": "newgts (100 random values)",
        "description": "",
        "body": [
            "NEWGTS 1 100 <% NaN NaN NaN RAND ADDVALUE %> FOR "
        ]
    },
    "newgts02": {
        "prefix": "newgts (100 random walk values)",
        "description": "",
        "body": [
            "100 @senx/rand/RANDOMWALK"
        ]
    },
    "newgts03": {
        "prefix": "newgts (2 gts, non aligned)",
        "description": "",
        "body": [
            "[",
            "  [ 0 1 2 3 ] [] [] [] [ 10 -11 12 -13 ] MAKEGTS 'gts a' RENAME",
            "  [ 0 1 3 6 ] [] [] [] [ 20 -21 22 -23 ] MAKEGTS 'gts b' RENAME",
            "]"
        ]
    },
    "discovery (ex1)": {
        "prefix": "discovery example 1: autorefresh",
        "description": "Discovery within WarpScript with autorefresh with macros executed by the dashboard",
        "body": [
            "// @endpoint https://sandbox.senx.io/api/v0/exec",
            "// (endpoint of your Warp 10 exec endpoint is mandatory if you also use Discovery Explorer)",
            "// @preview discovery",
            "// (opens the discovery tab after execution)",
            "// @theme dark-blue",
            "// (can be light / dark / green / fresh / dark-blue / chalk / vintage, as in Discovery Explorer)",
            "{",
            "  'title' 'Discovery Dashboard'",
            "  'description' 'test dashboard'",
            "  'tiles' [",
            "    {",
            "    'title' 'random data, autorefresh'",
            "    'options' { 'autoRefresh' 1   'showErrors' true }",
            "    'x' 0 'y' 0 'w' 12 'h' 2",
            "    'type' 'area' ",
            "    'macro' <%",
            "        1 4 <% DROP ",
            "          NEWGTS 'g' STORE",
            "          1 10 <% ",
            "            'ts' STORE \\$g \\$ts RAND + STU * NOW + NaN NaN NaN RAND ADDVALUE DROP ",
            "          %> FOR",
            "          \\$g ",
            "        %> FOR ",
            "      %>",
            "    }",
            "  ]",
            "}",
            "// the `// @preview discovery` will wrap the execution result in a html page, using <discovery-dashboard> webcomponent.",
            ""
        ]
    },
    "discovery (ex2)": {
        "prefix": "discovery example 2: events",
        "description": "Discovery within WarpScript",
        "body": [
            "// @endpoint https://sandbox.senx.io/api/v0/exec",
            "// (endpoint of your Warp 10 exec endpoint is mandatory if you also use Discovery Explorer)",
            "// @preview discovery",
            "// (opens the discovery tab after execution)",
            "// @theme dark",
            "// (can be light / dark / green / fresh / dark-blue / chalk, as in Discovery Explorer)",
            "",
            "true 'debug' STORE // add a debug panel to understand events",
            "",
            "[ 'temperature' 'pressure' 'flow' ] 'channelSelection' STORE // input list",
            "\\$channelSelection 1 GET 'channelName' STORE // variable default value (pressure)",
            "NOW 'endDate' STORE          // variable default value",
            "\\$endDate 10 d - 'startDate' STORE // variable default value",
            "{ ",
            "  'temperature' 'red' ",
            "  'pressure' 'chocolate'",
            "  'flow' 'cyan'",
            "} 'dataSetColors' STORE",
            "",
            "{",
            "  'title' 'Discovery Dashboard, responsive, with events'",
            "  'description' 'test dashboard'",
            "  'type' 'flex' // no need to specify each tile x y position",
            "  'cols' 4      // 4 columns",
            "  'cellHeight' 120",
            "  'vars' { // list of dashboard variables (can be set via dashboard url too)",
            "    'channelName' \\$channelName  // default value",
            "    'endDate' \\$endDate",
            "    'startDate' \\$startDate",
            "  }",
            "  'options' { 'showErrors' true  'eventHandler' 'type=popup,tag=dashboard' }",
            "  'tiles' [",
            "    {",
            "      'type' 'input:list' 'w' 1 'h' 1",
            "      'title' 'Select classname'",
            "      'macro' <% {",
            "        'events' [ { 'tags' 'input' 'type' 'variable' 'selector' 'channelName' } ]",
            "        'globalParams' { 'input' { 'value' \\$channelName } } // default value",
            "        // when refering to a variable defined outside the tile macro and not in dashboard vars,",
            "        // use early binding:  !\\$xxx  will replace the variable by its content during the first execution.",
            "        'data' !\\$channelSelection",
            "      } %>",
            "    }",
            "",
            "    {",
            "      'type' 'input:date' 'w' 1 'h' 1",
            "      'title' 'Select start date'",
            "      'macro' <% {",
            "        'events' [ { 'tags' 'input' 'type' 'variable' 'selector' 'startDate' } ]",
            "        'data' \\$startDate",
            "      } %>",
            "    }",
            "",
            "    {",
            "      'type' 'input:date' 'w' 1 'h' 1",
            "      'title' 'Select end date'",
            "      'macro' <% {",
            "        'events' [ { 'tags' 'input' 'type' 'variable' 'selector' 'endDate' } ]",
            "        'data' \\$endDate",
            "      } %>",
            "    }",
            "   ",
            "    // a popup triggered by a button can be usefull to hide some less usefull features of your dashboard.",
            "    // note that buttons can do other things. try 'discovery-tile 11 input:button' snippet.",
            "    {",
            "      'type' 'button' 'w' 1 'h' 1",
            "      'title' 'Statistics'",
            "      'macro' <%",
            "        { ",
            "          'data' <%",
            "            {",
            "              'events' [ ",
            "                { ",
            "                  // This event will send an event to the dashbard itself. At the dashboard level, you must suscribe the event by adding:",
            "                  // 'options' { 'eventHandler' 'type=popup,tag=dashboard' }",
            "                  'tags' [ 'dashboard' ] ",
            "                  'type' 'popup'",
            "                  // the value of a popup event is a tile (you can also insert it with any 'discovery-tile xxx' snippet",
            "                  'value' {",
            "                    'type' 'tabular' 'w' 4 'h' 2",
            "                    'title' 'Advanced Statistics'",
            "                    'macro' <%",
            "                      {",
            "                        'columns' [ 'classname' 'Min' 'Max' 'Median' 'Link' ]",
            "                        'rows' [",
            "                          [ 'temperature'  15  56  44  '<a href=\"https://warp10.io/\">Warp 10</a>' ]",
            "                          [ 'pressure'  1    5   4.5  '<a href=\"https://senx.io/\">SenX</a>' ]",
            "                          [ 'flow'  14  45  30.54  '<img src=\"https://warp10.io/assets/img/header-w-white.png\" />' ]",
            "                        ]",
            "                      } ",
            "                      'values' STORE                  ",
            "                      { 'data' \\$values } ",
            "                    %>",
            "                  } // end of the tile in the popup event",
            "                }",
            "              ]",
            "            }",
            "          %>",
            "          'globalParams' { 'button' { 'label' 'Display Stats' } } ",
            "        }",
            "      %>",
            "    }",
            "    ",
            "    \\$debug ",
            "    <%",
            "      { // this display will help you to debug your event source",
            "        'type' 'display' 'w' 4 'h' 1",
            "        'title' 'debug panel'",
            "        'options' { 'eventHandler' 'type=variable,tag=input' } // suscribe to input",
            "        'macro' <%  // you can write html in a display tile...",
            "            [ '<b>channelName=</b>' \\$channelName + ",
            "              '<b>startDate=</b>' \\$startDate ISO8601 + ",
            "              '<b>endDate=</b>' \\$endDate ISO8601 + ",
            "            ] ' -- ' JOIN",
            "        %>",
            "      }",
            "    %> IFT ",
            "",
            "    {",
            "      'type' 'line' 'w' 4 'h' 4",
            "      'options' { 'eventHandler' 'type=variable,tag=input' } // suscribe to input",
            "      'macro' <% ",
            "        // generate a fake GTS",
            "        NEWGTS \\$channelName RENAME",
            "        \\$startDate \\$endDate <% 1 h + %> <% NaN NaN NaN RAND ADDVALUE %> FORSTEP 'gts' STORE",
            "        {",
            "          'data' \\$gts ",
            "          'globalParams' {  'showLegend' true } ",
            "          'params' [",
            "            // when refering to a variable defined outside the tile macro and not in dashboard vars,",
            "            // use early binding:  !\\$xxx  will replace the variable by its content during the first execution.",
            "            { 'datasetColor' !\\$dataSetColors \\$gts NAME GET } ",
            "          ]",
            "        }",
            "      %>",
            "    }",
            "",
            "  ]",
            "}",
            "// the `// @preview discovery` will wrap the execution result in a html page, using <discovery-dashboard> webcomponent.",
            "// this file, saved as xxx.mc2, can be served directly by discovery-explorer.",
            ""
        ]
    },
    "discovery (empty)": {
        "prefix": "discovery empty dashboard",
        "description": "Discovery within WarpScript",
        "body": [
            "// @endpoint ${1:http://localhost:8080/api/v0/exec}",
            "// (endpoint of your Warp 10 exec endpoint is mandatory if you also use Discovery Explorer)",
            "// @preview discovery",
            "// (opens the discovery tab after execution)",
            "// @theme dark",
            "// (can be light / dark / green / fresh / dark-blue / chalk, as in Discovery Explorer)",
            "",
            "// default variable definition",
            "",
            "",
            "{",
            "  'title' '${2:Discovery Dashboard}'",
            "  'description' '${3:test}'",
            "  'type' 'flex' // flex : no need to specify each tile x y position",
            "  'cols' ${4:4}      // 4 columns",
            "  'cellHeight' ${5:120}",
            "  'vars' { // list of dashboard variables (can be set via dashboard url too)",
            "  ",
            "  }",
            "  'options' { 'showErrors' true  'eventHandler' 'type=popup,tag=dashboard' }",
            "  'tiles' [",
            "    // list of tiles (type discovery-tiles to get some snippets)",
            "    ${6:}",
            "  ]",
            "}",
            "// the `// @preview discovery` will wrap the execution result in a html page, using <discovery-dashboard> webcomponent.",
            ""
        ]
    },
    "dtile01": {
        "prefix": "discovery-tile 01 line, area...",
        "description": "Discovery within WarpScript",
        "body": [
            "{",
            "  'type' 'line'  'w' 4 'h' 4 // type can also be area, spline-area, step-area, spline, step, step-after, step-before",
            "  'options' { 'eventHandler' 'type=variable,tag=input' } // suscribe to events",
            "  'macro' <% ",
            "    // fetch and process data here",
            "    ${1:[ NEWGTS 0 10 <% m NaN NaN NaN RAND ADDVALUE %> FOR ]} ",
            "    'gtsList' STORE",
            "    {",
            "      'data' \\$gtsList",
            "      // 'globalParams' { // optional",
            "      //   'showLegend' true",
            "      //   'thresholds' [ // can also define markers, see doc.",
            "      //     { 'value' 75 'color' '#77BE69' 'name' 'Danger' 'fill' false }",
            "      //   ]",
            "      // }",
            "      // 'params' [ // optional",
            "      //   { 'key' 'My sensor' 'datasetColor' '#8A2BE2' 'type' 'spline-area' }  // one configuration per output gts",
            "      // ]",
            "    }",
            "  %>",
            "}"
        ]
    },
    "dtile02": {
        "prefix": "discovery-tile 02 display",
        "description": "Discovery within WarpScript",
        "body": [
            "{",
            "  'type' 'display' 'w' 4 'h' 2",
            "  'title' ''",
            "  'options' { 'eventHandler' 'type=variable,tag=input' } // suscribe to events",
            "  'macro' <%",
            "      {",
            "        'data' ${1:42.0} // any number or string, or html string",
            "        // 'globalParams' { ",
            "        //   'timeMode' 'custom' // custom, date, duration",
            "        //   'unit' '°C' 'bgColor' '#f57f17' 'fontColor' '#fc0000'",
            "        // }",
            "      }",
            "  %>",
            "}"
        ]
    },
    "dtile03": {
        "prefix": "discovery-tile 03 input:date",
        "description": "Discovery within WarpScript",
        "body": [
            "{",
            "  'type' 'input:date' 'w' 1 'h' 1",
            "  'title' 'Select start date'",
            "  'macro' <% {",
            "    'events' [ { 'tags' 'input' 'type' 'variable' 'selector' 'startDate' } ]",
            "    'data' ${1:defaultValue}  // you must define  'startDate' ${1:defaultValue}  into dashboard 'vars' too.",
            "  } %>",
            "}"
        ]
    },
    "dtile04": {
        "prefix": "discovery-tile 04 input:date range",
        "description": "Discovery within WarpScript",
        "body": [
            "{",
            "  'type' 'input:date-range' 'w' 2 'h' 1",
            "  'title' 'Select date range'",
            "  'macro' <% {",
            "    'events' [ { 'tags' 'input' 'type' 'variable' 'selector' 'startEndDates' } ]",
            "    'data' [ ${1:defaultStartValue} ${2:defaultEndValue} ]",
            "// you must define  'startEndDates' [ ${1:defaultStartValue} ${2:defaultEndValue} ]  into dashboard 'vars' too.",
            "  } %>",
            "}"
        ]
    },
    "dtile05": {
        "prefix": "discovery-tile 05 table view",
        "description": "Discovery within WarpScript",
        "body": [
            "{",
            "  'type' 'tabular' 'w' 4 'h' 2",
            "  'title' 'Table'",
            "  'options' { 'eventHandler' 'type=variable,tag=input'  // suscribe to events",
            "    'tabular' { 'fixedWidth' true }",
            "  }",
            "  'macro' <%",
            "    ${1:{",
            "      'columns' [ 'Name' 'A' 'B' 'C' 'Link' ]",
            "      'rows' [",
            "        [ 'label X'  15  56  44  '<a href=\"https://warp10.io/\">Warp 10</a>' ]",
            "        [ 'label Y'  1    5   4  '<a href=\"https://senx.io/\">SenX</a>' ]",
            "        [ 'label Z'  14  45  78  '<img src=\"https://warp10.io/assets/img/header-w-white.png\" />' ]",
            "      ]",
            "    \\} }",
            "    'values' STORE",
            "",
            "    { 'data' \\$values } // data can also be a gts or a list thereof",
            "  %>",
            "}"
        ]
    },
    "dtile06": {
        "prefix": "discovery-tile 06 bar chart",
        "description": "Discovery within WarpScript",
        "body": [
            "{",
            "  'type' 'bar' 'w' 4 'h' 3",
            "  'title' 'Bar Chart'",
            "  'options' { 'eventHandler' 'type=variable,tag=input' } // suscribe to events",
            "  'macro' <%",
            "    ${1:{",
            "      'title' 'Bar Chart'",
            "      'columns' [ 'failure A' 'failure B' 'failure C' ]",
            "      'rows' [",
            "        [ 'device A'       15  56  44  ]",
            "        [ 'device B'       1    5   4  ]",
            "        [ 'fleet average'  14  45  78  ]",
            "      ]",
            "    \\} }",
            "    'values' STORE",
            "",
            "    { ",
            "      'data' \\$values // data can also be a gts or a list thereof",
            "      // 'globalParams' { 'bar' { 'stacked' true } }",
            "    } ",
            "  %>",
            "}"
        ]
    },
    "dtile07": {
        "prefix": "discovery-tile 07 gauge",
        "description": "Discovery within WarpScript",
        "body": [
            "{",
            "  'type' 'gauge' 'w' 1 'h' 2  // gauge, circle, compass",
            "  'title' 'temperature'",
            "  'options' { ",
            "    'eventHandler' 'type=variable,tag=input' // suscribe to events",
            "    'autoRefresh' 2",
            "  } ",
            "  'macro' <%",
            "      ${1:RAND 100 * 50 - ROUND} 'value' STORE",
            "      {",
            "        // data can be a number, or a list of number for several gauge in the same tile",
            "        'data' \\$value ",
            "        'params' [ { 'minValue' -50 'maxValue' 50 'datasetColor' \\$value 0 > <% '#00f010' %> <% '#f01000'  %> IFTE  } ]",
            "        'globalParams' { 'unit' '°C' } // 'bgColor' is also possible.",
            "      }",
            "  %>",
            "}"
        ]
    },
    "dtile08": {
        "prefix": "discovery-tile 08 linear gauge",
        "description": "Discovery within WarpScript",
        "body": [
            "{",
            "  'type' 'linear-gauge' 'w' 2 'h' 2 ",
            "  'title' 'disk usage'",
            "  'options' { ",
            "    'eventHandler' 'type=variable,tag=input' // suscribe to events",
            "    'autoRefresh' 2",
            "  } ",
            "  'macro' <%",
            "      // for this type of gauge, minimum value is 0 and value cannot be negative",
            "      RAND 452 * ROUND 'value' STORE",
            "      {",
            "        // data can be a number, or a list of number for several gauge in the same tile",
            "        'data' \\$value ",
            "        'params' [ { 'maxValue' 452 'datasetColor' \\$value 350 < <% '#00f010' %> <% '#f01000'  %> IFTE  } ]",
            "        'globalParams' { 'unit' 'GB' 'gauge' { 'horizontal' true } } // 'bgColor' is also possible.",
            "      }",
            "  %>",
            "}"
        ]
    },
    "dtile09": {
        "prefix": "discovery-tile 09 scatter",
        "description": "Discovery within WarpScript",
        "body": [
            "{",
            "  'type' 'scatter' 'w' 4 'h' 2  ",
            "  'title' 'Scatter'",
            "  'options' { 'eventHandler' 'type=variable,tag=input' } // suscribe to events",
            "  'macro' <%",
            "    ${1:[",
            "      // values is a list of [ X Y ] coordinates (try ZIP function !)",
            "      { 'label' 'two points' 'values' [ [ 0.5 0.5 ] [ 1.0 1.0 ] ] \\} ",
            "      { 'label' 'one point'  'values' [ [  -1  -2 ] ] \\}",
            "    ]} 'value' STORE",
            "    {",
            "      'data' \\$value // it can also be a gts or list of gts",
            "      'globalParams' { 'bounds' { 'minDate' -1.5 'maxDate' 2.5  'yRanges' [ -2 2 ] } }",
            "    }",
            "  %>",
            "}"
        ]
    },
    "dtile10": {
        "prefix": "discovery-tile 10 map",
        "description": "Discovery within WarpScript",
        "body": [
            "{",
            "  'type' 'map' 'w' 4 'h' 4  ",
            "  'title' 'Map'",
            "  'options' { 'eventHandler' 'type=variable,tag=input' } // suscribe to events",
            "  'macro' <%",
            "    '60VBSaKcPLCgOKCkOLKZ5k.L.0N.5k..PDkd6sg7.........6LPUp1eqMb6RyzavjL_EmQII2dCBgrjIIPQOAEOQ8fSnAGzSSeO85qaoy_oqXGCorIPIIjIIXUh6zqYBse9XgV4G3G3GEm4X7eVM3G3K3F3G4FF03G3G.G4wFRVeEI9TRvRkwAxWzbBylvTttnnbjBwryRtvzaEEzQPWrRovJPsxnRzzOYz8rygpMKzWi9AvgsjMiUwqXIuvGjtsT.YmZwMh0GTtznSXkjJyEf4oIqkhRC6QrX9LDOkS2o22hjLQY0n7ekh.Q0RUb6P2QmNwYQr7Psl2YhCEsU6rrRjYZ7IBIxNJ2whxHBRE4_vI3_OgRtdQDzyJeB6OjU9iJOVtvEbQLQVW3wJMrb0NTrjJBAIF8rf0JjjPSHsRSeo.LoNxT8OAr0nQfVn.BlBI5j1mEX0VzZ6K7POs3IWrZ2jeD73L6zTR6k9Q7Yk5Xy0IPj9ik8k9fLfjwEYbhKrpSJVjj0ZpFlVXwnCOSPJv2KDYQlDgSb8NkuuKuDNbFpzX8f_dLB6MU.MyMIehVzsOEFaCk2C8RRarvyWmm9IbYR5IKHp.qEIkD90QShnN5_MO5VLLQOU6QZzIf3bOD44i2_FTmgl.kxShBmiVVqOMqzx2rGOTDSliP68Sgtrj_q2OhnBv_93Ph1BXvT9.p4gnxdP4kRDuoGrdwVqTvTCcj8pxxsorAixQAr9.CRTSvfmk9PS7JRhWKXOxswo.7yUl8SQV4MvKrphkDchid366AeTbip.M0DzHeUydqGPr2.qw0PKKkqf8S1DbqLhxFEM1WRJkw19ttaYJT2JL4po6CWbUpsr0LkyDtOcVHrvLUogw4HYkYR6A0Z9IHw.qulRYOZeSJFnAatzG.qotROg4EUW8imWHNMS.Po6XcqqSL0Mrwn98f0lDG_p.xBCaQ.MLCYauho0ravTaVw.Cskrr.LGpPm3zKjJsZWInlsTIIsR1.BrSoXi2q65Beherzz0.58OnG3T89Tj7ss6AqazXKFldnpTt_YWBGTMfg6zAK_qIeYzZ5ccyaJePBPvNfRCFYD2a8rx2Qcgo9UOhz2u6FbYUFANjrRGrwEANfVsuR3v7xfdSFAfVehpXqX8hMHpYrfTcglvOyiIg7uQvtn0MpUgBj5pwdk8zpTTWZIrg6bnuUcLjCahWveh12Xk39zrwdRk.gOXmocKjmFhM4zD7byXQPxzHcL3Dk3Kr0DdI3hmvAD3SFbkXxHqQI.deT7vNtC6PH5kuu2pgVEsdAgs7eroeJcLTqV7aRsKyjgUJxPKcbV1zWEg16HfsIzbQOr4Us0O6irqnD0GilmwqU8W_8cbc_q4Mo2jr2rCCaW14xDMbBYRvO6wguHrfRanBhEz0ChbUXfgVfw7xstvE4JR9YbrW3DZT45yJNcx_CESV2qXgi1unm6I1wnpEuLoWGkf.PNtCoTIjoACLB5_xJDsA5fU5zmMHYThI7IxGGk9ijQPqaceTm3tofDkXqNjG6gyA0aLAJZmh2AMIYmMC1UgfGRMbfvRtiFxhIj6Pw8aRVdKHop_KuOoU2gMALnDbjor4Ajqd_4FJlZaWdQ1NI3kUoReVY001Or9n21kk2ui6F3ytvLbRRkVhZdOz503ImNaZDr7gzuupmYD0JEL2MDGRpzozHjNtgtNoY1CPjsTUlyjOayrpKcTtZjgxbLiSq3K3OYfPR3fzgeiHNEeR3p4WBS7biHLFgl641EIexm.avnBXbsGRNr.rnAyKy.cydQtzS0ZRzhOx0akS5olKFwgP9iAb2kdBNqStANgU7.s_GJJgxx6QDfDP.8zWEX1UWREUezJ2uZWzHOCh0GnQQw6rMVykDMXOub1ThivX0aaLBjsSl1AQ7Qcw2i7rPPObQtj7uQ6bciwQmDqgdxEnF0Ud8KpzR2yp9VwwmrZIMdPgsd6C5Q1HYzv4fcvhLORxk6bfyTDxR0Xqplah3cQVJM8t_Tni57MlN0tzZKCuvSA4goWlPxcdf2tB.cxtgpP0XQTeGmWDTeTnH5aQYEuI2EBX6VViMJEBt8UIpfPj_gtPuf2.xoTiZuIfaGp9T.AinxozKrZMGPTInsePkVrZIBw4Rf4wA1wuintt6gkSO9RW.MB6Bmv2c4K_eDGyiwWIjI3bzJ0tvaMRVxunNlJcAmScnLS9T2zXl_A4fYiavjgYi8brHSf_q68y1GOKYBg8QDGraJ6nY2Ptgy0JzIQQSzvwEm5vVE40mMQor6ypmbtgSDRT.AAxOOYj.IqpQ7_uRffCOaJfj0YS2Zmht4ckPjTg5_Y.fCH5MgIg5nTlRGhcWCvY5Sc_kofDnxQhajNsNNs1vSIvpfPNBE8EMMujsGMiH78So1IvQaGc01sNIClAFMqHKQR.w1eVv4p0Q02mKLB7xE68xmVsW3KDRaQhM.r3afTburRvOIvq8ql.7gqIxbfo1_hy9AbQx0_Lo2U37.aJnUbUL3w0cue3.BqyjYP828y8lQzCuL7ywuisSt8s6.oYopR2YILVMTmBPDW8inC2hKx262qAdb4wUUcgYCxhwr0eNjGEwqj3hQ8R1woecUvJHGIbGbfMuVLXD9_iqHLS63pO0n6ZLeLhPE0XS0sKsRDLDhNKwzWPAvc6nSWusShmXJX0D6geIIpguQflxGFtCZ8IeRBaaD40OXJDQSIRSgmyGHmNRKCHBcTIBmRebs52S1xT7n_L9lJ4lnOo7N0ad21tBeraB4287F8dKw7g0RyZVDLhZOWvS15ICwdSpOTGDZWdqybJWxkChO6Yy3zFznbY6CcZh7MljsOMbzZP6TfHgd8Y9PaSeBpysykD2DilYKZiIJhyYF76a8Lm2GJh85SwOTbcLY8hXIEcyHUO5Bxv9E9jW4SdYNp8ohMmA0YKYYtX07cgjEOmWmK40zYTmUPTVYod0.WKU5fC83gP7ar7q6Fqx6lOuHcpjTDAsak2YbXrJi.vthL.Y8Vyhrawm3gu6BTflmNn5E4otPJ1eI5_3UhzbSoDHYn9bI7Rhn2TtSXnU6CRyJtF7b8Y8NrB5uk.0iL2atgL.upLeULRHulEMXtWUL_UMAS1uOp4eMtEu4ryybaELGPqKvsG6aqPqxOXB4Ub8qByjx1_urMPhZG6_2onAcAfCYdpqnXTMqOWtB28SEyr6Yj1WxOSVTKgoz942CbPMR_WIq5PXasMLJUXqIDjQ69ZZlODJRHKyrYBcy.pSeLerHKwTn7ipGkXYbgWrj0tQlh1zjzZorhRWMjrPl_Y7w19qzQjMr_cPU37Tgmak4wBKrURKROtLX5SEigu.T_UdWXzCy_GOf30Xy7CkD6Nwh.CAMigyzpk23TURV.3ORxkWmyVFVSZYKUxk8QTtj3_xy2wKn6viGVYp.CL5LJWEygSfWBYdId5UfTEcB0BgJZRukcFUwF5i_dt5.CNX0CU5dSvFFOdKeQarD2j57eMK6hDmKvNwuxIx8w0wh5AhlYdrkyDb.asHpuF8uGJZosvqLh.Bhr_pVusC2Gxh.7B1_5KHRn2_MtUogleLzePOaxeRDcvF2rVl1wZQ4JeD5xmXasB4onDc1OtgnT.Y.d2Rbfmju.iUqxZirNvhFrHQ4SdiARcXEh4Q1VAWGZKXcuHbeHjWa4pk7XzeEjioncoyabDq_VJLC9AUZyLajqklSmSz25i.zfX46cx.r.yVd4braEV7DmdcCiL7y1UCEen.TkZLDi0ZVs944PABc1WrPapJMVg6r8qN2qa7jMxpMeEfTsnsExBCGzghXDHv6CkJiwCnN4aRCY58yt_w3wVrt7tE_DCf2efaJe.LEHgLej7g1iwQh.3iO.CrdAboU9xrOtcyrrmmPPQYfBYflMyP75CEjhLMX05TMTUVxkIDTq6gD1CXpNhtifA5tmBRDXUI.iXPJzVUBExC97j7IBXcVwWa8gYv9h6oUMmGn7Uq0lSF2I5uS5CCyeQ.ytKBalnURyUaKyO7pupavUfhlNO2t3Qcm0nKrO4cmQNQUjgxw4Eq6_InElVbmtBU2pWrsRgQjTdNK5FgrdvpINcEXhCtZ7vfjSRRa2UanI4xSDezGQTfcPu6uvQ9nZ62nNLvDiU8uRblc8TuMk.Ia4ArJ7IGZUmNXft8Yad58x4SYWadRrVgrwxc7zx6PO3rekiMlWYnkaoy7PEvhdz3xVASZ2tnRkrdIevjV9lbgzuyZIk0dI1YBbP_X6O8c59Km4VsT4Mue0ifBz9Zj8XBp1HJQPS4jkUa9MYOrWxmgrppHSX6ZEn.WqfpdWggmpn.Aj0yVtkXAv6eSdSD_Hs0exqvq_upzLr6OeXnweisMXIbGZik0wfavor.CAU4dTATlxtapwV_uOY_4lkRpx8r1XiPav0n7XgPIrv1R_mtTIMQx6XIgqMREFIC7JE_6XnA06DYF4f2Ks2bINvLlqx8XeWEOM84pW8MwdX9DzGAPrYvnOTjroweRcYiNVSknzXUFNUMwA1r4k_N3EaRmI0hgCxbA1vJJu903Luy.T3XoegaPUNNDFhSpNfIy4zTBKIcYVgh__CzwBsToThybbeE.UvbjmmgH9f89H8oxZpi6g5JbY1XyGj4IADh29GJME0xiTxR2vp19ADyz5XGmGY4nSRwuVIZfJaRb18RKqQXFIKOFTQndtV.yWY4v8UVPOTyQLmKycUr4Yw0OAEmtMKsjfU1fASJC_yRvL5IvxHAallA6CYHViCO9mMgwpvEJ15lbLqMsZILLWdYwjZzDAdzgP8U.sLw0KsLmYMbPekGa5hIZy.oleySmihLyWXdPzCJTug6tM66KofX6Q0zSbQt5bKTFlkP9s_Qq2in3rbkk1CnRD2DpYRUtHmtEu6FuiHZkTLgZ68YpMmEAsvCGIPbBdlfj0Bl7KbSzL3EZQTRA4n3zF2r6uZUSmhegB_tXeghD9y_tr7v7tNhnHE14nFOKg7sTECBZXEKZS75gFl3uXG6LSlzYN_xXc_6zl_ib0EaOOhaC5DxeJ2kszdZFwCqTZoi_FYdEgP2Bi.jJjS4y0EsJHKsZYFo9vtjp9bope2P8TL0NEKNiykogJGtOLWqhcibEQ_0KXY2awb7pz3z4.Qa9t4_WsD28lxMLkkLADCF.bWWgjCKx2v8Sro6iz1jQslT2k5sVthsqwZPwVQhPTfely1T8GUK9qzwKHEzen0T3YahxtCD2s.VHErdXE.nn_2PXIboSwRGt_TN2xdkRPDQ2sUhOJy0mPh3rWG6jIPn.83axVt6BkDAttFUTtZg5CzBmbMuWFzO3IzeBBhnhQMmBXhMlkduoT6gs9ftiNk7_L_uNAq5all9HUWkTgxmhsNCGwjP7DsZvaf9ohMo0GapTgcKoJKeEIT8.9imcCAAnoQ.iy1EOZMhZag6wXqM3DQ82ji3TzK2aIDgEOYTnAe0wWd_1zXVTUPtXtzMA8ChTWq6_BBuUHZ_Os4U7X7yZ04cwrEyU1uv8CBNwIQpHyJfwajpB3Kf8jWIOsvJlDxu2sIRHOXP68jISA0VDIhXRo4NxphVhAlOcRrKxv1n527qcMUVBlyrfwODgQwDPwakNSm8JAnVXb1BiESqCRE.8t_7Wc4lHKgd79guH2LoXHGJvKv3RopuLxvGcPZcZPaNkl3Xjb1RGZIabkW.d4q1sGGy7oY4EFOOxH24geNNW9vb1DpbTIpOMbJVzxD2jcziimPfSeD1ZPfd8AdEdmWpCK9hk2QRzHepVeBTsa5f5in.rTWb2TYbAuoWl.SUj0hhMhTJAtAvfpaHet3_Zf76JFZIEKm8FCqdy.CmpmDr3dDXYND0z18NUaEGQLF.t8foL2r8jFmjpoaFu9QU6btgjS7EATizheDrPKf_Ge6ORvsaELQKn9P7kT0gd43Fdcj7bi58GJtb8EeGYSq6a1QLGMAwykpX8RBz_pYYVYLmvXuyb0FpmW8efH_BGfaaihsiuSeP9.WkJ4yafbcGzvkwMWCuVWINmAYtkrEKrEebn5VqjLm65w44Jp5Hqz6cuKmL7pTF7iQN_vhTMuug4qgp4RJpPw8XivO5aPp4jwrEeVczkg5goOJQ7_mq6kpRy2EStez5p9ciDe2y0TfbWxRZHLMB_EUy7Sqe3nl3zxb6gD2LkuGrOjeWlV1xbhDUn_IzEkGfc8WTn84UgIuae_RQqpv1VOAQx1NK.7Um4DLBh9V9wuobp4mGFUsnuNQY1TuGtGuii84XmoBZ_xcs5J98PCiuHqmWCpNxAWYj8E_x1.XMEnqdqTiZlOSUr0e9WsxmQtkFItTcExPoK_4KJXLvUhh5386Id7UeF1LQ9VMUP67TMN2ZGsYj91Nma64bWzX.yMo9cWx.bU8dQmVP6cJbfgmvngGO.QwfFXbpGLom4fF5Hh1DcbP7uavm8HtBDRrJUwItMK0WqflzkdRBP1o5OAAnYdaCU_MPuHstCp0zE1Pdk4IDQTm_qnl.10Whwke6Gw.lMEsfkbh74DdIg7FJigvXl7VO_dXR.3VNq_5LPmV2axr3By03Eu9BBGWX28QmrBxm1i3PkZUS0huFOUM7UYuqNa6c1serGRPT_jc3KUY.RUowHyslsb0DiFdd1g0stRpsUMJTHbQSQSLAe0WNdRy.vJFLnzKDw2IdoUt4pU9erP_nzcW3ZswtamdXejMrc3A8p8HIE.XU3.cz6AW47Xp.UOWn7_ZhcsH_sW8M83fzg4ISSnaQ0wWMX7kKGRpwAcuIOuk.1ngYbF75f1.fD_ur7Gq9ZInSw2oyg52zhWocJCFoNMJX.QBtqUdDZ3EStfi8RPvKWSVGS41_fm8PSNMUcZt_Elu2CN5782TRwtw9gy17WgaTfJQuDjFIJv6mwf885U9d248f7cGvNbXrVVq45UNdOD7mvw3RK0Ji228X__DSkpyPU9BV56sfIGKoLqZ0KANYjHG.D8WMmKJXyJSohwrp4UYDBY.XOQqECymQWVnEb2gaB4BcE8Brgu5Z1qp0e5ytBVIOGfXKj7T1WAiugnMuLBFrcSyM_MxXw.Mlue1kk9FlUmOUEPbexGjcbbDU0UInBvhNrNIlBda5qZEI4GdP22PS0Atj.6BKaAUu6w4AoJU0gqPwf3YAf2Rymd7a27crGOIzxwdA9VFnYegaxtmCCpMv4nxUQpzkS8AQopZmk..0Q52W3.'",
            "    UNWRAP 'vehicleSpeed' STORE ",
            "    \\$vehicleSpeed 18 GEO.COVER true ->GEOJSON JSON-> 'geoJson' STORE",
            "    { ",
            "      'data' [ \\$geoJson \\$vehicleSpeed ] ",
            "      'params' [ ",
            "        { 'datasetColor' '#0080ff' 'fillColor' '#0000ff'  } // geojson",
            "        { 'color' '#ff1030' ",
            "          //'render' 'marker' 'marker' 'car'                ",
            "          //'render' 'path'   'marker' 'car'",
            "          //'render' 'dots' 'baseRadius' 10",
            "          //'render' 'weightedDots'  'maxValue' 800 'minValue' 0 'borderColor' '#ffC000'    ",
            "          //'line' false // remove line that connect the dots",
            "          //'key' 'new data name to show'",
            "          //'map' { 'heatmap' true 'heatRadius' 10 'heatOpacity' 0.5 }  ",
            "        } ",
            "      ]",
            "      'globalParams' { ",
            "        'map' { ",
            "          'mapType' 'SATELLITE' // map style NONE, DEFAULT, HOT, TOPO, TOPO2, STADIA, STADIA_DARK, TONER, TONER_LITE, TERRAIN, ESRI, SATELLITE, OCEANS, GRAY, GRAYSCALE, WATERCOLOR, CARTODB, CARTODB_DARK",
            "          'tiles' [ // extra tile servers to overlay on the map",
            "            'https://tiles.openseamap.org/seamark/{z}/{x}/{y}.png' ",
            "          ]",
            "          // 'startLat' 37.4",
            "          // 'startLong' -3.0",
            "          // 'startZoom' 5  // can be restricted with 'maxZoom' 'maxNativeZoom' ",
            "        } ",
            "      } ",
            "    }",
            "  %>",
            "}"
        ]
    },
    "dtile11": {
        "prefix": "discovery-tile 11 input:button",
        "description": "Discovery within WarpScript",
        "body": [
            "{",
            "  'type' 'button' 'w' 1 'h' 1",
            "  'title' 'apply'",
            "  'macro' <%",
            "    { ",
            "      // when loaded, a button returns a macro to execute on each click",
            "      // this macro is not aware of the dashboard variables (unless the button tile suscribe to the variable events)",
            "      // 'options' { 'eventHandler' 'tag=input,type=variable'  }",
            "      // In this example, the button just send an event with an empty list of variable",
            "      // tiles listening it to will refresh ( 'eventHandler' 'type=variable,tag=(input|${1:applybutton})' in the tile options)",
            "      'data' <%",
            "        {",
            "          'events' [ { 'tags' [ '${1:applybutton}' ] 'type' 'variable' 'value' {} } ]",
            "        }",
            "      %>",
            "      'globalParams' { 'button' { 'label' 'Apply' } } ",
            "    }",
            "  %>",
            "}"
        ]
    },
    "dtile12": {
        "prefix": "discovery-tile 12 input:text",
        "description": "Discovery within WarpScript",
        "body": [
            "{",
            "  'type' 'input:text' 'w' 2 'h' 1  // or 'input:secret' for sensitive information",
            "  'title' 'Enter text'",
            "  'options' { 'input' { 'showButton' true } }",
            "  'macro' <% {",
            "    // If showButton is false, the event is sent at each letter you type in the input field",
            "    // If showButton is true, the event is sent when the user click the OK button",
            "    'events' [ { 'tags' 'input' 'type' 'variable' 'selector' 'inputText01' } ]",
            "    'data' '${1:Default Value}'  // you must define  'inputText01' '${1:Default Value}'  into dashboard 'vars' too.",
            "  } %>",
            "}"
        ]
    },
    "dtile13": {
        "prefix": "discovery-tile 13 input:list or autocomplete",
        "description": "Discovery within WarpScript",
        "body": [
            "{",
            "  'type' 'input:list' 'w' 1 'h' 1   // try input:autocomplete if the choice list is too big",
            "  'title' 'Select classname'",
            "  'macro' <% {",
            "    'events' [ { 'tags' 'input' 'type' 'variable' 'selector' '${1:channelName}' } ]",
            "    'globalParams' { 'input' { 'value' 'pressure' } } // you must define  '${1:channelName}' '${2:pressure}'  into dashboard 'vars' too.",
            "    // when refering to a variable defined outside the tile macro and not in dashboard vars,",
            "    // use early binding:  !\\$xxx  will replace the variable by its content during the first execution.",
            "    'data' [ 'temperature' 'pressure' 'flow' ]",
            "  } %>",
            "}"
        ]
    },
    "dtile14": {
        "prefix": "discovery-tile 14 input:checkboxes",
        "description": "Discovery within WarpScript",
        "body": [
            "{",
            "  'type' 'input:multi-cb' 'w' 2 'h' 2   // try input:autocomplete if the choice list is too big",
            "  'title' 'Select sensors'",
            "  'options' { 'input' { 'showButton' true 'showFilter' true } }",
            "  'macro' <% {",
            "    'events' [ { 'tags' 'input' 'type' 'variable' 'selector' '${1:checkBoxList}' } ]",
            "    'globalParams' { 'input' { 'value' ${2:[ 'sensor 1' 'sensor 3' ]} } } // you must define  '${1:checkBoxList}' ${2:[ 'sensor 1' 'sensor 3' ]} into dashboard 'vars' too.",
            "    // when refering to a variable defined outside the tile macro and not in dashboard vars,",
            "    // use early binding:  !\\$xxx  will replace the variable by its content during the first execution.",
            "    'data' [ 1 100 <% TOSTRING 'sensor ' SWAP + %> FOR ]",
            "  } %>",
            "}"
        ]
    },
    "dtile15": {
        "prefix": "discovery-tile 15 input:slider",
        "description": "Discovery within WarpScript",
        "body": [
            "{",
            "  'type' 'input:slider' 'w' 2 'h' 1   // try input:autocomplete if the choice list is too big",
            "  'title' 'Trigger Value'",
            "  'options' { 'input' { 'showButton' true } } // when false, event is sent when click is released",
            "  'macro' <% {",
            "    'data' ${1:42.5}  // default value",
            "    'globalParams' { 'input' { 'min' -10 'max' 50 'step' 0.5 } }",
            "    'events' [ { 'tags' 'input' 'type' 'variable' 'selector' '${2:triggerValue}' } ]",
            "      // you must define  '${2:triggerValue}' ${1:42.5} into dashboard 'vars' too.",
            "  } %>",
            "}"
        ]
    },
    "dtile16": {
        "prefix": "discovery-tile 16 input:radio",
        "description": "Discovery within WarpScript",
        "body": [
            "{",
            "  'type' 'button:radio'",
            "  'x' 0 'y' 0 'w' 12 'h' 1",
            "  'macro' <%",
            "    {",
            "      // you must define  '${1:period}' '1 w' // default = week",
            "      // into dashboard 'vars' too.",
            "      'data'  [",
            "        { 'label' 'Hour'  'value' '1 h'    'active' \\$${1:period} '1 h' ==   }",
            "        { 'label' 'Day'   'value' '1 d'    'active' \\$${1:period} '1 d' ==   }",
            "        { 'label' 'Week'  'value' '1 w'    'active' \\$${1:period} '1 w' ==   }",
            "        { 'label' 'Month' 'value' '31 d'   'active' \\$${1:period} '31 d' ==  }",
            "        { 'label' 'Year'  'value' '365 d'  'active' \\$${1:period} '365 d' == }",
            "        // In this example, as the value is valid WarpScript, you can evaluate directly the result with \\$period EVAL in the tiles listening to this event.",
            "      ]",
            "      'events' [ { 'type' 'variable' 'tags' 'input' 'selector' '${1:period}' } ]",
            "    }",
            "  %>",
            "}"
        ]
    },
    "devent01": {
        "prefix": "discovery-event 01 popup",
        "description": "Discovery within WarpScript",
        "body": [
            "{ ",
            "  // This event will send an event to the dashbard itself. At the dashboard level, you must suscribe the event by adding:",
            "  // 'options' { 'eventHandler' 'type=popup,tag=dashboard' }",
            "  'tags' [ 'dashboard' ] ",
            "  'type' 'popup'",
            "  'value' ${1:insert a discovery tile here, or a full dashboard structure with several tiles}",
            "}"
        ]
    },
    "devent02": {
        "prefix": "discovery-event 02 variable",
        "description": "Discovery within WarpScript",
        "body": [
            "// this event will force some variables to be updated in all the tiles that suscribe to it",
            "{ 'tags' [ 'input' ] 'type' 'variable' 'value' { '{1:a}' \\${1:a} } } // make sure '{1:a}' is declared in the 'vars' of your dashboard",
            ""
        ]
    }
}
