[
  {
    "id": "nkb0000000tab001",
    "type": "tab",
    "label": "React to what comes next",
    "disabled": false,
    "info": "The same section can mean different things depending on what comes NEXT.\nEvery stream message tells you: this flow dims the lights during a Drive\nBreak that resolves back into a Drive, but lifts them when the break leads\ninto a Build.\n\nHOW IT WORKS\n- The Drive Break node's STREAM output (bottom) carries lookahead fields on\n  every message: nextKeypoint, previousKeypoint, and the group/family\n  versions (nextKeypointGroup, nextKeypointFamily).\n- Two function nodes split the stream on msg.payload.nextKeypoint:\n  'drive' goes one way, 'build' the other. Anything else is dropped.\n- Each branch has its own Progress node with its own curve:\n  - next is DRIVE: start at 100%, duck to 25% for most of the break, return\n    to 100% right before the Drive comes back. The room breathes, then\n    snaps back.\n  - next is BUILD: rise from 25% to 100% across the break, handing over to\n    the Build already lifting.\n- Each branch sends its value via OSC and shows a progress bar in the\n  Automations view.\n\nTHE LOOKAHEAD FIELDS\nAvailable on stream payloads AND on enter/exit event payloads, so the same\ntrick works for one-shot cues (keypoint node -> Enter -> function -> output):\n- nextKeypoint / previousKeypoint - e.g. 'drive', 'build', 'drop'\n- nextKeypointGroup / nextKeypointFamily - the zoomed-out versions\n\nSETUP\nDouble-click an OSC output node, then the pencil next to 'Server'. This\nexample points at 127.0.0.1:8000 - run Protokol (free OSC monitor by\nHexler) on this machine to watch the values, or aim it at your console and\nchange the addresses.\n\nTESTING\nClick the test buttons to simulate the stream: one pretends the next\nsection is a Drive, one pretends it is a Build, one sits at 95% progress so\nyou can see the dip curve returning to full.\n",
    "env": []
  },
  {
    "id": "nkb0000000grp001",
    "type": "group",
    "z": "nkb0000000tab001",
    "name": "Branch on the NEXT keypoint",
    "style": {
      "label": true
    },
    "nodes": [
      "nkb0000000key001",
      "nkb0000000fna001",
      "nkb0000000fnb001",
      "nkb0000000prg001",
      "nkb0000000prg002",
      "nkb0000000out001",
      "nkb0000000out002",
      "nkb0000000dbg001"
    ],
    "x": 54,
    "y": 59,
    "w": 952,
    "h": 262
  },
  {
    "id": "nkb0000000grp002",
    "type": "group",
    "z": "nkb0000000tab001",
    "name": "No deck playing? Test with these",
    "style": {
      "label": true
    },
    "nodes": [
      "nkb0000000inj001",
      "nkb0000000inj002",
      "nkb0000000inj003"
    ],
    "x": 54,
    "y": 359,
    "w": 322,
    "h": 202
  },
  {
    "id": "nkb0000000key001",
    "type": "tl-keypoint-drive-break",
    "z": "nkb0000000tab001",
    "g": "nkb0000000grp001",
    "x": 170,
    "y": 200,
    "wires": [
      [],
      [
        "nkb0000000fna001",
        "nkb0000000fnb001"
      ]
    ]
  },
  {
    "id": "nkb0000000fna001",
    "type": "function",
    "z": "nkb0000000tab001",
    "g": "nkb0000000grp001",
    "name": "If next is drive",
    "func": "// The stream payload always tells you what's coming next.\nif (msg.payload.nextKeypoint === 'drive') {\n    return msg;\n}\nreturn null;",
    "outputs": 1,
    "timeout": 0,
    "noerr": 0,
    "initialize": "",
    "finalize": "",
    "libs": [],
    "x": 400,
    "y": 160,
    "wires": [
      [
        "nkb0000000prg001"
      ]
    ]
  },
  {
    "id": "nkb0000000fnb001",
    "type": "function",
    "z": "nkb0000000tab001",
    "g": "nkb0000000grp001",
    "name": "If next is build",
    "func": "if (msg.payload.nextKeypoint === 'build') {\n    return msg;\n}\nreturn null;",
    "outputs": 1,
    "timeout": 0,
    "noerr": 0,
    "initialize": "",
    "finalize": "",
    "libs": [],
    "x": 400,
    "y": 260,
    "wires": [
      [
        "nkb0000000prg002"
      ]
    ]
  },
  {
    "id": "nkb0000000prg001",
    "type": "tl-progress",
    "z": "nkb0000000tab001",
    "g": "nkb0000000grp001",
    "progressType": "keypoint",
    "windowMode": "full",
    "seconds": "5",
    "bars": "2",
    "outputMin": "0",
    "outputMax": "1",
    "curvePoints": "[{\"x\":0,\"y\":1},{\"x\":0.1,\"y\":0.25},{\"x\":0.9,\"y\":0.25},{\"x\":1,\"y\":1}]",
    "curveSegments": "{}",
    "onlyWhilePlaying": false,
    "x": 610,
    "y": 160,
    "wires": [
      [
        "nkb0000000out001",
        "nkb0000000dbg001"
      ]
    ]
  },
  {
    "id": "nkb0000000prg002",
    "type": "tl-progress",
    "z": "nkb0000000tab001",
    "g": "nkb0000000grp001",
    "progressType": "keypoint",
    "windowMode": "full",
    "seconds": "5",
    "bars": "2",
    "outputMin": "0",
    "outputMax": "1",
    "curvePoints": "[{\"x\":0,\"y\":0.25},{\"x\":1,\"y\":1}]",
    "curveSegments": "{}",
    "onlyWhilePlaying": false,
    "x": 610,
    "y": 260,
    "wires": [
      [
        "nkb0000000out002",
        "nkb0000000dbg001"
      ]
    ]
  },
  {
    "id": "nkb0000000out001",
    "type": "tl-output",
    "z": "nkb0000000tab001",
    "g": "nkb0000000grp001",
    "name": "Dim during break",
    "protocol": "osc",
    "server": "nkb0000000srv001",
    "address": "/time-line/break-dim",
    "message": "",
    "vizType": "progress",
    "textSuffix": "",
    "progressMin": 0,
    "progressMax": 1,
    "progressStartLabel": "",
    "progressEndLabel": "",
    "x": 850,
    "y": 160,
    "wires": []
  },
  {
    "id": "nkb0000000out002",
    "type": "tl-output",
    "z": "nkb0000000tab001",
    "g": "nkb0000000grp001",
    "name": "Rise into build",
    "protocol": "osc",
    "server": "nkb0000000srv001",
    "address": "/time-line/break-rise",
    "message": "",
    "vizType": "progress",
    "textSuffix": "",
    "progressMin": 0,
    "progressMax": 1,
    "progressStartLabel": "",
    "progressEndLabel": "",
    "x": 840,
    "y": 260,
    "wires": []
  },
  {
    "id": "nkb0000000dbg001",
    "type": "debug",
    "z": "nkb0000000tab001",
    "g": "nkb0000000grp001",
    "name": "value sent",
    "active": true,
    "tosidebar": true,
    "console": false,
    "tostatus": false,
    "complete": "payload",
    "targetType": "msg",
    "statusVal": "",
    "statusType": "auto",
    "x": 840,
    "y": 100,
    "wires": []
  },
  {
    "id": "nkb0000000inj001",
    "type": "inject",
    "z": "nkb0000000tab001",
    "g": "nkb0000000grp002",
    "name": "test: next is drive (50%)",
    "props": [
      {
        "p": "payload"
      }
    ],
    "repeat": "",
    "crontab": "",
    "once": false,
    "onceDelay": 0.1,
    "topic": "",
    "payload": "{\"nextKeypoint\":\"drive\",\"currentKeypointProgress\":0.5}",
    "payloadType": "json",
    "x": 200,
    "y": 400,
    "wires": [
      [
        "nkb0000000fna001",
        "nkb0000000fnb001"
      ]
    ]
  },
  {
    "id": "nkb0000000inj002",
    "type": "inject",
    "z": "nkb0000000tab001",
    "g": "nkb0000000grp002",
    "name": "test: next is drive (95%)",
    "props": [
      {
        "p": "payload"
      }
    ],
    "repeat": "",
    "crontab": "",
    "once": false,
    "onceDelay": 0.1,
    "topic": "",
    "payload": "{\"nextKeypoint\":\"drive\",\"currentKeypointProgress\":0.95}",
    "payloadType": "json",
    "x": 200,
    "y": 460,
    "wires": [
      [
        "nkb0000000fna001",
        "nkb0000000fnb001"
      ]
    ]
  },
  {
    "id": "nkb0000000inj003",
    "type": "inject",
    "z": "nkb0000000tab001",
    "g": "nkb0000000grp002",
    "name": "test: next is build (50%)",
    "props": [
      {
        "p": "payload"
      }
    ],
    "repeat": "",
    "crontab": "",
    "once": false,
    "onceDelay": 0.1,
    "topic": "",
    "payload": "{\"nextKeypoint\":\"build\",\"currentKeypointProgress\":0.5}",
    "payloadType": "json",
    "x": 200,
    "y": 520,
    "wires": [
      [
        "nkb0000000fna001",
        "nkb0000000fnb001"
      ]
    ]
  },
  {
    "id": "nkb0000000srv001",
    "type": "tl-output-server",
    "name": "Protokol",
    "protocol": "osc",
    "host": "127.0.0.1",
    "port": 8000,
    "udpFamily": "udp4"
  }
]
