[
  {
    "path": ".github/FUNDING.yml",
    "content": "github: dastergon\n"
  },
  {
    "path": ".github/workflows/deploy_to_gh_pages.yml",
    "content": "name: Deploy Wheel of Misfortune to GitHub Pages\n\non:\n  push:\n    branches:\n      - master\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - name: Copy needed files and dirs into the public/ directory\n        run: |\n          mkdir -p public/incidents\n          for source in *.html static; do cp -r $source public/; done\n          ls incidents/ | while read i; do cp incidents/$i public/incidents/${i/.sample/}; done\n      - uses: crazy-max/ghaction-github-pages@v2\n        with:\n          commit_message: Deploy from ${{ github.ref }}@${{ github.sha }}\n          build_dir: public\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": "incidents/*.json\nincidents/*.jsonnet\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2018 Pavlos Ratis\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 all\ncopies 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 THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Wheel of Misfortune\n**Wheel of Misfortune** is a game that aims to build confidence in on-call engineers via simulated outage scenarios.\nWith the game, you practice problem debugging under stress, understanding the incident management protocol,\nand effective communication with other engineers of your team and organization.\nIt is a great way to train new hires, interns, and seasoned engineers to become well-rounded on-call engineers.\n\nThe game is inspired by the [Site Reliability Engineering](https://landing.google.com/sre/book/chapters/accelerating-sre-on-call.html#xref_training_disaster-rpg) book.\n\n[Demo website](https://dastergon.gr/wheel-of-misfortune)\n\n## Instructions\n### Terminology\n\n*   **Scenario**: A past or fictional incident case.\n*   **Game Master**: The host-coordinator of the session.\n*   **Volunteer**: The trainee on-call engineer.\n\nFeel free to fork the [repository](https://github.com/dastergon/wheel-of-misfortune) or [download](https://github.com/dastergon/wheel-of-misfortune/releases) the stable release.\nCopy the [general\\_incidents.json.sample](incidents/general\\_incidents.json.sample) file to *general_incidents.json*, inside the [incidents/](incidents/) directory, and insert your incident scenarios into it.\n\nTo run the game locally on your computer please navigate the the main directory of the downloaded project i.e. `wheel-of-misfortune-5.0/` and from here start a web server i.e. `python -m SimpleHTTPServer` after that open the http://localhost:8000 using your web browser.\n\nThe file has the following format:\n- **ID**: the unique ID of the outage (you can just auto-increment).\n- **title**: the title of the incident.\n- **scenario**: the description of the incident. It is useful to include URLs from monitoring systems, dashboards, time-series databases and playbooks.\n- **inkstory**: the path to an [Ink](https://www.inklestudios.com/ink/) story file in JSON format.\n\nYou can also use [general\\_incidents.jsonnet](incidents/general_incidents.jsonnet.sample) as an example, in case you want to generate your incident scenarios using [Jsonnet](https://jsonnet.org/).\n\n### Ink\n[Ink](https://github.com/inkle/ink) is a scripting language for writing interactive narrative stories. It enables us to write interactive incident response narratives for team or individual trainings. You can use [Inky](https://github.com/inkle/inky) to write an interactive narrative for an incident and then export the story as JSON. Then, you can store the story file inside the [incidents/](incidents/) folder and associate the Ink story file with an Incident scenario using the **inkstory** key. You can read an example incident narrative [here](https://github.com/dastergon/wheel-of-misfortune/tree/master/incidents/redis-story.json).\n\n### Role Playing\n#### Game Master\n\n1.  Choose a volunteer to be the primary on-call engineer in front of the group.\n2.  Find a balance between the volunteer's experience and the incident's difficulty.\n3.  Assist volunteer by answering questions that may arise in each theoretical action or dashboard observation.\n  * Engage with the rest of the team and ask for different ways to debug the problem following the volunteer's explanation.\n  * Team members may be made available over time for assistance in various topics.\n5.  At the end, have a debrief on the learnings of the session.\n\n\n#### Volunteer\n\n1.  Spin the wheel and attempt to fix the theoretical outage scenario.\n2.  Explain to the Game Master and the rest of the group what actions you would take (lookup queries, checks in dashboards, etc.) to find the root causes, and eventually solve the incident.\n3.  Always keep an eye on the time, since it is a simulated incident response scenario and not a routine troubleshooting process. During a real incident, you might have an SLA or SLO breach and therefore you should take timing into account.\n4.  Engage with the rest of the group. Keep them in the loop. Ask questions to different members depending on their expertise.\n\nMost importantly, **have fun!**\n\nYou can [read](https://landing.google.com/sre/book/chapters/accelerating-sre-on-call.html#xref_training_disaster-rpg) a comprehensive example on how to conduct the exercise in the Google SRE book.\n\n### Featured\n\nThe Wheel of Misfortune was established as a practice in [Open Practice Library](https://openpracticelibrary.com/) and this project was [featured](https://openpracticelibrary.com/practice/wheel-of-misfortune/) there.\n\n### Resources\n\n*   [Disaster Role Playing](https://landing.google.com/sre/book/chapters/accelerating-sre-on-call.html#xref_training_disaster-rpg)\n*   [Managing Misfortune for Best Results](https://www.usenix.org/conference/srecon18europe/presentation/barry)\n*   [Postmortem Culture: Learning from Failure](https://landing.google.com/sre/book/chapters/postmortem-culture.html)\n*   [Postmortem Templates](https://github.com/dastergon/postmortem-templates)\n*   [Postmortems Metadata Index](https://postmortems.app)\n*   [Site Reliability Engineering Resources](https://github.com/dastergon/awesome-sre)\n"
  },
  {
    "path": "incidents/general_incidents.json.sample",
    "content": "[\n    {\n        \"ID\": \"1\",\n        \"title\": \"Incident 1\",\n        \"scenario\": \"You received alerts that your MySQL master does not accept writes...\"\n    },\n    {\n        \"ID\": \"2\",\n        \"title\": \"Incident 2\",\n        \"scenario\": \"You've received alerts that your load balancer is down...\"\n    },\n    {\n        \"ID\": \"3\",\n        \"title\": \"Incident 3\",\n        \"scenario\": \"You've received an alert that your Blob storage system is unable to store objects...\"\n    },\n    {\n        \"ID\": \"4\",\n        \"title\": \"Incident 4\",\n        \"scenario\": \"You've received alerts that your DC eu-west-1 has a power outage...\"\n    },\n    {\n        \"ID\": \"5\",\n        \"title\": \"Incident 5\",\n        \"inkstory\": \"incidents/redis-story.json\",\n        \"scenario\": \"You've received an alert that your Redis server is killed...\"\n    },\n    {\n        \"ID\": \"6\",\n        \"title\": \"Incident 6\",\n        \"scenario\": \"You've received alerts of high HTTP 5xx error rate...\"\n    },\n    {\n        \"ID\": \"7\",\n        \"title\": \"Incident 7\",\n        \"scenario\": \"You've received alerts that there is high query latency in the RPC servers...\"\n    },\n    {\n        \"ID\": \"8\",\n        \"title\": \"Incident 8\",\n        \"scenario\": \"You've received an alert that an LDAP client cannot query LDAP server\"\n    }\n]\n"
  },
  {
    "path": "incidents/general_incidents.jsonnet.sample",
    "content": "local incidents = [\n  { scenario: \"You've received an alert that your \" + database + ' server is killed...' }\n  for database in [\n    'Redis',\n    'MySQL',\n    'MongoDB',\n  ]\n] + [\n  // Generates DC is down incidents\n  { scenario: \"You've received alerts that your DC \" + dc + ' has a power outage...' }\n  for dc in [\n    'eu-west-1',\n    'eu-north-1',\n    'us-east-2',\n  ]\n] + [\n  // Static incidents\n  {\n    scenario: 'You received alerts that your MySQL master does not accept writes...',\n  },\n  {\n    scenario: \"You've received alerts that your load balancer is down...\",\n  },\n  {\n    scenario: \"You've received an alert that your Blob storage system is unable to store objects...\",\n  },\n  {\n    scenario: \"You've received an alert that your Redis server is killed...\",\n  },\n  {\n    scenario: \"You've received alerts of high HTTP 5xx error rate...\",\n  },\n  {\n    scenario: \"You've received alerts that there is high query latency in the RPC servers...\",\n  },\n  {\n    scenario: \"You've received an alert that an LDAP client cannot query LDAP server\",\n  },\n];\n\n# Generates incident title and id\n[incidents[i] { id: '%d' % [i + 1], title: 'Incident %d' % [i + 1] } for i in std.range(0, std.length(incidents) - 1)]\n"
  },
  {
    "path": "incidents/redis-story.json.sample",
    "content": "﻿{\"inkVersion\":19,\"root\":[[[\"^You've received an alert that your Redis server is killed...\",\"\\n\",[\"ev\",{\"^->\":\"0.g-0.2.$r1\"},{\"temp=\":\"$r\"},\"str\",{\"->\":\".^.s\"},[{\"#n\":\"$r1\"}],\"/str\",\"/ev\",{\"*\":\".^.^.c-0\",\"flg\":18},{\"s\":[\"^Acknowledge the alert\",{\"->\":\"$r\",\"var\":true},null]}],\"ev\",\"str\",\"^Wait for the incident to autoresolve\",\"/str\",\"/ev\",{\"*\":\".^.c-1\",\"flg\":4},\"ev\",\"str\",\"^Do Nothing\",\"/str\",\"/ev\",{\"*\":\".^.c-2\",\"flg\":4},{\"c-0\":[\"ev\",{\"^->\":\"0.g-0.c-0.$r2\"},\"/ev\",{\"temp=\":\"$r\"},{\"->\":\".^.^.2.s\"},[{\"#n\":\"$r2\"}],\"\\n\",\"^How do you proceed?\",\"\\n\",[[\"ev\",{\"^->\":\"0.g-0.c-0.9.0.$r1\"},{\"temp=\":\"$r\"},\"str\",{\"->\":\".^.s\"},[{\"#n\":\"$r1\"}],\"/str\",\"/ev\",{\"*\":\".^.^.c-0\",\"flg\":18},{\"s\":[\"^Restart the service\",{\"->\":\"$r\",\"var\":true},null]}],[\"ev\",{\"^->\":\"0.g-0.c-0.9.1.$r1\"},{\"temp=\":\"$r\"},\"str\",{\"->\":\".^.s\"},[{\"#n\":\"$r1\"}],\"/str\",\"/ev\",{\"*\":\".^.^.c-1\",\"flg\":18},{\"s\":[\"^Check Grafana \",{\"->\":\"$r\",\"var\":true},null]}],{\"c-0\":[\"ev\",{\"^->\":\"0.g-0.c-0.9.c-0.$r2\"},\"/ev\",{\"temp=\":\"$r\"},{\"->\":\".^.^.0.s\"},[{\"#n\":\"$r2\"}],\"\\n\",\"^\\\"It looks like the restart didn't help the situation\\\"\",\"\\n\",[[\"^And now, what?\",\"\\n\",[\"ev\",{\"^->\":\"0.g-0.c-0.9.c-0.9.g-0.2.$r1\"},{\"temp=\":\"$r\"},\"str\",{\"->\":\".^.s\"},[{\"#n\":\"$r1\"}],\"/str\",\"/ev\",{\"*\":\".^.^.c-0\",\"flg\":18},{\"s\":[\"^Restart again\",{\"->\":\"$r\",\"var\":true},null]}],[\"ev\",{\"^->\":\"0.g-0.c-0.9.c-0.9.g-0.3.$r1\"},{\"temp=\":\"$r\"},\"str\",{\"->\":\".^.s\"},[{\"#n\":\"$r1\"}],\"/str\",\"/ev\",{\"*\":\".^.^.c-1\",\"flg\":18},{\"s\":[\"^Scale out\",{\"->\":\"$r\",\"var\":true},null]}],{\"c-0\":[\"ev\",{\"^->\":\"0.g-0.c-0.9.c-0.9.g-0.c-0.$r2\"},\"/ev\",{\"temp=\":\"$r\"},{\"->\":\".^.^.2.s\"},[{\"#n\":\"$r2\"}],\"\\n\",{\"->\":\".^.^.^.g-1\"},{\"#f\":5}],\"c-1\":[\"ev\",{\"^->\":\"0.g-0.c-0.9.c-0.9.g-0.c-1.$r2\"},\"/ev\",{\"temp=\":\"$r\"},{\"->\":\".^.^.3.s\"},[{\"#n\":\"$r2\"}],\"\\n\",{\"->\":\".^.^.^.g-1\"},{\"#f\":5}],\"#f\":5,\"#n\":\"g-0\"}],{\"g-1\":[\"^\\\"It seems that the alert is not getting resolved\\\"\",\"\\n\",[\"ev\",{\"^->\":\"0.g-0.c-0.9.c-0.9.g-1.2.$r1\"},{\"temp=\":\"$r\"},\"str\",{\"->\":\".^.s\"},[{\"#n\":\"$r1\"}],\"/str\",\"/ev\",{\"*\":\".^.^.c-2\",\"flg\":18},{\"s\":[\"^Check Dashboard for service X\",{\"->\":\"$r\",\"var\":true},null]}],[\"ev\",{\"^->\":\"0.g-0.c-0.9.c-0.9.g-1.3.$r1\"},{\"temp=\":\"$r\"},\"str\",{\"->\":\".^.s\"},[{\"#n\":\"$r1\"}],\"/str\",\"/ev\",{\"*\":\".^.^.c-3\",\"flg\":18},{\"s\":[\"^Check Dashboard for service Y\",{\"->\":\"$r\",\"var\":true},null]}],{\"c-2\":[\"ev\",{\"^->\":\"0.g-0.c-0.9.c-0.9.g-1.c-2.$r2\"},\"/ev\",{\"temp=\":\"$r\"},{\"->\":\".^.^.2.s\"},[{\"#n\":\"$r2\"}],\"\\n\",\"^\\\"There's the URL for service X\\\" \",{\"->\":\"inspect\"},\"\\n\",{\"->\":\"0.g-1\"},{\"#f\":5}],\"c-3\":[\"ev\",{\"^->\":\"0.g-0.c-0.9.c-0.9.g-1.c-3.$r2\"},\"/ev\",{\"temp=\":\"$r\"},{\"->\":\".^.^.3.s\"},[{\"#n\":\"$r2\"}],\"\\n\",\"^\\\"There's the URL for service Y\\\" \",{\"->\":\"inspect\"},\"\\n\",{\"->\":\"0.g-1\"},{\"#f\":5}],\"#f\":5}]}],{\"#f\":5}],\"c-1\":[\"ev\",{\"^->\":\"0.g-0.c-0.9.c-1.$r2\"},\"/ev\",{\"temp=\":\"$r\"},{\"->\":\".^.^.1.s\"},[{\"#n\":\"$r2\"}],{\"->\":\"grafana\"},\"\\n\",{\"->\":\"0.g-1\"},{\"#f\":5}]}],{\"#f\":5}],\"c-1\":[\"^ \",{\"->\":\"chill\"},\"\\n\",{\"->\":\"0.g-1\"},{\"#f\":5}],\"c-2\":[\"^ \",{\"->\":\"chill\"},\"\\n\",{\"->\":\"0.g-1\"},{\"#f\":5}],\"#f\":5,\"#n\":\"g-0\"}],{\"g-1\":[\"end\",[\"done\",{\"#f\":5,\"#n\":\"g-2\"}],{\"#f\":5}]}],\"done\",{\"grafana\":[\"^There's the dashboard for Redis:  URL \",{\"->\":\"inspect\"},\"\\n\",{\"#f\":1}],\"inspect\":[[[\"^Do you see anything suspicious?\",\"\\n\",[[\"ev\",{\"^->\":\"inspect.0.g-0.2.0.$r1\"},{\"temp=\":\"$r\"},\"str\",{\"->\":\".^.s\"},[{\"#n\":\"$r1\"}],\"/str\",\"/ev\",{\"*\":\".^.^.c-0\",\"flg\":18},{\"s\":[\"^Nope \",{\"->\":\"$r\",\"var\":true},null]}],[\"ev\",{\"^->\":\"inspect.0.g-0.2.1.$r1\"},{\"temp=\":\"$r\"},\"str\",{\"->\":\".^.s\"},[{\"#n\":\"$r1\"}],\"/str\",\"/ev\",{\"*\":\".^.^.c-1\",\"flg\":18},{\"s\":[\"^Too many open connections\",{\"->\":\"$r\",\"var\":true},null]}],[\"ev\",{\"^->\":\"inspect.0.g-0.2.2.$r1\"},{\"temp=\":\"$r\"},\"str\",{\"->\":\".^.s\"},[{\"#n\":\"$r1\"}],\"/str\",\"/ev\",{\"*\":\".^.^.c-2\",\"flg\":18},{\"s\":[\"^System is running out of memory\",{\"->\":\"$r\",\"var\":true},null]}],{\"c-0\":[\"ev\",{\"^->\":\"inspect.0.g-0.2.c-0.$r2\"},\"/ev\",{\"temp=\":\"$r\"},{\"->\":\".^.^.0.s\"},[{\"#n\":\"$r2\"}],{\"->\":\"grafana\"},\"\\n\",{\"->\":\".^.^.g-0\"},{\"#f\":5}],\"c-1\":[\"ev\",{\"^->\":\"inspect.0.g-0.2.c-1.$r2\"},\"/ev\",{\"temp=\":\"$r\"},{\"->\":\".^.^.1.s\"},[{\"#n\":\"$r2\"}],\"\\n\",{\"->\":\".^.^.g-0\"},{\"#f\":5}],\"c-2\":[\"ev\",{\"^->\":\"inspect.0.g-0.2.c-2.$r2\"},\"/ev\",{\"temp=\":\"$r\"},{\"->\":\".^.^.2.s\"},[{\"#n\":\"$r2\"}],\"\\n\",{\"->\":\".^.^.g-0\"},{\"#f\":5}],\"g-0\":[\"^And now what?\",\"\\n\",[\"ev\",{\"^->\":\"inspect.0.g-0.2.g-0.2.$r1\"},{\"temp=\":\"$r\"},\"str\",{\"->\":\".^.s\"},[{\"#n\":\"$r1\"}],\"/str\",\"/ev\",{\"*\":\".^.^.c-3\",\"flg\":18},{\"s\":[\"^Restart the service\",{\"->\":\"$r\",\"var\":true},null]}],[\"ev\",{\"^->\":\"inspect.0.g-0.2.g-0.3.$r1\"},{\"temp=\":\"$r\"},\"str\",{\"->\":\".^.s\"},[{\"#n\":\"$r1\"}],\"/str\",\"/ev\",{\"*\":\".^.^.c-4\",\"flg\":18},{\"s\":[\"^Restart service X (that connects to Redis) \",{\"->\":\"$r\",\"var\":true},null]}],[\"ev\",{\"^->\":\"inspect.0.g-0.2.g-0.4.$r1\"},{\"temp=\":\"$r\"},\"str\",{\"->\":\".^.s\"},[{\"#n\":\"$r1\"}],\"/str\",\"/ev\",{\"*\":\".^.^.c-5\",\"flg\":18},{\"s\":[\"^Call your secondary to ask for help \",\"<>\",\"^ \",{\"->\":\"$r\",\"var\":true},null]}],[\"ev\",{\"^->\":\"inspect.0.g-0.2.g-0.5.$r1\"},{\"temp=\":\"$r\"},\"str\",{\"->\":\".^.s\"},[{\"#n\":\"$r1\"}],\"/str\",\"/ev\",{\"*\":\".^.^.c-6\",\"flg\":18},{\"s\":[\"^Call your boss \",{\"->\":\"$r\",\"var\":true},null]}],{\"c-3\":[\"ev\",{\"^->\":\"inspect.0.g-0.2.g-0.c-3.$r2\"},\"/ev\",{\"temp=\":\"$r\"},{\"->\":\".^.^.2.s\"},[{\"#n\":\"$r2\"}],\"\\n\",\"^\\\"It looks like the restart didn't help the situation\\\" \",{\"->\":\"grafana\"},\"\\n\",{\"#f\":5}],\"c-4\":[\"ev\",{\"^->\":\"inspect.0.g-0.2.g-0.c-4.$r2\"},\"/ev\",{\"temp=\":\"$r\"},{\"->\":\".^.^.3.s\"},[{\"#n\":\"$r2\"}],\"\\n\",\"^\\\" \",{\"->\":\"resolve\"},\"\\n\",{\"#f\":5}],\"c-5\":[\"ev\",{\"^->\":\"inspect.0.g-0.2.g-0.c-5.$r2\"},\"/ev\",{\"temp=\":\"$r\"},{\"->\":\".^.^.4.s\"},[{\"#n\":\"$r2\"}],{\"->\":\"chill\"},\"\\n\",{\"#f\":5}],\"c-6\":[\"ev\",{\"^->\":\"inspect.0.g-0.2.g-0.c-6.$r2\"},\"/ev\",{\"temp=\":\"$r\"},{\"->\":\".^.^.5.s\"},[{\"#n\":\"$r2\"}],{\"->\":\"escalate\"},\"\\n\",{\"#f\":5}],\"#f\":5}]}],{\"#f\":5,\"#n\":\"g-0\"}],null],{\"#f\":1}],\"resolve\":[[\"^\\\"Congrats, the Redis started to get back to normal\\\"\",\"\\n\",\"^How do you proceed?\",\"\\n\",[\"ev\",{\"^->\":\"resolve.0.4.$r1\"},{\"temp=\":\"$r\"},\"str\",{\"->\":\".^.s\"},[{\"#n\":\"$r1\"}],\"/str\",\"/ev\",{\"*\":\".^.^.c-0\",\"flg\":18},{\"s\":[\"^Did you forget to open a ticket?\",{\"->\":\"$r\",\"var\":true},null]}],[\"ev\",{\"^->\":\"resolve.0.5.$r1\"},{\"temp=\":\"$r\"},\"str\",{\"->\":\".^.s\"},[{\"#n\":\"$r1\"}],\"/str\",\"/ev\",{\"*\":\".^.^.c-1\",\"flg\":18},{\"s\":[\"^Mark the open ticket as resolved\",{\"->\":\"$r\",\"var\":true},null]}],{\"c-0\":[\"ev\",{\"^->\":\"resolve.0.c-0.$r2\"},\"/ev\",{\"temp=\":\"$r\"},{\"->\":\".^.^.4.s\"},[{\"#n\":\"$r2\"}],\"\\n\",[[\"ev\",{\"^->\":\"resolve.0.c-0.7.0.$r1\"},{\"temp=\":\"$r\"},\"str\",{\"->\":\".^.s\"},[{\"#n\":\"$r1\"}],\"/str\",\"/ev\",{\"*\":\".^.^.c-0\",\"flg\":18},{\"s\":[\"^Create a new ticket, fill out the details and mark it as resolved \",{\"->\":\"$r\",\"var\":true},null]}],{\"c-0\":[\"ev\",{\"^->\":\"resolve.0.c-0.7.c-0.$r2\"},\"/ev\",{\"temp=\":\"$r\"},{\"->\":\".^.^.0.s\"},[{\"#n\":\"$r2\"}],\"end\",\"\\n\",{\"#f\":5}]}],{\"#f\":5}],\"c-1\":[\"ev\",{\"^->\":\"resolve.0.c-1.$r2\"},\"/ev\",{\"temp=\":\"$r\"},{\"->\":\".^.^.5.s\"},[{\"#n\":\"$r2\"}],\"\\n\",\"^\\\"Awesome, nice work!\\\"\",\"\\n\",\"end\",{\"#f\":5}]}],{\"#f\":1}],\"escalate\":[\"^\\\"Good luck with that\\\" \",\"end\",\"\\n\",{\"#f\":1}],\"chill\":[\"^\\\"Have fun, doing nothing.\\\" \",\"end\",\"\\n\",{\"#f\":1}],\"#f\":1}],\"listDefs\":{}}\n"
  },
  {
    "path": "index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0\">\n\n    <title>Wheel of Misfortune</title>\n    <meta name=\"author\" content=\"Pavlos Ratis\">\n    <meta name=\"description\" content=\"A role-playing game for incident management training\">\n    <meta name=\"keywords\" content=\"Incident Response,Trainng,Site Reliability Engineering,SRE,Oncall\">\n    <link rel=\"stylesheet\" href=\"static/styles.css\">\n\n    <link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"static/apple-touch-icon.png\">\n    <link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"static/favicon-32x32.png\">\n    <link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"static/favicon-16x16.png\">\n    <link rel=\"manifest\" href=\"static/site.webmanifest\">\n</head>\n\n<body>\n    <a href=\"https://github.com/dastergon/wheel-of-misfortune\" class=\"github-corner\"\n        aria-label=\"View source on GitHub\"><svg width=\"80\" height=\"80\" viewBox=\"0 0 250 250\"\n            style=\"fill:#151513; color:#fff; position: absolute; top: 0; border: 0; right: 0;\" aria-hidden=\"true\">\n            <path d=\"M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z\"></path>\n            <path\n                d=\"M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2\"\n                fill=\"currentColor\" style=\"transform-origin: 130px 106px;\" class=\"octo-arm\"></path>\n            <path\n                d=\"M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z\"\n                fill=\"currentColor\" class=\"octo-body\"></path>\n        </svg></a>\n    <style>\n        .github-corner:hover .octo-arm {\n            animation: octocat-wave 560ms ease-in-out\n        }\n\n        @keyframes octocat-wave {\n\n            0%,\n            100% {\n                transform: rotate(0)\n            }\n\n            20%,\n            60% {\n                transform: rotate(-25deg)\n            }\n\n            40%,\n            80% {\n                transform: rotate(10deg)\n            }\n        }\n\n        @media (max-width:500px) {\n            .github-corner:hover .octo-arm {\n                animation: none\n            }\n\n            .github-corner .octo-arm {\n                animation: octocat-wave 560ms ease-in-out\n            }\n        }\n    </style>\n\n    <header class=\"tc pv4 bg-blue\">\n        <a href=\"index.html\">\n            <h1 class=\"athelas i white-ft f1\">Wheel of Misfortune</h1>\n        </a>\n        <h1 class=\"white-ft f4\">A role-playing game for incident management training</h1>\n        <small class=\"white-ft \">Inspired by the\n            <a\n                href=\"https://landing.google.com/sre/book/chapters/accelerating-sre-on-call.html#xref_training_disaster-rpg\">Site\n                Reliability Engineering book</a>\n        </small>\n    </header>\n    <div class=\"flex items-center justify-center bg-lightest-blue navy pa3\">\n        <svg class=\"w1\" data-icon=\"info\" viewBox=\"0 0 32 32\" style=\"fill:currentcolor\">\n            <title>info icon</title>\n            <path\n                d=\"M16 0 A16 16 0 0 1 16 32 A16 16 0 0 1 16 0 M19 15 L13 15 L13 26 L19 26 z M16 6 A3 3 0 0 0 16 12 A3 3 0 0 0 16 6\">\n            </path>\n        </svg>\n        <div class=\"ml3\"><a class=\"navy\" href=\"instructions.html\">Instructions</a></div>\n    </div>\n\n    <article class=\"cf mw mw-h center bg-white br3 mv4 ba b--black-10\">\n        <div class=\"fl w-100 w-50-ns tc pa3\">\n            <h4 class=\"f4 center mw6\">Spin the Wheel!</h4> &#128223;\n            <hr class=\"mw3 bb bw1 b--black-10\">\n            <div id=\"wheel\"></div>\n            <script src=\"https://d3js.org/d3.v3.min.js\" charset=\"utf-8\"></script>\n            <script src=\"static/wheel.js\"></script>\n        </div>\n        <div class=\"fl w-100 w-50-ns tc pa3\">\n            <article id=\"incident\">\n                <p></p>\n            </article>\n        </div>\n    </article>\n\n    <article class=\"cf\">\n        <div class=\"mw mw-h center\">\n            <div class=\"fl w-100 w-30-ns tc center bg-white br3 pa3 mv3 ba b--black-10 mbr\">\n                <ul class=\"list\">\n                    <h4 class=\"f4 center mw6\">Incident Actions</h4> &#128203;\n                    <hr class=\"mw3 bb bw1 b--black-10\">\n                    <li class=\"pv3 ba bl-0 bt-0 br-0 b--dotted b--black-30\">\n                        <input type=\"checkbox\" class=\"magic-checkbox\" name=\"progress\" value=\"first\" id=\"first\"\n                            onClick=\"stopwatch.lap();changeProgress(this, 0, 25);unlockCheckbox(this);\" />\n                        <label for=\"first\">ACKNOWLEDGE</label>\n                    </li>\n                    <li class=\"pv3 ba bl-0 bt-0 br-0 b--dotted b--black-30\"><input type=\"checkbox\"\n                            class=\"magic-checkbox\" name=\"progress\" value=\"second\" id=\"second\"\n                            onClick=\"stopwatch.lap();changeProgress(this, 25, 50);unlockCheckbox(this);\" disabled>\n                        <label for=\"second\">MITIGATE</label></li>\n                    <li class=\"pv3 ba bl-0 bt-0 br-0 b--dotted b--black-30\">\n                        <input type=\"checkbox\" class=\"magic-checkbox\" name=\"progress\" value=\"third\" id=\"third\"\n                            onClick=\"stopwatch.lap();changeProgress(this, 50, 75);unlockCheckbox(this);\" disabled>\n                        <label for=\"third\">TRIAGE</label></li>\n                    <li class=\"pv3 ba bl-0 bt-0 br-0 b--dotted b--black-30\">\n                        <input type=\"checkbox\" class=\"magic-checkbox\" name=\"progress\" value=\"fourth\" id=\"fourth\"\n                            onClick=\"stopwatch.lap();stopwatch.stop();changeProgress(this, 75, 100);\" disabled>\n                        <label for=\"fourth\">RESOLVE</label></li>\n                </ul>\n            </div>\n            <div class=\"fl w-100 w-30-ns tc center bg-white br3 pa3 mv3 ba b--black-10 mbr\">\n                <h4 class=\"f4 center mw6\">Incident Progress</h4>&#128202;\n                <hr class=\"mw3 bb bw1 b--black-10\">\n                <div class=\"sz pa3\">\n                    <div id=\"progress\" class=\"pie-wrapper\">\n                        <span id=\"percent\" class=\"label\">0<span class=\"smaller\">%</span></span>\n                        <div class=\"pie\">\n                            <div class=\"left-side half-circle\"></div>\n                            <div class=\"right-side half-circle\"></div>\n                        </div>\n                        <div class=\"shadow\"></div>\n                    </div>\n                </div>\n            </div>\n            <div class=\"fl w-100 w-30-ns tc center bg-white br3 pa3 mv3 ba b--black-10 mbr\">\n                <div class=\"timing\">\n                    <h4 class=\"f4 center mw6\">Timing Controls</h4>&#9203;\n                    <hr class=\"mw3 bb bw1 b--black-10\">\n                    <div class=\"stopwatch pa3\"></div>\n                    <button id=\"start\" class=\"button\" onClick=\"stopwatch.start();changeControls();\">▶</button>\n                    <button id=\"restart\" class=\"button\"\n                        onClick=\"stopwatch.restart();stopwatch.clear();changeControls();\">↻</button>\n                    <button id=\"lap\" class=\"button\" onClick=\"stopwatch.lap();\">Lap</button>\n                    <ul class=\"results\"></ul>\n                    <script src=\"static/stopwatch.js\"></script>\n                    <script src=\"static/ink.js\"></script>\n                    <script src=\"static/mainink.js\"></script>\n                </div>\n            </div>\n        </div>\n    </article>\n\n    <footer class=\"pv4 ph4\">\n        <small class=\"f4 db tc\"><a href=\"https://dastergon.gr\" class=\"link\">Pavlos Ratis</a></small>\n    </footer>\n</body>\n\n</html>\n\n<script>\n\n    function unlockCheckbox(c) {\n        if (c.value == \"first\") {\n            document.getElementById(\"first\").disabled = true;\n            document.getElementById(\"second\").disabled = false;\n        }\n        else if (c.value == \"second\") {\n            document.getElementById(\"second\").disabled = true;\n            document.getElementById(\"third\").disabled = false;\n        }\n        else if (c.value == \"third\") {\n            document.getElementById(\"third\").disabled = true;\n            document.getElementById(\"fourth\").disabled = false;\n        }\n        else {\n            document.getElementById(\"fourth\").disabled = true;\n        }\n\n    }\n\n    function changeProgress(c, p, n) {\n        if (c.checked) {\n            var element = document.getElementById(\"progress\");\n            element.classList.remove(\"progress-\" + p);\n            element.classList.add(\"progress-\" + n);\n            document.getElementById('percent').childNodes[0].nodeValue = n;\n        } else {\n            var element = document.getElementById(\"progress\");\n            element.classList.remove(\"progress-\" + n);\n            element.classList.add(\"progress-\" + p);\n            document.getElementById('percent').childNodes[0].nodeValue = p;\n        }\n    }\n\n    function changeControls() {\n        var timingBtn = document.getElementById(\"start\");\n        if (timingBtn) {\n            timingBtn.setAttribute('onclick', 'stopwatch.stop();changeControls();');\n            timingBtn.id = \"stop\";\n            timingBtn.innerText = \"||\";\n        } else {\n            var timingBtn = document.getElementById(\"stop\");\n            timingBtn.setAttribute('onclick', 'stopwatch.start();changeControls();');\n            timingBtn.id = \"start\";\n            timingBtn.innerText = \"▶\";\n        }\n\n\n    }\n</script>\n"
  },
  {
    "path": "instructions.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0\">\n\n    <title>Wheel of Misfortune</title>\n    <meta name=\"author\" content=\"Pavlos Ratis\">\n    <meta name=\"description\" content=\"A role-playing game for incident management training\">\n    <meta name=\"keywords\" content=\"Incident Response,Trainng,Site Reliability Engineering,SRE,Oncall\">\n    <link rel=\"stylesheet\" href=\"static/styles.css\">\n\n    <link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"static/apple-touch-icon.png\">\n    <link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"static/favicon-32x32.png\">\n    <link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"static/favicon-16x16.png\">\n    <link rel=\"manifest\" href=\"static/site.webmanifest\">\n</head>\n\n<body>\n    <a href=\"https://github.com/dastergon/wheel-of-misfortune\" class=\"github-corner\"\n        aria-label=\"View source on GitHub\"><svg width=\"80\" height=\"80\" viewBox=\"0 0 250 250\"\n            style=\"fill:#151513; color:#fff; position: absolute; top: 0; border: 0; right: 0;\" aria-hidden=\"true\">\n            <path d=\"M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z\"></path>\n            <path\n                d=\"M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2\"\n                fill=\"currentColor\" style=\"transform-origin: 130px 106px;\" class=\"octo-arm\"></path>\n            <path\n                d=\"M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z\"\n                fill=\"currentColor\" class=\"octo-body\"></path>\n        </svg></a>\n    <style>\n        .github-corner:hover .octo-arm {\n            animation: octocat-wave 560ms ease-in-out\n        }\n\n        @keyframes octocat-wave {\n\n            0%,\n            100% {\n                transform: rotate(0)\n            }\n\n            20%,\n            60% {\n                transform: rotate(-25deg)\n            }\n\n            40%,\n            80% {\n                transform: rotate(10deg)\n            }\n        }\n\n        @media (max-width:500px) {\n            .github-corner:hover .octo-arm {\n                animation: none\n            }\n\n            .github-corner .octo-arm {\n                animation: octocat-wave 560ms ease-in-out\n            }\n        }\n    </style>\n\n    <header class=\"tc pv4 bg-blue\">\n        <a href=\"/\">\n            <h1 class=\"athelas i white-ft f1\">Wheel of Misfortune</h1>\n        </a>\n        <h1 class=\"white-ft f4\">A role-playing game for incident management training</h1>\n        <small class=\"white-ft \">Inspired by the\n            <a\n                href=\"https://landing.google.com/sre/book/chapters/accelerating-sre-on-call.html#xref_training_disaster-rpg\">Site\n                Reliability Engineering book</a>\n        </small>\n    </header>\n    <div class=\"flex items-center justify-center bg-lightest-blue navy pa3\">\n        <svg class=\"w1\" data-icon=\"info\" viewBox=\"0 0 32 32\" style=\"fill:currentcolor\">\n            <title>info icon</title>\n            <path\n                d=\"M16 0 A16 16 0 0 1 16 32 A16 16 0 0 1 16 0 M19 15 L13 15 L13 26 L19 26 z M16 6 A3 3 0 0 0 16 12 A3 3 0 0 0 16 6\">\n            </path>\n        </svg>\n        <div class=\"ml3\"><a class=\"navy\" href=\"instructions.html\">Instructions</a></div>\n    </div>\n\n    <article class=\"cf pa4 mw center bg-white br3 pa3 mv4 ba b--black-10\">\n        <div class=\"fl w-100 mw mw-h center\">\n            <h2 class=\"f6 center mw6 tc\">Instructions</h2>\n            <hr class=\"mw3 bb bw1 b--black-10\">\n            <p>Wheel of Misfortune is a game that aims to build confidence to oncall engineers via simulated\n                outage scenarios.\n                With the game, you practice problem debugging under stress, the understanding of the incident\n                management protocol, and effective communication with other engineers\n                of your team and organization. It is a great way to train new hires, interns, and seasoned\n                engineers to become well-rounded oncall engineers.</p>\n            <h4>Terminology</h4>\n            <ul>\n                <li><strong>Scenario</strong>: A past or fictional incident case.</li>\n                <li><strong>Game Master</strong>: The host-coordinator of the session.</li>\n                <li><strong>Volunteer</strong>: The trainee oncall engineer.</li>\n            </ul>\n            <p>Feel free to fork the <a href=\"https://github.com/dastergon/wheel-of-misfortune\">repository</a> or <a\n                    href=\"https://github.com/dastergon/wheel-of-misfortune/releases\">download</a> the stable\n                release.<br />\n                Insert your incident scenarios into the <a\n                    href=\"https://github.com/dastergon/wheel-of-misfortune/blob/master/incidents/general_incidents.json\">general_incidents.json</a>\n                file inside the <a\n                    href=\"https://github.com/dastergon/wheel-of-misfortune/tree/master/incidents\">incidents/</a>\n                folder. The file has the following format:\n            <table>\n                <tr>\n                    <td><b>title</b></td>\n                    <td>the title of the incident.</td>\n                </tr>\n                <tr>\n                    <td><b>scenario</b></td>\n                    <td>the description of the incident. It is useful to include URLs from monitoring\n                        systems, dashboards, time-series databases and playbooks.</td>\n                </tr>\n                <tr>\n                    <td><b>ID</b></td>\n                    <td>the unique ID of the outage (you can just auto-increment).</td>\n                </tr>\n                <tr>\n                    <td><b>inkstory</b></td>\n                    <td>the path to an <a href=\"https://www.inklestudios.com/ink/\">Ink</a> story file in JSON format.\n                    </td>\n                </tr>\n            </table>\n            <p>You could use <a\n                    href=\"https://github.com/dastergon/wheel-of-misfortune/blob/master/incidents/general_incidents.jsonnet\">general_incidents.jsonnet</a>\n                as an example in case you want to generate your incident scenarios using <a\n                    href=\"https://jsonnet.org/\">Jsonnet.</a>\n            <p>Wheel of Misfortune also supports the <a href=\"https://github.com/inkle/ink\">Ink</a> scripting language\n                for writing incident response narratives, for team and invdividual training. <a\n                    href=\"https://github.com/inkle/ink\">Ink</a> is a scripting language for writing interactive\n                narrative stories. It enables us to write interactive incident response narratives for\n                team or individual trainings. You can use <a href=\"https://github.com/inkle/inky\">Inky</a> to write an\n                interactive narrative for an\n                incident and then export the story as JSON. Then, you can store the story file inside the\n                <a href=\"https://github.com/dastergon/wheel-of-misfortune/tree/master/incidents\">incidents/</a> folder and associate the Ink story file with an Incident scenario using the <b>inkstory</b> key. \n                You can have a look at the <a\n                    href=\"https://github.com/dastergon/wheel-of-misfortune/tree/master/incidentsredis-story.json\">incident\n                    narrative example</a>.</p>\n            </p>\n            <h4>Game Master</h4>\n            <ol>\n                <li>Choose a volunteer to be the primary oncall engineer in front of the group.</li>\n                <li>Find a balance between volunteer's experience and incident's difficulty.</li>\n                <li>Assist volunteer by answering questions that may arise in each theoretical action or\n                    dashboard observation.</li>\n                <ul>\n                    <li>Engage with the rest of the team and ask for different ways to debug the problem\n                        following the volunteer's explanation.</li>\n                    <li>Team members may be made available over time for assistance in various topics.</li>\n                </ul>\n                <li>At the end, have a debrief on the learnings of the session.</li>\n            </ol>\n\n            <h4>Volunteer</h4>\n            <ol>\n                <li>Spin the wheel and attempt to fix the theoretical outage scenario.</li>\n                <li>Explain to the Game Master and the rest of the group what actions you would take (lookup\n                    queries, checks in dashboards, etc.) to find the root causes, and eventually solve the\n                    incident.</li>\n                <li>Always keep an eye on the time, since it is simulated incident response scenario and not a\n                    routine troubleshooting process. During a real incident you might have an SLA or SLO\n                    breach and therefore you should take timing into account.</li>\n                <li>Engage with the rest of the group. Keep them in the loop. Ask questions to different\n                    members depending on their expertise.</li>\n            </ol>\n            <p>Most importantly, <strong>have fun!</strong></p>\n            <p>You can read a comprehensive example on how to conduct the exercise <a\n                    href=\"https://landing.google.com/sre/book/chapters/accelerating-sre-on-call.html#xref_training_disaster-rpg\">here</a>.\n            </p>\n\n            <h4>Resources</h4>\n            <ul>\n                <li>\n                    <a\n                        href=\"https://landing.google.com/sre/book/chapters/accelerating-sre-on-call.html#xref_training_disaster-rpg\">Disaster\n                        Role Playing</a>\n                </li>\n                <li>\n                    <a href=\"https://www.usenix.org/conference/srecon18europe/presentation/barry\">Managing\n                        Misfortune for Best\n                        Results</a>\n                </li>\n                <li>\n                    <a href=\"https://landing.google.com/sre/book/chapters/postmortem-culture.html\">Postmortem\n                        Culture: Learning\n                        from Failure</a>\n                </li>\n                <li>\n                    <a href=\"https://github.com/dastergon/postmortem-templates\">Postmortem Templates</a>\n                </li>\n                <li>\n                    <a href=\"https://postmortems.app\">Postmortems Metadata Index</a>\n                </li>\n                <li>\n                    <a href=\"https://github.com/dastergon/awesome-sre\">Site Reliability Engineering Resources</a>\n                </li>\n            </ul>\n        </div>\n    </article>\n\n    <footer class=\"pv4 ph4\">\n        <small class=\"f4 db tc\"><a href=\"https://dastergon.gr\" class=\"link\">Pavlos Ratis</a> | 2020</small>\n    </footer>\n</body>\n\n</html>\n"
  },
  {
    "path": "static/ink.js",
    "content": "!function(t,e){\"object\"==typeof exports&&\"undefined\"!=typeof module?e(exports):\"function\"==typeof define&&define.amd?define([\"exports\"],e):e((t=t||self).inkjs={})}(this,function(t){\"use strict\";class e{constructor(){if(this._components=[],this._componentsString=null,this._isRelative=!1,\"string\"==typeof arguments[0]){let t=arguments[0];this.componentsString=t}else if(arguments[0]instanceof e.Component&&arguments[1]instanceof e){let t=arguments[0],e=arguments[1];this._components.push(t),this._components=this._components.concat(e._components)}else if(arguments[0]instanceof Array){let t=arguments[0],e=!!arguments[1];this._components=this._components.concat(t),this._isRelative=e}}get isRelative(){return this._isRelative}get componentCount(){return this._components.length}get head(){return this._components.length>0?this._components[0]:null}get tail(){if(this._components.length>=2){let t=this._components.slice(1,this._components.length);return new e(t)}return e.self}get length(){return this._components.length}get lastComponent(){let t=this._components.length-1;return t>=0?this._components[t]:null}get containsNamedComponent(){for(let t=0,e=this._components.length;t<e;t++)if(!this._components[t].isIndex)return!0;return!1}static get self(){let t=new e;return t._isRelative=!0,t}GetComponent(t){return this._components[t]}PathByAppendingPath(t){let n=new e,i=0;for(let e=0;e<t._components.length&&t._components[e].isParent;++e)i++;for(let t=0;t<this._components.length-i;++t)n._components.push(this._components[t]);for(let e=i;e<t._components.length;++e)n._components.push(t._components[e]);return n}get componentsString(){return null==this._componentsString&&(this._componentsString=this._components.join(\".\"),this.isRelative&&(this._componentsString=\".\"+this._componentsString)),this._componentsString}set componentsString(t){if(this._components.length=0,this._componentsString=t,null==this._componentsString||\"\"==this._componentsString)return;\".\"==this._componentsString[0]&&(this._isRelative=!0,this._componentsString=this._componentsString.substring(1));let n=this._componentsString.split(\".\");for(let t of n)/^(\\-|\\+)?([0-9]+|Infinity)$/.test(t)?this._components.push(new e.Component(parseInt(t))):this._components.push(new e.Component(t))}toString(){return this.componentsString}Equals(t){if(null==t)return!1;if(t._components.length!=this._components.length)return!1;if(t.isRelative!=this.isRelative)return!1;for(let e=0,n=t._components.length;e<n;e++)if(!t._components[e].Equals(this._components[e]))return!1;return!0}PathByAppendingComponent(t){let n=new e;return n._components.push.apply(n._components,this._components),n._components.push(t),n}}var n,i,a;function r(t,e){return t instanceof e?h(t):null}function s(t,e){if(t instanceof e)return h(t);throw new Error(`${t} is not of type ${e}`)}function l(t){if(\"number\"==typeof t)return t;throw new Error(`${t} is not a number`)}function o(t){return t.hasValidName&&t.name?t:null}function u(t){return void 0===t?null:t}function h(t,e){return t}e.parentId=\"^\",function(t){class e{constructor(t){this.index=-1,this.name=null,\"string\"==typeof t?this.name=t:this.index=t}get isIndex(){return this.index>=0}get isParent(){return this.name==t.parentId}static ToParent(){return new e(t.parentId)}toString(){return this.isIndex?this.index.toString():this.name}Equals(t){return null!=t&&t.isIndex==this.isIndex&&(this.isIndex?this.index==t.index:this.name==t.name)}}t.Component=e}(e||(e={})),function(t){function e(t,e){if(!t)throw void 0!==e&&console.warn(e),console.trace&&console.trace(),\"\"}t.AssertType=function(t,n,i){e(t instanceof n,i)},t.Assert=e}(n||(n={}));class c extends Error{}function d(t){throw new c(`${t} is null or undefined`)}class p{constructor(){this.parent=null,this._debugMetadata=null,this._path=null}get debugMetadata(){return null===this._debugMetadata&&this.parent?this.parent.debugMetadata:this._debugMetadata}set debugMetadata(t){this._debugMetadata=t}get ownDebugMetadata(){return this._debugMetadata}DebugLineNumberOfPath(t){if(null===t)return null;let e=this.rootContentContainer;if(e){let n=e.ContentAtPath(t).obj;if(n){let t=n.debugMetadata;if(null!==t)return t.startLineNumber}}return null}get path(){if(null==this._path)if(null==this.parent)this._path=new e;else{let t=[],n=this,i=r(n.parent,N);for(;null!==i;){let a=o(n);null!=a&&a.hasValidName?t.unshift(new e.Component(a.name)):t.unshift(new e.Component(i.content.indexOf(n))),n=i,i=r(i.parent,N)}this._path=new e(t)}return this._path}ResolvePath(t){if(null===t)return d(\"path\");if(t.isRelative){let e=r(this,N);return null===e&&(n.Assert(null!==this.parent,\"Can't resolve relative path because we don't have a parent\"),e=r(this.parent,N),n.Assert(null!==e,\"Expected parent to be a container\"),n.Assert(t.GetComponent(0).isParent),t=t.tail),null===e?d(\"nearestContainer\"):e.ContentAtPath(t)}{let e=this.rootContentContainer;return null===e?d(\"contentContainer\"):e.ContentAtPath(t)}}ConvertPathToRelative(t){let n=this.path,i=Math.min(t.length,n.length),a=-1;for(let e=0;e<i;++e){let i=n.GetComponent(e),r=t.GetComponent(e);if(!i.Equals(r))break;a=e}if(-1==a)return t;let r=n.componentCount-1-a,s=[];for(let t=0;t<r;++t)s.push(e.Component.ToParent());for(let e=a+1;e<t.componentCount;++e)s.push(t.GetComponent(e));return new e(s,!0)}CompactPathString(t){let e=null,n=null;if(t.isRelative)n=t.componentsString,e=this.path.PathByAppendingPath(t).componentsString;else{n=this.ConvertPathToRelative(t).componentsString,e=t.componentsString}return n.length<e.length?n:e}get rootContentContainer(){let t=this;for(;t.parent;)t=t.parent;return r(t,N)}Copy(){throw Error(\"Not Implemented: Doesn't support copying\")}SetChild(t,e,n){t[e]&&(t[e]=null),t[e]=n,t[e]&&(t[e].parent=this)}}class m{constructor(t){t=void 0!==t?t.toString():\"\",this.string=t}get Length(){return this.string.length}Append(t){null!==t&&(this.string+=t)}AppendLine(t){void 0!==t&&this.Append(t),this.string+=\"\\n\"}AppendFormat(t,...e){this.string+=t.replace(/{(\\d+)}/g,(t,n)=>void 0!==e[n]?e[n]:t)}toString(){return this.string}}class f{constructor(){if(this.originName=null,this.itemName=null,void 0!==arguments[1]){let t=arguments[0],e=arguments[1];this.originName=t,this.itemName=e}else if(arguments[0]){let t=arguments[0].toString().split(\".\");this.originName=t[0],this.itemName=t[1]}}static get Null(){return new f(null,null)}get isNull(){return null==this.originName&&null==this.itemName}get fullName(){return(null!==this.originName?this.originName:\"?\")+\".\"+this.itemName}toString(){return this.fullName}Equals(t){if(t instanceof f){let e=t;return e.itemName==this.itemName&&e.originName==this.originName}return!1}copy(){return new f(this.originName,this.itemName)}serialized(){return JSON.stringify({originName:this.originName,itemName:this.itemName})}static fromSerializedKey(t){let e=JSON.parse(t);if(!f.isLikeInkListItem(e))return f.Null;let n=e;return new f(n.originName,n.itemName)}static isLikeInkListItem(t){return\"object\"==typeof t&&(!(!t.hasOwnProperty(\"originName\")||!t.hasOwnProperty(\"itemName\"))&&((\"string\"==typeof t.originName||null===typeof t.originName)&&(\"string\"==typeof t.itemName||null===typeof t.itemName)))}}class g extends Map{constructor(){if(super((()=>arguments[0]instanceof g?arguments[0]:void 0)()),this.origins=null,this._originNames=[],arguments[0]instanceof g){let t=arguments[0];t._originNames&&(this._originNames=t._originNames.slice())}else if(\"string\"==typeof arguments[0]){let t=arguments[0],e=arguments[1];this.SetInitialOriginName(t);let n=e.listDefinitions.TryListGetDefinition(t,null);if(!n.exists)throw new Error(\"InkList origin could not be found in story when constructing new list: \"+t);this.origins=[n.result]}else if(\"object\"==typeof arguments[0]&&arguments[0].hasOwnProperty(\"Key\")&&arguments[0].hasOwnProperty(\"Value\")){let t=arguments[0];this.Add(t.Key,t.Value)}}AddItem(t){if(t instanceof f){let e=t;if(null==e.originName)return void this.AddItem(e.itemName);if(null===this.origins)return d(\"this.origins\");for(let t of this.origins)if(t.name==e.originName){let n=t.TryGetValueForItem(e,0);if(n.exists)return void this.Add(e,n.result);throw new Error(\"Could not add the item \"+e+\" to this list because it doesn't exist in the original list definition in ink.\")}throw new Error(\"Failed to add item to list because the item was from a new list definition that wasn't previously known to this list. Only items from previously known lists can be used, so that the int value can be found.\")}{let e=t,n=null;if(null===this.origins)return d(\"this.origins\");for(let t of this.origins){if(null===e)return d(\"itemName\");if(t.ContainsItemWithName(e)){if(null!=n)throw new Error(\"Could not add the item \"+e+\" to this list because it could come from either \"+t.name+\" or \"+n.name);n=t}}if(null==n)throw new Error(\"Could not add the item \"+e+\" to this list because it isn't known to any list definitions previously associated with this list.\");let i=new f(n.name,e),a=n.ValueForItem(i);this.Add(i,a)}}ContainsItemNamed(t){for(let[e,n]of this){if(f.fromSerializedKey(e).itemName==t)return!0}return!1}ContainsKey(t){return this.has(t.serialized())}Add(t,e){let n=t.serialized();if(this.has(n))throw new Error(`The Map already contains an entry for ${t}`);this.set(n,e)}Remove(t){return this.delete(t.serialized())}get Count(){return this.size}get originOfMaxItem(){if(null==this.origins)return null;let t=this.maxItem.Key.originName,e=null;return this.origins.every(n=>n.name!=t||(e=n,!1)),e}get originNames(){if(this.Count>0){null==this._originNames&&this.Count>0?this._originNames=[]:(this._originNames||(this._originNames=[]),this._originNames.length=0);for(let[t,e]of this){let e=f.fromSerializedKey(t);if(null===e.originName)return d(\"item.originName\");this._originNames.push(e.originName)}}return this._originNames}SetInitialOriginName(t){this._originNames=[t]}SetInitialOriginNames(t){this._originNames=null==t?null:t.slice()}get maxItem(){let t={Key:f.Null,Value:0};for(let[e,n]of this){let i=f.fromSerializedKey(e);(t.Key.isNull||n>t.Value)&&(t={Key:i,Value:n})}return t}get minItem(){let t={Key:f.Null,Value:0};for(let[e,n]of this){let i=f.fromSerializedKey(e);(t.Key.isNull||n<t.Value)&&(t={Key:i,Value:n})}return t}get inverse(){let t=new g;if(null!=this.origins)for(let e of this.origins)for(let[n,i]of e.items){let e=f.fromSerializedKey(n);this.ContainsKey(e)||t.Add(e,i)}return t}get all(){let t=new g;if(null!=this.origins)for(let e of this.origins)for(let[n,i]of e.items){let e=f.fromSerializedKey(n);t.set(e.serialized(),i)}return t}Union(t){let e=new g(this);for(let[n,i]of t)e.set(n,i);return e}Intersect(t){let e=new g;for(let[n,i]of this)t.has(n)&&e.set(n,i);return e}Without(t){let e=new g(this);for(let[n,i]of t)e.delete(n);return e}Contains(t){for(let[e,n]of t)if(!this.has(e))return!1;return!0}GreaterThan(t){return 0!=this.Count&&(0==t.Count||this.minItem.Value>t.maxItem.Value)}GreaterThanOrEquals(t){return 0!=this.Count&&(0==t.Count||this.minItem.Value>=t.minItem.Value&&this.maxItem.Value>=t.maxItem.Value)}LessThan(t){return 0!=t.Count&&(0==this.Count||this.maxItem.Value<t.minItem.Value)}LessThanOrEquals(t){return 0!=t.Count&&(0==this.Count||this.maxItem.Value<=t.maxItem.Value&&this.minItem.Value<=t.minItem.Value)}MaxAsList(){return this.Count>0?new g(this.maxItem):new g}MinAsList(){return this.Count>0?new g(this.minItem):new g}ListWithSubRange(t,e){if(0==this.Count)return new g;let n=this.orderedItems,i=0,a=Number.MAX_SAFE_INTEGER;Number.isInteger(t)?i=t:t instanceof g&&t.Count>0&&(i=t.minItem.Value),Number.isInteger(e)?a=e:t instanceof g&&t.Count>0&&(a=e.maxItem.Value);let r=new g;r.SetInitialOriginNames(this.originNames);for(let t of n)t.Value>=i&&t.Value<=a&&r.Add(t.Key,t.Value);return r}Equals(t){if(t instanceof g==!1)return!1;if(t.Count!=this.Count)return!1;for(let[e,n]of this)if(!t.has(e))return!1;return!0}get orderedItems(){let t=new Array;for(let[e,n]of this){let i=f.fromSerializedKey(e);t.push({Key:i,Value:n})}return t.sort((t,e)=>null===t.Key.originName?d(\"x.Key.originName\"):null===e.Key.originName?d(\"y.Key.originName\"):t.Value==e.Value?t.Key.originName.localeCompare(e.Key.originName):t.Value<e.Value?-1:t.Value>e.Value?1:0),t}toString(){let t=this.orderedItems,e=new m;for(let n=0;n<t.length;n++){n>0&&e.Append(\", \");let i=t[n].Key;if(null===i.itemName)return d(\"item.itemName\");e.Append(i.itemName)}return e.toString()}valueOf(){return NaN}}class C extends Error{constructor(t){super(t),this.useEndLineNumber=!1,this.message=t,this.name=\"StoryException\"}}function v(t,e,n){if(null===t)return{result:n,exists:!1};let i=t.get(e);return i?{result:i,exists:!0}:{result:n,exists:!1}}class S extends p{static Create(t){if(\"boolean\"==typeof t){t=!!t?1:0}return Number.isInteger(Number(t))?new T(Number(t)):isNaN(t)?\"string\"==typeof t?new _(String(t)):t instanceof e?new w(s(t,e)):t instanceof g?new O(s(t,g)):null:new b(Number(t))}Copy(){return s(S.Create(this),p)}BadCastException(t){return new C(\"Can't cast \"+this.valueObject+\" from \"+this.valueType+\" to \"+t)}}class y extends S{constructor(t){super(),this.value=t}get valueObject(){return this.value}toString(){return null===this.value?d(\"Value.value\"):this.value.toString()}}class T extends y{constructor(t){super(t||0)}get isTruthy(){return 0!=this.value}get valueType(){return i.Int}Cast(t){if(null===this.value)return d(\"Value.value\");if(t==this.valueType)return this;if(t==i.Float)return new b(this.value);if(t==i.String)return new _(\"\"+this.value);throw this.BadCastException(t)}}class b extends y{constructor(t){super(t||0)}get isTruthy(){return 0!=this.value}get valueType(){return i.Float}Cast(t){if(null===this.value)return d(\"Value.value\");if(t==this.valueType)return this;if(t==i.Int)return new T(this.value);if(t==i.String)return new _(\"\"+this.value);throw this.BadCastException(t)}}class _ extends y{constructor(t){if(super(t||\"\"),this._isNewline=\"\\n\"==this.value,this._isInlineWhitespace=!0,null===this.value)return d(\"Value.value\");this.value.length>0&&this.value.split(\"\").every(t=>\" \"==t||\"\\t\"==t||(this._isInlineWhitespace=!1,!1))}get valueType(){return i.String}get isTruthy(){return null===this.value?d(\"Value.value\"):this.value.length>0}get isNewline(){return this._isNewline}get isInlineWhitespace(){return this._isInlineWhitespace}get isNonWhitespace(){return!this.isNewline&&!this.isInlineWhitespace}Cast(t){if(t==this.valueType)return this;if(t==i.Int){let e=function(t,e=0){let n=parseInt(t);return Number.isNaN(n)?{result:e,exists:!1}:{result:n,exists:!0}}(this.value);if(e.exists)return new T(e.result);throw this.BadCastException(t)}if(t==i.Float){let e=function(t,e=0){let n=parseFloat(t);return Number.isNaN(n)?{result:e,exists:!1}:{result:n,exists:!0}}(this.value);if(e.exists)return new b(e.result);throw this.BadCastException(t)}throw this.BadCastException(t)}}class w extends y{constructor(t){super(t)}get valueType(){return i.DivertTarget}get targetPath(){return null===this.value?d(\"Value.value\"):this.value}set targetPath(t){this.value=t}get isTruthy(){throw new Error(\"Shouldn't be checking the truthiness of a divert target\")}Cast(t){if(t==this.valueType)return this;throw this.BadCastException(t)}toString(){return\"DivertTargetValue(\"+this.targetPath+\")\"}}class E extends y{constructor(t,e=-1){super(t),this._contextIndex=e}get contextIndex(){return this._contextIndex}set contextIndex(t){this._contextIndex=t}get variableName(){return null===this.value?d(\"Value.value\"):this.value}set variableName(t){this.value=t}get valueType(){return i.VariablePointer}get isTruthy(){throw new Error(\"Shouldn't be checking the truthiness of a variable pointer\")}Cast(t){if(t==this.valueType)return this;throw this.BadCastException(t)}toString(){return\"VariablePointerValue(\"+this.variableName+\")\"}Copy(){return new E(this.variableName,this.contextIndex)}}class O extends y{get isTruthy(){return null===this.value?d(\"this.value\"):this.value.Count>0}get valueType(){return i.List}Cast(t){if(null===this.value)return d(\"Value.value\");if(t==i.Int){let t=this.value.maxItem;return t.Key.isNull?new T(0):new T(t.Value)}if(t==i.Float){let t=this.value.maxItem;return t.Key.isNull?new b(0):new b(t.Value)}if(t==i.String){let t=this.value.maxItem;return t.Key.isNull?new _(\"\"):new _(t.Key.toString())}if(t==this.valueType)return this;throw this.BadCastException(t)}constructor(t,e){super(null),t||e?t instanceof g?this.value=new g(t):t instanceof f&&\"number\"==typeof e&&(this.value=new g({Key:t,Value:e})):this.value=new g}static RetainListOriginsForAssignment(t,e){let n=r(t,O),i=r(e,O);return i&&null===i.value?d(\"newList.value\"):n&&null===n.value?d(\"oldList.value\"):void(n&&i&&0==i.value.Count&&i.value.SetInitialOriginNames(n.value.originNames))}}!function(t){t[t.Int=0]=\"Int\",t[t.Float=1]=\"Float\",t[t.List=2]=\"List\",t[t.String=3]=\"String\",t[t.DivertTarget=4]=\"DivertTarget\",t[t.VariablePointer=5]=\"VariablePointer\"}(i||(i={}));class x{constructor(){this.obj=null,this.approximate=!1}get correctObj(){return this.approximate?null:this.obj}get container(){return this.obj instanceof N?this.obj:null}copy(){let t=new x;return t.obj=this.obj,t.approximate=this.approximate,t}}class N extends p{constructor(){super(...arguments),this.name=\"\",this._content=[],this.namedContent=new Map,this.visitsShouldBeCounted=!1,this.turnIndexShouldBeCounted=!1,this.countingAtStartOnly=!1,this._pathToFirstLeafContent=null}get hasValidName(){return null!=this.name&&this.name.length>0}get content(){return this._content}set content(t){this.AddContent(t)}get namedOnlyContent(){let t=new Map;for(let[e,n]of this.namedContent){let i=s(n,p);t.set(e,i)}for(let e of this.content){let n=o(e);null!=n&&n.hasValidName&&t.delete(n.name)}return 0==t.size&&(t=null),t}set namedOnlyContent(t){let e=this.namedOnlyContent;if(null!=e)for(let[t,n]of e)this.namedContent.delete(t);if(null!=t)for(let[e,n]of t){let t=o(n);null!=t&&this.AddToNamedContentOnly(t)}}get countFlags(){let t=0;return this.visitsShouldBeCounted&&(t|=N.CountFlags.Visits),this.turnIndexShouldBeCounted&&(t|=N.CountFlags.Turns),this.countingAtStartOnly&&(t|=N.CountFlags.CountStartOnly),t==N.CountFlags.CountStartOnly&&(t=0),t}set countFlags(t){let e=t;(e&N.CountFlags.Visits)>0&&(this.visitsShouldBeCounted=!0),(e&N.CountFlags.Turns)>0&&(this.turnIndexShouldBeCounted=!0),(e&N.CountFlags.CountStartOnly)>0&&(this.countingAtStartOnly=!0)}get pathToFirstLeafContent(){return null==this._pathToFirstLeafContent&&(this._pathToFirstLeafContent=this.path.PathByAppendingPath(this.internalPathToFirstLeafContent)),this._pathToFirstLeafContent}get internalPathToFirstLeafContent(){let t=[],n=this;for(;n instanceof N;)n.content.length>0&&(t.push(new e.Component(0)),n=n.content[0]);return new e(t)}AddContent(t){if(t instanceof Array){let e=t;for(let t of e)this.AddContent(t)}else{let e=t;if(this._content.push(e),e.parent)throw new Error(\"content is already in \"+e.parent);e.parent=this,this.TryAddNamedContent(e)}}TryAddNamedContent(t){let e=o(t);null!=e&&e.hasValidName&&this.AddToNamedContentOnly(e)}AddToNamedContentOnly(t){n.AssertType(t,p,\"Can only add Runtime.Objects to a Runtime.Container\"),s(t,p).parent=this,this.namedContent.set(t.name,t)}ContentAtPath(t,e=0,n=-1){-1==n&&(n=t.length);let i=new x;i.approximate=!1;let a=this,s=this;for(let l=e;l<n;++l){let e=t.GetComponent(l);if(null==a){i.approximate=!0;break}let n=a.ContentWithPathComponent(e);if(null==n){i.approximate=!0;break}s=n,a=r(n,N)}return i.obj=s,i}InsertContent(t,e){if(this.content[e]=t,t.parent)throw new Error(\"content is already in \"+t.parent);t.parent=this,this.TryAddNamedContent(t)}AddContentsOfContainer(t){this.content=this.content.concat(t.content);for(let e of t.content)e.parent=this,this.TryAddNamedContent(e)}ContentWithPathComponent(t){if(t.isIndex)return t.index>=0&&t.index<this.content.length?this.content[t.index]:null;if(t.isParent)return this.parent;{if(null===t.name)return d(\"component.name\");let e=v(this.namedContent,t.name,null);return e.exists?s(e.result,p):null}}BuildStringOfHierarchy(){let t;if(0==arguments.length)return t=new m,this.BuildStringOfHierarchy(t,0,null),t.toString();t=arguments[0];let e=arguments[1],i=arguments[2];function a(){for(let n=0;n<4*e;++n)t.Append(\" \")}a(),t.Append(\"[\"),this.hasValidName&&t.AppendFormat(\" ({0})\",this.name),this==i&&t.Append(\"  <---\"),t.AppendLine(),e++;for(let n=0;n<this.content.length;++n){let r=this.content[n];if(r instanceof N){r.BuildStringOfHierarchy(t,e,i)}else a(),r instanceof _?(t.Append('\"'),t.Append(r.toString().replace(\"\\n\",\"\\\\n\")),t.Append('\"')):t.Append(r.toString());n!=this.content.length-1&&t.Append(\",\"),r instanceof N||r!=i||t.Append(\"  <---\"),t.AppendLine()}let r=new Map;for(let[t,e]of this.namedContent)this.content.indexOf(s(e,p))>=0||r.set(t,e);if(r.size>0){a(),t.AppendLine(\"-- named: --\");for(let[a,s]of r){n.AssertType(s,N,\"Can only print out named Containers\"),s.BuildStringOfHierarchy(t,e,i),t.AppendLine()}}e--,a(),t.Append(\"]\")}}!function(t){let e;!function(t){t[t.Visits=1]=\"Visits\",t[t.Turns=2]=\"Turns\",t[t.CountStartOnly=4]=\"CountStartOnly\"}(e=t.CountFlags||(t.CountFlags={}))}(N||(N={}));class P extends p{toString(){return\"Glue\"}}class A extends p{get commandType(){return this._commandType}constructor(t=A.CommandType.NotSet){super(),this._commandType=t}Copy(){return new A(this.commandType)}static EvalStart(){return new A(A.CommandType.EvalStart)}static EvalOutput(){return new A(A.CommandType.EvalOutput)}static EvalEnd(){return new A(A.CommandType.EvalEnd)}static Duplicate(){return new A(A.CommandType.Duplicate)}static PopEvaluatedValue(){return new A(A.CommandType.PopEvaluatedValue)}static PopFunction(){return new A(A.CommandType.PopFunction)}static PopTunnel(){return new A(A.CommandType.PopTunnel)}static BeginString(){return new A(A.CommandType.BeginString)}static EndString(){return new A(A.CommandType.EndString)}static NoOp(){return new A(A.CommandType.NoOp)}static ChoiceCount(){return new A(A.CommandType.ChoiceCount)}static Turns(){return new A(A.CommandType.Turns)}static TurnsSince(){return new A(A.CommandType.TurnsSince)}static ReadCount(){return new A(A.CommandType.ReadCount)}static Random(){return new A(A.CommandType.Random)}static SeedRandom(){return new A(A.CommandType.SeedRandom)}static VisitIndex(){return new A(A.CommandType.VisitIndex)}static SequenceShuffleIndex(){return new A(A.CommandType.SequenceShuffleIndex)}static StartThread(){return new A(A.CommandType.StartThread)}static Done(){return new A(A.CommandType.Done)}static End(){return new A(A.CommandType.End)}static ListFromInt(){return new A(A.CommandType.ListFromInt)}static ListRange(){return new A(A.CommandType.ListRange)}static ListRandom(){return new A(A.CommandType.ListRandom)}toString(){return this.commandType.toString()}}!function(t){let e;!function(t){t[t.NotSet=-1]=\"NotSet\",t[t.EvalStart=0]=\"EvalStart\",t[t.EvalOutput=1]=\"EvalOutput\",t[t.EvalEnd=2]=\"EvalEnd\",t[t.Duplicate=3]=\"Duplicate\",t[t.PopEvaluatedValue=4]=\"PopEvaluatedValue\",t[t.PopFunction=5]=\"PopFunction\",t[t.PopTunnel=6]=\"PopTunnel\",t[t.BeginString=7]=\"BeginString\",t[t.EndString=8]=\"EndString\",t[t.NoOp=9]=\"NoOp\",t[t.ChoiceCount=10]=\"ChoiceCount\",t[t.Turns=11]=\"Turns\",t[t.TurnsSince=12]=\"TurnsSince\",t[t.Random=13]=\"Random\",t[t.SeedRandom=14]=\"SeedRandom\",t[t.VisitIndex=15]=\"VisitIndex\",t[t.SequenceShuffleIndex=16]=\"SequenceShuffleIndex\",t[t.StartThread=17]=\"StartThread\",t[t.Done=18]=\"Done\",t[t.End=19]=\"End\",t[t.ListFromInt=20]=\"ListFromInt\",t[t.ListRange=21]=\"ListRange\",t[t.ListRandom=22]=\"ListRandom\",t[t.ReadCount=23]=\"ReadCount\",t[t.TOTAL_VALUES=24]=\"TOTAL_VALUES\"}(e=t.CommandType||(t.CommandType={}))}(A||(A={})),function(t){t[t.Tunnel=0]=\"Tunnel\",t[t.Function=1]=\"Function\",t[t.FunctionEvaluationFromGame=2]=\"FunctionEvaluationFromGame\"}(a||(a={}));class k{constructor(){this.container=null,this.index=-1,2===arguments.length&&(this.container=arguments[0],this.index=arguments[1])}Resolve(){return this.index<0?this.container:null==this.container?null:0==this.container.content.length?this.container:this.index>=this.container.content.length?null:this.container.content[this.index]}get isNull(){return null==this.container}get path(){return this.isNull?null:this.index>=0?this.container.path.PathByAppendingComponent(new e.Component(this.index)):this.container.path}toString(){return this.container?\"Ink Pointer -> \"+this.container.path.toString()+\" -- index \"+this.index:\"Ink Pointer (null)\"}copy(){return new k(this.container,this.index)}static StartOf(t){return new k(t,0)}static get Null(){return new k(null,-1)}}class I extends p{constructor(t){super(),this._targetPath=null,this._targetPointer=k.Null,this.variableDivertName=null,this.pushesToStack=!1,this.stackPushType=0,this.isExternal=!1,this.externalArgs=0,this.isConditional=!1,this.pushesToStack=!1,void 0!==t&&(this.pushesToStack=!0,this.stackPushType=t)}get targetPath(){if(null!=this._targetPath&&this._targetPath.isRelative){let t=this.targetPointer.Resolve();t&&(this._targetPath=t.path)}return this._targetPath}set targetPath(t){this._targetPath=t,this._targetPointer=k.Null}get targetPointer(){if(this._targetPointer.isNull){let t=this.ResolvePath(this._targetPath).obj;if(null===this._targetPath)return d(\"this._targetPath\");if(null===this._targetPath.lastComponent)return d(\"this._targetPath.lastComponent\");if(this._targetPath.lastComponent.isIndex){if(null===t)return d(\"targetObj\");this._targetPointer.container=t.parent instanceof N?t.parent:null,this._targetPointer.index=this._targetPath.lastComponent.index}else this._targetPointer=k.StartOf(t instanceof N?t:null)}return this._targetPointer.copy()}get targetPathString(){return null==this.targetPath?null:this.CompactPathString(this.targetPath)}set targetPathString(t){this.targetPath=null==t?null:new e(t)}get hasVariableTarget(){return null!=this.variableDivertName}Equals(t){let e=t;return e instanceof I&&this.hasVariableTarget==e.hasVariableTarget&&(this.hasVariableTarget?this.variableDivertName==e.variableDivertName:null===this.targetPath?d(\"this.targetPath\"):this.targetPath.Equals(e.targetPath))}toString(){if(this.hasVariableTarget)return\"Divert(variable: \"+this.variableDivertName+\")\";if(null==this.targetPath)return\"Divert(null)\";{let t=new m,e=this.targetPath.toString();return t.Append(\"Divert\"),this.isConditional&&t.Append(\"?\"),this.pushesToStack&&(this.stackPushType==a.Function?t.Append(\" function\"):t.Append(\" tunnel\")),t.Append(\" -> \"),t.Append(this.targetPathString),t.Append(\" (\"),t.Append(e),t.Append(\")\"),t.toString()}}}class F extends p{constructor(t=!0){super(),this._pathOnChoice=null,this.hasCondition=!1,this.hasStartContent=!1,this.hasChoiceOnlyContent=!1,this.isInvisibleDefault=!1,this.onceOnly=!0,this.onceOnly=t}get pathOnChoice(){if(null!=this._pathOnChoice&&this._pathOnChoice.isRelative){let t=this.choiceTarget;t&&(this._pathOnChoice=t.path)}return this._pathOnChoice}set pathOnChoice(t){this._pathOnChoice=t}get choiceTarget(){return null===this._pathOnChoice?d(\"ChoicePoint._pathOnChoice\"):this.ResolvePath(this._pathOnChoice).container}get pathStringOnChoice(){return null===this.pathOnChoice?d(\"ChoicePoint.pathOnChoice\"):this.CompactPathString(this.pathOnChoice)}set pathStringOnChoice(t){this.pathOnChoice=new e(t)}get flags(){let t=0;return this.hasCondition&&(t|=1),this.hasStartContent&&(t|=2),this.hasChoiceOnlyContent&&(t|=4),this.isInvisibleDefault&&(t|=8),this.onceOnly&&(t|=16),t}set flags(t){this.hasCondition=(1&t)>0,this.hasStartContent=(2&t)>0,this.hasChoiceOnlyContent=(4&t)>0,this.isInvisibleDefault=(8&t)>0,this.onceOnly=(16&t)>0}toString(){if(null===this.pathOnChoice)return d(\"ChoicePoint.pathOnChoice\");return\"Choice: -> \"+this.pathOnChoice.toString()}}class V extends p{constructor(t=null){super(),this.pathForCount=null,this.name=t}get containerForCount(){return null===this.pathForCount?null:this.ResolvePath(this.pathForCount).container}get pathStringForCount(){return null===this.pathForCount?null:this.CompactPathString(this.pathForCount)}set pathStringForCount(t){this.pathForCount=null===t?null:new e(t)}toString(){if(null!=this.name)return\"var(\"+this.name+\")\";return\"read_count(\"+this.pathStringForCount+\")\"}}class L extends p{constructor(t,e){super(),this.variableName=t||null,this.isNewDeclaration=!!e,this.isGlobal=!1}toString(){return\"VarAssign to \"+this.variableName}}class R extends p{}class D extends p{constructor(){if(super(),this._name=null,this._numberOfParameters=0,this._prototype=null,this._isPrototype=!1,this._operationFuncs=null,0===arguments.length)D.GenerateNativeFunctionsIfNecessary();else if(1===arguments.length){let t=arguments[0];D.GenerateNativeFunctionsIfNecessary(),this.name=t}else if(2===arguments.length){let t=arguments[0],e=arguments[1];this._isPrototype=!0,this.name=t,this.numberOfParameters=e}}static CallWithName(t){return new D(t)}static CallExistsWithName(t){return this.GenerateNativeFunctionsIfNecessary(),this._nativeFunctions.get(t)}get name(){return null===this._name?d(\"NativeFunctionCall._name\"):this._name}set name(t){this._name=t,this._isPrototype||(null===D._nativeFunctions?d(\"NativeFunctionCall._nativeFunctions\"):this._prototype=D._nativeFunctions.get(this._name)||null)}get numberOfParameters(){return this._prototype?this._prototype.numberOfParameters:this._numberOfParameters}set numberOfParameters(t){this._numberOfParameters=t}Call(t){if(this._prototype)return this._prototype.Call(t);if(this.numberOfParameters!=t.length)throw new Error(\"Unexpected number of parameters\");let e=!1;for(let n of t){if(n instanceof R)throw new C('Attempting to perform operation on a void value. Did you forget to \"return\" a value from a function you called here?');n instanceof O&&(e=!0)}if(2==t.length&&e)return this.CallBinaryListOperation(t);let n=this.CoerceValuesToSingleType(t),a=n[0].valueType;return a==i.Int?this.CallType(n):a==i.Float?this.CallType(n):a==i.String?this.CallType(n):a==i.DivertTarget?this.CallType(n):a==i.List?this.CallType(n):null}CallType(t){let e=s(t[0],y),n=e.valueType,i=e,a=t.length;if(2==a||1==a){if(null===this._operationFuncs)return d(\"NativeFunctionCall._operationFuncs\");let e=this._operationFuncs.get(n);if(!e)throw new C(\"Cannot perform operation \"+this.name+\" on \"+n);if(2==a){let n=s(t[1],y),a=e;if(null===i.value||null===n.value)return d(\"NativeFunctionCall.Call BinaryOp values\");let r=a(i.value,n.value);return y.Create(r)}{let t=e;if(null===i.value)return d(\"NativeFunctionCall.Call UnaryOp value\");let n=t(i.value);return y.Create(n)}}throw new Error(\"Unexpected number of parameters to NativeFunctionCall: \"+t.length)}CallBinaryListOperation(t){if((\"+\"==this.name||\"-\"==this.name)&&t[0]instanceof O&&t[1]instanceof T)return this.CallListIncrementOperation(t);let e=s(t[0],y),n=s(t[1],y);if(!(\"&&\"!=this.name&&\"||\"!=this.name||e.valueType==i.List&&n.valueType==i.List)){if(null===this._operationFuncs)return d(\"NativeFunctionCall._operationFuncs\");let t=this._operationFuncs.get(i.Int);if(null===t)return d(\"NativeFunctionCall.CallBinaryListOperation op\");let a=t(e.isTruthy?1:0,n.isTruthy?1:0);return new T(a)}if(e.valueType==i.List&&n.valueType==i.List)return this.CallType([e,n]);throw new C(\"Can not call use \"+this.name+\" operation on \"+e.valueType+\" and \"+n.valueType)}CallListIncrementOperation(t){let e=s(t[0],O),n=s(t[1],T),a=new g;if(null===e.value)return d(\"NativeFunctionCall.CallListIncrementOperation listVal.value\");for(let[t,r]of e.value){let s=f.fromSerializedKey(t);if(null===this._operationFuncs)return d(\"NativeFunctionCall._operationFuncs\");let l=this._operationFuncs.get(i.Int);if(null===n.value)return d(\"NativeFunctionCall.CallListIncrementOperation intVal.value\");let o=l(r,n.value),u=null;if(null===e.value.origins)return d(\"NativeFunctionCall.CallListIncrementOperation listVal.value.origins\");for(let t of e.value.origins)if(t.name==s.originName){u=t;break}if(null!=u){let t=u.TryGetItemWithValue(o,f.Null);t.exists&&a.Add(t.result,o)}}return new O(a)}CoerceValuesToSingleType(t){let e=i.Int,n=null;for(let a of t){let t=s(a,y);t.valueType>e&&(e=t.valueType),t.valueType==i.List&&(n=r(t,O))}let a=[];if(i[e]==i[i.List])for(let e of t){let t=s(e,y);if(t.valueType==i.List)a.push(t);else{if(t.valueType!=i.Int)throw new C(\"Cannot mix Lists and \"+t.valueType+\" values in this operation\");{let e=parseInt(t.valueObject);if(null===(n=s(n,O)).value)return d(\"NativeFunctionCall.CoerceValuesToSingleType specialCaseList.value\");let i=n.value.originOfMaxItem;if(null===i)return d(\"NativeFunctionCall.CoerceValuesToSingleType list\");let r=i.TryGetItemWithValue(e,f.Null);if(!r.exists)throw new C(\"Could not find List item with the value \"+e+\" in \"+i.name);{let t=new O(r.result,e);a.push(t)}}}}else for(let n of t){let t=s(n,y).Cast(e);a.push(t)}return a}static Identity(t){return t}static GenerateNativeFunctionsIfNecessary(){if(null==this._nativeFunctions){this._nativeFunctions=new Map,this.AddIntBinaryOp(this.Add,(t,e)=>t+e),this.AddIntBinaryOp(this.Subtract,(t,e)=>t-e),this.AddIntBinaryOp(this.Multiply,(t,e)=>t*e),this.AddIntBinaryOp(this.Divide,(t,e)=>Math.round(t/e)),this.AddIntBinaryOp(this.Mod,(t,e)=>t%e),this.AddIntUnaryOp(this.Negate,t=>-t),this.AddIntBinaryOp(this.Equal,(t,e)=>t==e?1:0),this.AddIntBinaryOp(this.Greater,(t,e)=>t>e?1:0),this.AddIntBinaryOp(this.Less,(t,e)=>t<e?1:0),this.AddIntBinaryOp(this.GreaterThanOrEquals,(t,e)=>t>=e?1:0),this.AddIntBinaryOp(this.LessThanOrEquals,(t,e)=>t<=e?1:0),this.AddIntBinaryOp(this.NotEquals,(t,e)=>t!=e?1:0),this.AddIntUnaryOp(this.Not,t=>0==t?1:0),this.AddIntBinaryOp(this.And,(t,e)=>0!=t&&0!=e?1:0),this.AddIntBinaryOp(this.Or,(t,e)=>0!=t||0!=e?1:0),this.AddIntBinaryOp(this.Max,(t,e)=>Math.max(t,e)),this.AddIntBinaryOp(this.Min,(t,e)=>Math.min(t,e)),this.AddIntBinaryOp(this.Pow,(t,e)=>Math.pow(t,e)),this.AddIntUnaryOp(this.Floor,D.Identity),this.AddIntUnaryOp(this.Ceiling,D.Identity),this.AddIntUnaryOp(this.Int,D.Identity),this.AddIntUnaryOp(this.Float,t=>t),this.AddFloatBinaryOp(this.Add,(t,e)=>t+e),this.AddFloatBinaryOp(this.Subtract,(t,e)=>t-e),this.AddFloatBinaryOp(this.Multiply,(t,e)=>t*e),this.AddFloatBinaryOp(this.Divide,(t,e)=>t/e),this.AddFloatBinaryOp(this.Mod,(t,e)=>t%e),this.AddFloatUnaryOp(this.Negate,t=>-t),this.AddFloatBinaryOp(this.Equal,(t,e)=>t==e?1:0),this.AddFloatBinaryOp(this.Greater,(t,e)=>t>e?1:0),this.AddFloatBinaryOp(this.Less,(t,e)=>t<e?1:0),this.AddFloatBinaryOp(this.GreaterThanOrEquals,(t,e)=>t>=e?1:0),this.AddFloatBinaryOp(this.LessThanOrEquals,(t,e)=>t<=e?1:0),this.AddFloatBinaryOp(this.NotEquals,(t,e)=>t!=e?1:0),this.AddFloatUnaryOp(this.Not,t=>0==t?1:0),this.AddFloatBinaryOp(this.And,(t,e)=>0!=t&&0!=e?1:0),this.AddFloatBinaryOp(this.Or,(t,e)=>0!=t||0!=e?1:0),this.AddFloatBinaryOp(this.Max,(t,e)=>Math.max(t,e)),this.AddFloatBinaryOp(this.Min,(t,e)=>Math.min(t,e)),this.AddFloatBinaryOp(this.Pow,(t,e)=>Math.pow(t,e)),this.AddFloatUnaryOp(this.Floor,t=>Math.floor(t)),this.AddFloatUnaryOp(this.Ceiling,t=>Math.ceil(t)),this.AddFloatUnaryOp(this.Int,t=>Math.floor(t)),this.AddFloatUnaryOp(this.Float,D.Identity),this.AddStringBinaryOp(this.Add,(t,e)=>t+e),this.AddStringBinaryOp(this.Equal,(t,e)=>t===e?1:0),this.AddStringBinaryOp(this.NotEquals,(t,e)=>t!==e?1:0),this.AddStringBinaryOp(this.Has,(t,e)=>t.includes(e)?1:0),this.AddStringBinaryOp(this.Hasnt,(t,e)=>t.includes(e)?0:1),this.AddListBinaryOp(this.Add,(t,e)=>t.Union(e)),this.AddListBinaryOp(this.Subtract,(t,e)=>t.Without(e)),this.AddListBinaryOp(this.Has,(t,e)=>t.Contains(e)?1:0),this.AddListBinaryOp(this.Hasnt,(t,e)=>t.Contains(e)?0:1),this.AddListBinaryOp(this.Intersect,(t,e)=>t.Intersect(e)),this.AddListBinaryOp(this.Equal,(t,e)=>t.Equals(e)?1:0),this.AddListBinaryOp(this.Greater,(t,e)=>t.GreaterThan(e)?1:0),this.AddListBinaryOp(this.Less,(t,e)=>t.LessThan(e)?1:0),this.AddListBinaryOp(this.GreaterThanOrEquals,(t,e)=>t.GreaterThanOrEquals(e)?1:0),this.AddListBinaryOp(this.LessThanOrEquals,(t,e)=>t.LessThanOrEquals(e)?1:0),this.AddListBinaryOp(this.NotEquals,(t,e)=>t.Equals(e)?0:1),this.AddListBinaryOp(this.And,(t,e)=>t.Count>0&&e.Count>0?1:0),this.AddListBinaryOp(this.Or,(t,e)=>t.Count>0||e.Count>0?1:0),this.AddListUnaryOp(this.Not,t=>0==t.Count?1:0),this.AddListUnaryOp(this.Invert,t=>t.inverse),this.AddListUnaryOp(this.All,t=>t.all),this.AddListUnaryOp(this.ListMin,t=>t.MinAsList()),this.AddListUnaryOp(this.ListMax,t=>t.MaxAsList()),this.AddListUnaryOp(this.Count,t=>t.Count),this.AddListUnaryOp(this.ValueOfList,t=>t.maxItem.Value);let t=(t,e)=>t.Equals(e)?1:0,e=(t,e)=>t.Equals(e)?0:1;this.AddOpToNativeFunc(this.Equal,2,i.DivertTarget,t),this.AddOpToNativeFunc(this.NotEquals,2,i.DivertTarget,e)}}AddOpFuncForType(t,e){null==this._operationFuncs&&(this._operationFuncs=new Map),this._operationFuncs.set(t,e)}static AddOpToNativeFunc(t,e,n,i){if(null===this._nativeFunctions)return d(\"NativeFunctionCall._nativeFunctions\");let a=this._nativeFunctions.get(t);a||(a=new D(t,e),this._nativeFunctions.set(t,a)),a.AddOpFuncForType(n,i)}static AddIntBinaryOp(t,e){this.AddOpToNativeFunc(t,2,i.Int,e)}static AddIntUnaryOp(t,e){this.AddOpToNativeFunc(t,1,i.Int,e)}static AddFloatBinaryOp(t,e){this.AddOpToNativeFunc(t,2,i.Float,e)}static AddFloatUnaryOp(t,e){this.AddOpToNativeFunc(t,1,i.Float,e)}static AddStringBinaryOp(t,e){this.AddOpToNativeFunc(t,2,i.String,e)}static AddListBinaryOp(t,e){this.AddOpToNativeFunc(t,2,i.List,e)}static AddListUnaryOp(t,e){this.AddOpToNativeFunc(t,1,i.List,e)}toString(){return'Native \"'+this.name+'\"'}}D.Add=\"+\",D.Subtract=\"-\",D.Divide=\"/\",D.Multiply=\"*\",D.Mod=\"%\",D.Negate=\"_\",D.Equal=\"==\",D.Greater=\">\",D.Less=\"<\",D.GreaterThanOrEquals=\">=\",D.LessThanOrEquals=\"<=\",D.NotEquals=\"!=\",D.Not=\"!\",D.And=\"&&\",D.Or=\"||\",D.Min=\"MIN\",D.Max=\"MAX\",D.Pow=\"POW\",D.Floor=\"FLOOR\",D.Ceiling=\"CEILING\",D.Int=\"INT\",D.Float=\"FLOAT\",D.Has=\"?\",D.Hasnt=\"!?\",D.Intersect=\"^\",D.ListMin=\"LIST_MIN\",D.ListMax=\"LIST_MAX\",D.All=\"LIST_ALL\",D.Count=\"LIST_COUNT\",D.ValueOfList=\"LIST_VALUE\",D.Invert=\"LIST_INVERT\",D._nativeFunctions=null;class M extends p{constructor(t){super(),this.text=t.toString()||\"\"}toString(){return\"# \"+this.text}}class G extends p{constructor(){super(...arguments),this.text=\"\",this.index=0,this.threadAtGeneration=null,this.sourcePath=\"\",this.targetPath=null,this.isInvisibleDefault=!1,this.originalThreadIndex=0}get pathStringOnChoice(){return null===this.targetPath?d(\"Choice.targetPath\"):this.targetPath.toString()}set pathStringOnChoice(t){this.targetPath=new e(t)}}class B{constructor(t,e){this._name=t||\"\",this._items=null,this._itemNameToValues=e||new Map}get name(){return this._name}get items(){if(null==this._items){this._items=new Map;for(let[t,e]of this._itemNameToValues){let n=new f(this.name,t);this._items.set(n.serialized(),e)}}return this._items}ValueForItem(t){if(!t.itemName)return 0;let e=this._itemNameToValues.get(t.itemName);return void 0!==e?e:0}ContainsItem(t){return!!t.itemName&&(t.originName==this.name&&this._itemNameToValues.has(t.itemName))}ContainsItemWithName(t){return this._itemNameToValues.has(t)}TryGetItemWithValue(t,e){for(let[e,n]of this._itemNameToValues)if(n==t)return{result:new f(this.name,e),exists:!0};return{result:f.Null,exists:!1}}TryGetValueForItem(t,e){if(!t.itemName)return{result:0,exists:!1};let n=this._itemNameToValues.get(t.itemName);return n?{result:n,exists:!0}:{result:0,exists:!1}}}class W{constructor(t){this._lists=new Map,this._allUnambiguousListValueCache=new Map;for(let e of t){this._lists.set(e.name,e);for(let[t,n]of e.items){let e=f.fromSerializedKey(t),i=new O(e,n);if(!e.itemName)throw new Error(\"item.itemName is null or undefined.\");this._allUnambiguousListValueCache.set(e.itemName,i),this._allUnambiguousListValueCache.set(e.fullName,i)}}}get lists(){let t=[];for(let[e,n]of this._lists)t.push(n);return t}TryListGetDefinition(t,e){if(null===t)return{result:e,exists:!1};let n=this._lists.get(t);return n?{result:n,exists:!0}:{result:e,exists:!1}}FindSingleItemListWithName(t){if(null===t)return d(\"name\");let e=this._allUnambiguousListValueCache.get(t);return void 0!==e?e:null}}class j{static ListToJArray(t){let e=[];for(let n of t)e.push(this.RuntimeObjectToJToken(n));return e}static JArrayToRuntimeObjList(t,e=!1){let n=t.length;e&&n--;let i=[];for(let e=0;e<n;e++){let n=t[e],a=this.JTokenToRuntimeObject(n);if(null===a)return d(\"runtimeObj\");i.push(a)}return i}static DictionaryRuntimeObjsToJObject(t){let e={};for(let[n,i]of t){let t=r(i,p);null!=t&&(e[n]=this.RuntimeObjectToJToken(t))}return e}static JObjectToDictionaryRuntimeObjs(t){let e=new Map;for(let n in t)if(t.hasOwnProperty(n)){let i=this.JTokenToRuntimeObject(t[n]);if(null===i)return d(\"inkObject\");e.set(n,i)}return e}static JObjectToIntDictionary(t){let e=new Map;for(let n in t)t.hasOwnProperty(n)&&e.set(n,parseInt(t[n]));return e}static IntDictionaryToJObject(t){let e={};for(let[n,i]of t)e[n]=l(i);return e}static JTokenToRuntimeObject(t){if(\"number\"==typeof t&&!isNaN(t))return y.Create(t);if(\"string\"==typeof t){let e=t.toString(),n=e[0];if(\"^\"==n)return new _(e.substring(1));if(\"\\n\"==n&&1==e.length)return new _(\"\\n\");if(\"<>\"==e)return new P;for(let t=0;t<j._controlCommandNames.length;++t){if(e==j._controlCommandNames[t])return new A(t)}if(\"L^\"==e&&(e=\"^\"),D.CallExistsWithName(e))return D.CallWithName(e);if(\"->->\"==e)return A.PopTunnel();if(\"~ret\"==e)return A.PopFunction();if(\"void\"==e)return new R}if(\"object\"==typeof t&&!Array.isArray(t)){let n,i=t;if(i[\"^->\"])return n=i[\"^->\"],new w(new e(n.toString()));if(i[\"^var\"]){n=i[\"^var\"];let t=new E(n.toString());return\"ci\"in i&&(n=i.ci,t.contextIndex=parseInt(n)),t}let r=!1,s=!1,l=a.Function,o=!1;if((n=i[\"->\"])?r=!0:(n=i[\"f()\"])?(r=!0,s=!0,l=a.Function):(n=i[\"->t->\"])?(r=!0,s=!0,l=a.Tunnel):(n=i[\"x()\"])&&(r=!0,o=!0,s=!1,l=a.Function),r){let t=new I;t.pushesToStack=s,t.stackPushType=l,t.isExternal=o;let e=n.toString();return(n=i.var)?t.variableDivertName=e:t.targetPathString=e,t.isConditional=!!i.c,o&&(n=i.exArgs)&&(t.externalArgs=parseInt(n)),t}if(n=i[\"*\"]){let t=new F;return t.pathStringOnChoice=n.toString(),(n=i.flg)&&(t.flags=parseInt(n)),t}if(n=i[\"VAR?\"])return new V(n.toString());if(n=i[\"CNT?\"]){let t=new V;return t.pathStringForCount=n.toString(),t}let u=!1,h=!1;if((n=i[\"VAR=\"])?(u=!0,h=!0):(n=i[\"temp=\"])&&(u=!0,h=!1),u){let t=n.toString(),e=!i.re,a=new L(t,e);return a.isGlobal=h,a}if(void 0!==i[\"#\"])return n=i[\"#\"],new M(n.toString());if(n=i.list){let t=n,e=new g;if(n=i.origins){let t=n;e.SetInitialOriginNames(t)}for(let n in t)if(t.hasOwnProperty(n)){let i=t[n],a=new f(n),r=parseInt(i);e.Add(a,r)}return new O(e)}if(null!=i.originalChoicePath)return this.JObjectToChoice(i)}if(Array.isArray(t))return this.JArrayToContainer(t);if(null==t)return null;throw new Error(\"Failed to convert token to runtime object: \"+JSON.stringify(t))}static RuntimeObjectToJToken(t){let e=r(t,N);if(e)return this.ContainerToJArray(e);let n=r(t,I);if(n){let t,e=\"->\";n.isExternal?e=\"x()\":n.pushesToStack&&(n.stackPushType==a.Function?e=\"f()\":n.stackPushType==a.Tunnel&&(e=\"->t->\")),t=n.hasVariableTarget?n.variableDivertName:n.targetPathString;let i={};return i[e]=t,n.hasVariableTarget&&(i.var=!0),n.isConditional&&(i.c=!0),n.externalArgs>0&&(i.exArgs=n.externalArgs),i}let i=r(t,F);if(i){let t={};return t[\"*\"]=i.pathStringOnChoice,t.flg=i.flags,t}let s=r(t,T);if(s)return s.value;let l=r(t,b);if(l)return l.value;let o=r(t,_);if(o)return o.isNewline?\"\\n\":\"^\"+o.value;let u=r(t,O);if(u)return this.InkListToJObject(u);let h=r(t,w);if(h){let t={};return null===h.value?d(\"divTargetVal.value\"):(t[\"^->\"]=h.value.componentsString,t)}let c=r(t,E);if(c){let t={};return t[\"^var\"]=c.value,t.ci=c.contextIndex,t}if(r(t,P))return\"<>\";let p=r(t,A);if(p)return j._controlCommandNames[p.commandType];let m=r(t,D);if(m){let t=m.name;return\"^\"==t&&(t=\"L^\"),t}let f=r(t,V);if(f){let t={},e=f.pathStringForCount;return null!=e?t[\"CNT?\"]=e:t[\"VAR?\"]=f.name,t}let g=r(t,L);if(g){let t={};return t[g.isGlobal?\"VAR=\":\"temp=\"]=g.variableName,g.isNewDeclaration||(t.re=!0),t}if(r(t,R))return\"void\";let C=r(t,M);if(C){let t={};return t[\"#\"]=C.text,t}let v=r(t,G);if(v)return this.ChoiceToJObject(v);throw new Error(\"Failed to convert runtime object to Json token: \"+t)}static ContainerToJArray(t){let e=this.ListToJArray(t.content),n=t.namedOnlyContent,i=t.countFlags;if(null!=n&&n.size>0||i>0||null!=t.name){let a;if(null!=n){a=this.DictionaryRuntimeObjsToJObject(n);for(let t in a)if(a.hasOwnProperty(t)){let e=a[t];if(null!=e){let t=e[e.length-1];null!=t&&(delete t[\"#n\"],0==Object.keys(t).length&&(e[e.length-1]=null))}}}else a={};i>0&&(a[\"#f\"]=i),null!=t.name&&(a[\"#n\"]=t.name),e.push(a)}else e.push(null);return e}static JArrayToContainer(t){let e=new N;e.content=this.JArrayToRuntimeObjList(t,!0);let n=t[t.length-1];if(null!=n){let t=new Map;for(let i in n)if(\"#f\"==i)e.countFlags=parseInt(n[i]);else if(\"#n\"==i)e.name=n[i].toString();else{let e=this.JTokenToRuntimeObject(n[i]),a=r(e,N);a&&(a.name=i),t.set(i,e)}e.namedOnlyContent=t}return e}static JObjectToChoice(t){let e=new G;return e.text=t.text.toString(),e.index=parseInt(t.index),e.sourcePath=t.originalChoicePath.toString(),e.originalThreadIndex=parseInt(t.originalThreadIndex),e.pathStringOnChoice=t.targetPath.toString(),e}static ChoiceToJObject(t){let e={};return e.text=t.text,e.index=t.index,e.originalChoicePath=t.sourcePath,e.originalThreadIndex=t.originalThreadIndex,e.targetPath=t.pathStringOnChoice,e}static InkListToJObject(t){let e=t.value;if(null===e)return d(\"rawList\");let n={},i={};for(let[t,n]of e){i[f.fromSerializedKey(t).toString()]=n}return n.list=i,0==e.Count&&null!=e.originNames&&e.originNames.length>0&&(n.origins=e.originNames),n}static ListDefinitionsToJToken(t){let e={};for(let n of t.lists){let t={};for(let[e,i]of n.items){let n=f.fromSerializedKey(e);if(null===n.itemName)return d(\"item.itemName\");t[n.itemName]=i}e[n.name]=t}return e}static JTokenToListDefinitions(t){let e=t,n=[];for(let t in e)if(e.hasOwnProperty(t)){let i=t.toString(),a=e[t],r=new Map;for(let n in a)if(e.hasOwnProperty(t)){let t=a[n];r.set(n,parseInt(t))}let s=new B(i,r);n.push(s)}return new W(n)}}j._controlCommandNames=(()=>{let t=[];t[A.CommandType.EvalStart]=\"ev\",t[A.CommandType.EvalOutput]=\"out\",t[A.CommandType.EvalEnd]=\"/ev\",t[A.CommandType.Duplicate]=\"du\",t[A.CommandType.PopEvaluatedValue]=\"pop\",t[A.CommandType.PopFunction]=\"~ret\",t[A.CommandType.PopTunnel]=\"->->\",t[A.CommandType.BeginString]=\"str\",t[A.CommandType.EndString]=\"/str\",t[A.CommandType.NoOp]=\"nop\",t[A.CommandType.ChoiceCount]=\"choiceCnt\",t[A.CommandType.Turns]=\"turn\",t[A.CommandType.TurnsSince]=\"turns\",t[A.CommandType.ReadCount]=\"readc\",t[A.CommandType.Random]=\"rnd\",t[A.CommandType.SeedRandom]=\"srnd\",t[A.CommandType.VisitIndex]=\"visit\",t[A.CommandType.SequenceShuffleIndex]=\"seq\",t[A.CommandType.StartThread]=\"thread\",t[A.CommandType.Done]=\"done\",t[A.CommandType.End]=\"end\",t[A.CommandType.ListFromInt]=\"listInt\",t[A.CommandType.ListRange]=\"range\",t[A.CommandType.ListRandom]=\"lrnd\";for(let e=0;e<A.CommandType.TOTAL_VALUES;++e)if(null==t[e])throw new Error(\"Control command not accounted for in serialisation\");return t})();class J{constructor(){if(this._threadCounter=0,this._startOfRoot=k.Null,arguments[0]instanceof H){let t=arguments[0];this._startOfRoot=k.StartOf(t.rootContentContainer),this.Reset()}else{let t=arguments[0];this._threads=[];for(let e of t._threads)this._threads.push(e.Copy());this._startOfRoot=t._startOfRoot}}get elements(){return this.callStack}get depth(){return this.elements.length}get currentElement(){let t=this._threads[this._threads.length-1].callstack;return t[t.length-1]}get currentElementIndex(){return this.callStack.length-1}get currentThread(){return this._threads[this._threads.length-1]}set currentThread(t){n.Assert(1==this._threads.length,\"Shouldn't be directly setting the current thread when we have a stack of them\"),this._threads.length=0,this._threads.push(t)}get canPop(){return this.callStack.length>1}Reset(){this._threads=[],this._threads.push(new J.Thread),this._threads[0].callstack.push(new J.Element(a.Tunnel,this._startOfRoot))}SetJsonToken(t,e){this._threads.length=0;let n=t.threads;for(let t of n){let n=t,i=new J.Thread(n,e);this._threads.push(i)}this._threadCounter=parseInt(t.threadCounter),this._startOfRoot=k.StartOf(e.rootContentContainer)}GetJsonToken(){let t={},e=[];for(let t of this._threads)e.push(t.jsonToken);return t.threads=e,t.threadCounter=this._threadCounter,t}PushThread(){let t=this.currentThread.Copy();this._threadCounter++,t.threadIndex=this._threadCounter,this._threads.push(t)}ForkThread(){let t=this.currentThread.Copy();return this._threadCounter++,t.threadIndex=this._threadCounter,t}PopThread(){if(!this.canPopThread)throw new Error(\"Can't pop thread\");this._threads.splice(this._threads.indexOf(this.currentThread),1)}get canPopThread(){return this._threads.length>1&&!this.elementIsEvaluateFromGame}get elementIsEvaluateFromGame(){return this.currentElement.type==a.FunctionEvaluationFromGame}Push(t,e=0,n=0){let i=new J.Element(t,this.currentElement.currentPointer,!1);i.evaluationStackHeightWhenPushed=e,i.functionStartInOutputStream=n,this.callStack.push(i)}CanPop(t=null){return!!this.canPop&&(null==t||this.currentElement.type==t)}Pop(t=null){if(!this.CanPop(t))throw new Error(\"Mismatched push/pop in Callstack\");this.callStack.pop()}GetTemporaryVariableWithName(t,e=-1){-1==e&&(e=this.currentElementIndex+1);let n=v(this.callStack[e-1].temporaryVariables,t,null);return n.exists?n.result:null}SetTemporaryVariable(t,e,n,i=-1){-1==i&&(i=this.currentElementIndex+1);let a=this.callStack[i-1];if(!n&&!a.temporaryVariables.get(t))throw new C(\"Could not find temporary variable to set: \"+t);let r=v(a.temporaryVariables,t,null);r.exists&&O.RetainListOriginsForAssignment(r.result,e),a.temporaryVariables.set(t,e)}ContextForVariableNamed(t){return this.currentElement.temporaryVariables.get(t)?this.currentElementIndex+1:0}ThreadWithIndex(t){return this._threads.filter(e=>{if(e.threadIndex==t)return e})[0]}get callStack(){return this.currentThread.callstack}get callStackTrace(){let t=new m;for(let e=0;e<this._threads.length;e++){let n=this._threads[e],i=e==this._threads.length-1;t.AppendFormat(\"=== THREAD {0}/{1} {2}===\\n\",e+1,this._threads.length,i?\"(current) \":\"\");for(let e=0;e<n.callstack.length;e++){n.callstack[e].type==a.Function?t.Append(\"  [FUNCTION] \"):t.Append(\"  [TUNNEL] \");let i=n.callstack[e].currentPointer;if(!i.isNull){if(t.Append(\"<SOMEWHERE IN \"),null===i.container)return d(\"pointer.container\");t.Append(i.container.path.toString()),t.AppendLine(\">\")}}}return t.toString()}}!function(t){class n{constructor(t,e,n=!1){this.evaluationStackHeightWhenPushed=0,this.functionStartInOutputStream=0,this.currentPointer=e.copy(),this.inExpressionEvaluation=n,this.temporaryVariables=new Map,this.type=t}Copy(){let t=new n(this.type,this.currentPointer,this.inExpressionEvaluation);return t.temporaryVariables=new Map(this.temporaryVariables),t.evaluationStackHeightWhenPushed=this.evaluationStackHeightWhenPushed,t.functionStartInOutputStream=this.functionStartInOutputStream,t}}t.Element=n;class i{constructor(){if(this.threadIndex=0,this.previousPointer=k.Null,this.callstack=[],arguments[0]&&arguments[1]){let t=arguments[0],i=arguments[1];this.threadIndex=parseInt(t.threadIndex);let a=t.callstack;for(let t of a){let a,r=t,s=parseInt(r.type),l=k.Null,o=r.cPath;if(void 0!==o){a=o.toString();let t=i.ContentAtPath(new e(a));if(l.container=t.container,l.index=parseInt(r.idx),null==t.obj)throw new Error(\"When loading state, internal story location couldn't be found: \"+a+\". Has the story changed since this save data was created?\");if(t.approximate){if(null===l.container)return d(\"pointer.container\");i.Warning(\"When loading state, exact internal story location couldn't be found: '\"+a+\"', so it was approximated to '\"+l.container.path.toString()+\"' to recover. Has the story changed since this save data was created?\")}}let u=!!r.exp,h=new n(s,l,u),c=r.temp;h.temporaryVariables=j.JObjectToDictionaryRuntimeObjs(c),this.callstack.push(h)}let r=t.previousContentObject;if(void 0!==r){let t=new e(r.toString());this.previousPointer=i.PointerAtPath(t)}}}Copy(){let t=new i;t.threadIndex=this.threadIndex;for(let e of this.callstack)t.callstack.push(e.Copy());return t.previousPointer=this.previousPointer.copy(),t}get jsonToken(){let t={},e=[];for(let t of this.callstack){let n={};if(!t.currentPointer.isNull){if(null===t.currentPointer.container)return d(\"el.currentPointer.container\");n.cPath=t.currentPointer.container.path.componentsString,n.idx=t.currentPointer.index}n.exp=t.inExpressionEvaluation,n.type=t.type,n.temp=j.DictionaryRuntimeObjsToJObject(t.temporaryVariables),e.push(n)}if(t.callstack=e,t.threadIndex=this.threadIndex,!this.previousPointer.isNull){let e=this.previousPointer.Resolve();if(null===e)return d(\"this.previousPointer.Resolve()\");t.previousContentObject=e.path.toString()}return t}}t.Thread=i}(J||(J={}));class q{constructor(t,e){this.variableChangedEventCallbacks=[],this._batchObservingVariableChanges=!1,this._defaultGlobalVariables=new Map,this._changedVariables=new Set,this._globalVariables=new Map,this._callStack=t,this._listDefsOrigin=e;try{return new Proxy(this,{get:(t,e)=>e in t?t[e]:t.$(e),set:(t,e,n)=>(e in t?t[e]=n:t.$(e,n),!0)})}catch(t){}}variableChangedEvent(t,e){for(let n of this.variableChangedEventCallbacks)n(t,e)}get batchObservingVariableChanges(){return this._batchObservingVariableChanges}set batchObservingVariableChanges(t){if(this._batchObservingVariableChanges=t,t)this._changedVariables=new Set;else if(null!=this._changedVariables)for(let t of this._changedVariables){let e=this._globalVariables.get(t);e?this.variableChangedEvent(t,e):d(\"currentValue\")}}get callStack(){return this._callStack}set callStack(t){this._callStack=t}$(t,e){if(void 0===e){let e=this._globalVariables.get(t);return void 0===e&&(e=this._defaultGlobalVariables.get(t)),void 0!==e?e.valueObject:null}{if(void 0===this._defaultGlobalVariables.get(t))throw new C(\"Cannot assign to a variable (\"+t+\") that hasn't been declared in the story\");let n=y.Create(e);if(null==n)throw new C(null==e?\"Cannot pass null to VariableState\":\"Invalid value passed to VariableState: \"+e.toString());this.SetGlobal(t,n)}}CopyFrom(t){if(this._globalVariables=new Map(t._globalVariables),this._defaultGlobalVariables=new Map(t._defaultGlobalVariables),this.variableChangedEvent=t.variableChangedEvent,t.batchObservingVariableChanges!=this.batchObservingVariableChanges)if(t.batchObservingVariableChanges){if(this._batchObservingVariableChanges=!0,null===t._changedVariables)return d(\"toCopy._changedVariables\");this._changedVariables=new Set(t._changedVariables)}else this._batchObservingVariableChanges=!1,this._changedVariables=null}get jsonToken(){return j.DictionaryRuntimeObjsToJObject(this._globalVariables)}set jsonToken(t){this._globalVariables=j.JObjectToDictionaryRuntimeObjs(t)}TryGetDefaultVariableValue(t){let e=v(this._defaultGlobalVariables,t,null);return e.exists?e.result:null}GlobalVariableExistsWithName(t){return this._globalVariables.has(t)}GetVariableWithName(t,e=-1){let n=this.GetRawVariableWithName(t,e),i=r(n,E);return null!==i&&(n=this.ValueAtVariablePointer(i)),n}GetRawVariableWithName(t,e){let n=null;if(0==e||-1==e){let e=v(this._globalVariables,t,null);if(e.exists)return e.result;if(null===this._listDefsOrigin)return d(\"VariablesState._listDefsOrigin\");let n=this._listDefsOrigin.FindSingleItemListWithName(t);if(n)return n}return n=this._callStack.GetTemporaryVariableWithName(t,e)}ValueAtVariablePointer(t){return this.GetVariableWithName(t.variableName,t.contextIndex)}Assign(t,e){let n=t.variableName;if(null===n)return d(\"name\");let i=-1,a=!1;if(a=t.isNewDeclaration?t.isGlobal:this._globalVariables.has(n),t.isNewDeclaration){let t=r(e,E);if(null!==t){e=this.ResolveVariablePointer(t)}}else{let t=null;do{null!=(t=r(this.GetRawVariableWithName(n,i),E))&&(n=t.variableName,a=0==(i=t.contextIndex))}while(null!=t)}a?this.SetGlobal(n,e):this._callStack.SetTemporaryVariable(n,e,t.isNewDeclaration,i)}SnapshotDefaultGlobals(){this._defaultGlobalVariables=new Map(this._globalVariables)}RetainListOriginsForAssignment(t,e){let n=s(t,O),i=s(e,O);n.value&&i.value&&0==i.value.Count&&i.value.SetInitialOriginNames(n.value.originNames)}SetGlobal(t,e){let n=v(this._globalVariables,t,null);if(n.exists&&O.RetainListOriginsForAssignment(n.result,e),null===t)return d(\"variableName\");if(this._globalVariables.set(t,e),null!=this.variableChangedEvent&&e!==n.result)if(this.batchObservingVariableChanges){if(null===this._changedVariables)return d(\"this._changedVariables\");this._changedVariables.add(t)}else this.variableChangedEvent(t,e)}ResolveVariablePointer(t){let e=t.contextIndex;-1==e&&(e=this.GetContextIndexOfVariableNamed(t.variableName));let n=r(this.GetRawVariableWithName(t.variableName,e),E);return null!=n?n:new E(t.variableName,e)}GetContextIndexOfVariableNamed(t){return this._globalVariables.get(t)?0:this._callStack.currentElementIndex}ObserveVariableChange(t){this.variableChangedEventCallbacks.push(t)}}class K{constructor(t){this.seed=t%2147483647,this.seed<=0&&(this.seed+=2147483646)}next(){return this.seed=16807*this.seed%2147483647}nextFloat(){return(this.next()-1)/2147483646}}class U{constructor(t){this.kInkSaveStateVersion=8,this.kMinCompatibleLoadVersion=8,this._currentErrors=null,this._currentWarnings=null,this.divertedPointer=k.Null,this._currentTurnIndex=0,this.storySeed=0,this.previousRandom=0,this.didSafeExit=!1,this._currentText=null,this._currentTags=null,this._outputStreamTextDirty=!0,this._outputStreamTagsDirty=!0,this.story=t,this._outputStream=[],this.OutputStreamDirty(),this._evaluationStack=[],this.callStack=new J(t),this._variablesState=new q(this.callStack,t.listDefinitions),this._visitCounts=new Map,this._turnIndices=new Map,this._currentTurnIndex=-1;let e=(new Date).getTime();this.storySeed=new K(e).next()%100,this.previousRandom=0,this._currentChoices=[],this.GoToStart()}ToJson(t=!1){return JSON.stringify(this.jsonToken,null,t?2:0)}toJson(t=!1){return this.ToJson(t)}LoadJson(t){this.jsonToken=JSON.parse(t)}VisitCountAtPathString(t){let e=v(this.visitCounts,t,null);return e.exists?e.result:0}get callstackDepth(){return this.callStack.depth}get outputStream(){return this._outputStream}get currentChoices(){return this.canContinue?[]:this._currentChoices}get generatedChoices(){return this._currentChoices}get currentErrors(){return this._currentErrors}get currentWarnings(){return this._currentWarnings}get variablesState(){return this._variablesState}get evaluationStack(){return this._evaluationStack}get visitCounts(){return this._visitCounts}get turnIndices(){return this._turnIndices}get currentTurnIndex(){return this._currentTurnIndex}get currentPathString(){let t=this.currentPointer;return t.isNull?null:null===t.path?d(\"pointer.path\"):t.path.toString()}get currentPointer(){return this.callStack.currentElement.currentPointer.copy()}set currentPointer(t){this.callStack.currentElement.currentPointer=t.copy()}get previousPointer(){return this.callStack.currentThread.previousPointer.copy()}set previousPointer(t){this.callStack.currentThread.previousPointer=t.copy()}get canContinue(){return!this.currentPointer.isNull&&!this.hasError}get hasError(){return null!=this.currentErrors&&this.currentErrors.length>0}get hasWarning(){return null!=this.currentWarnings&&this.currentWarnings.length>0}get currentText(){if(this._outputStreamTextDirty){let t=new m;for(let e of this._outputStream){let n=r(e,_);null!==n&&t.Append(n.value)}this._currentText=this.CleanOutputWhitespace(t.toString()),this._outputStreamTextDirty=!1}return this._currentText}CleanOutputWhitespace(t){let e=new m,n=-1,i=0;for(let a=0;a<t.length;a++){let r=t.charAt(a),s=\" \"==r||\"\\t\"==r;s&&-1==n&&(n=a),s||(\"\\n\"!=r&&n>0&&n!=i&&e.Append(\" \"),n=-1),\"\\n\"==r&&(i=a+1),s||e.Append(r)}return e.toString()}get currentTags(){if(this._outputStreamTagsDirty){this._currentTags=[];for(let t of this._outputStream){let e=r(t,M);null!==e&&this._currentTags.push(e.text)}this._outputStreamTagsDirty=!1}return this._currentTags}get inExpressionEvaluation(){return this.callStack.currentElement.inExpressionEvaluation}set inExpressionEvaluation(t){this.callStack.currentElement.inExpressionEvaluation=t}GoToStart(){this.callStack.currentElement.currentPointer=k.StartOf(this.story.mainContentContainer)}Copy(){let t=new U(this.story);return t.outputStream.push.apply(t.outputStream,this._outputStream),this.OutputStreamDirty(),t._currentChoices.push.apply(t._currentChoices,this._currentChoices),this.hasError&&(t._currentErrors=[],t._currentErrors.push.apply(t._currentErrors,this.currentErrors||[])),this.hasWarning&&(t._currentWarnings=[],t._currentWarnings.push.apply(t._currentWarnings,this.currentWarnings||[])),t.callStack=new J(this.callStack),t._variablesState=new q(t.callStack,this.story.listDefinitions),t.variablesState.CopyFrom(this.variablesState),t.evaluationStack.push.apply(t.evaluationStack,this.evaluationStack),this.divertedPointer.isNull||(t.divertedPointer=this.divertedPointer.copy()),t.previousPointer=this.previousPointer.copy(),t._visitCounts=new Map(this.visitCounts),t._turnIndices=new Map(this.turnIndices),t._currentTurnIndex=this.currentTurnIndex,t.storySeed=this.storySeed,t.previousRandom=this.previousRandom,t.didSafeExit=this.didSafeExit,t}get jsonToken(){let t,e={};for(let e of this._currentChoices){if(null===e.threadAtGeneration)return d(\"c.threadAtGeneration\");e.originalThreadIndex=e.threadAtGeneration.threadIndex,null==this.callStack.ThreadWithIndex(e.originalThreadIndex)&&(null==t&&(t=new Map),t[e.originalThreadIndex.toString()]=e.threadAtGeneration.jsonToken)}if(null!=t&&(e.choiceThreads=t),e.callstackThreads=this.callStack.GetJsonToken(),e.variablesState=this.variablesState.jsonToken,e.evalStack=j.ListToJArray(this.evaluationStack),e.outputStream=j.ListToJArray(this._outputStream),e.currentChoices=j.ListToJArray(this._currentChoices),!this.divertedPointer.isNull){if(null===this.divertedPointer.path)return d(\"this.divertedPointer.path\");e.currentDivertTarget=this.divertedPointer.path.componentsString}return e.visitCounts=j.IntDictionaryToJObject(this.visitCounts),e.turnIndices=j.IntDictionaryToJObject(this.turnIndices),e.turnIdx=this.currentTurnIndex,e.storySeed=this.storySeed,e.previousRandom=this.previousRandom,e.inkSaveVersion=this.kInkSaveStateVersion,e.inkFormatVersion=this.story.inkVersionCurrent,e}set jsonToken(t){let n=t,i=n.inkSaveVersion;if(null==i)throw new C(\"ink save format incorrect, can't load.\");if(parseInt(i)<this.kMinCompatibleLoadVersion)throw new C(\"Ink save format isn't compatible with the current version (saw '\"+i+\"', but minimum is \"+this.kMinCompatibleLoadVersion+\"), so can't load.\");this.callStack.SetJsonToken(n.callstackThreads,this.story),this.variablesState.jsonToken=n.variablesState,this._evaluationStack=j.JArrayToRuntimeObjList(n.evalStack),this._outputStream=j.JArrayToRuntimeObjList(n.outputStream),this.OutputStreamDirty(),this._currentChoices=j.JArrayToRuntimeObjList(n.currentChoices);let a=n.currentDivertTarget;if(null!=a){let t=new e(a.toString());this.divertedPointer=this.story.PointerAtPath(t)}this._visitCounts=j.JObjectToIntDictionary(n.visitCounts),this._turnIndices=j.JObjectToIntDictionary(n.turnIndices),this._currentTurnIndex=parseInt(n.turnIdx),this.storySeed=parseInt(n.storySeed),this.previousRandom=parseInt(n.previousRandom);let r=n.choiceThreads;for(let t of this._currentChoices){let e=this.callStack.ThreadWithIndex(t.originalThreadIndex);if(null!=e)t.threadAtGeneration=e.Copy();else{let e=r[t.originalThreadIndex.toString()];t.threadAtGeneration=new J.Thread(e,this.story)}}}ResetErrors(){this._currentErrors=null,this._currentWarnings=null}ResetOutput(t=null){this._outputStream.length=0,null!==t&&this._outputStream.push.apply(this._outputStream,t),this.OutputStreamDirty()}PushToOutputStream(t){let e=r(t,_);if(null!==e){let t=this.TrySplittingHeadTailWhitespace(e);if(null!==t){for(let e of t)this.PushToOutputStreamIndividual(e);return void this.OutputStreamDirty()}}this.PushToOutputStreamIndividual(t),this.OutputStreamDirty()}PopFromOutputStream(t){this.outputStream.splice(this.outputStream.length-t,t),this.OutputStreamDirty()}TrySplittingHeadTailWhitespace(t){let e=t.value;if(null===e)return d(\"single.value\");let n=-1,i=-1;for(let t=0;t<e.length;++t){let a=e[t];if(\"\\n\"!=a){if(\" \"==a||\"\\t\"==a)continue;break}-1==n&&(n=t),i=t}let a=-1,r=-1;for(let t=0;t<e.length;++t){let n=e[t];if(\"\\n\"!=n){if(\" \"==n||\"\\t\"==n)continue;break}-1==a&&(a=t),r=t}if(-1==n&&-1==a)return null;let s=[],l=0,o=e.length;if(-1!=n){if(n>0){let t=new _(e.substring(0,n));s.push(t)}s.push(new _(\"\\n\")),l=i+1}if(-1!=a&&(o=r),o>l){let t=e.substring(l,o-l);s.push(new _(t))}if(-1!=a&&r>i&&(s.push(new _(\"\\n\")),a<e.length-1)){let t=e.length-a-1,n=new _(e.substring(a+1,t));s.push(n)}return s}PushToOutputStreamIndividual(t){let e=r(t,P),n=r(t,_),i=!0;if(e)this.TrimNewlinesFromOutputStream(),i=!0;else if(n){let t=-1,e=this.callStack.currentElement;e.type==a.Function&&(t=e.functionStartInOutputStream);let r=-1;for(let e=this._outputStream.length-1;e>=0;e--){let n=this._outputStream[e],i=n instanceof A?n:null;if(null!=(n instanceof P?n:null)){r=e;break}if(null!=i&&i.commandType==A.CommandType.BeginString){e>=t&&(t=-1);break}}let s=-1;if(-1!=(s=-1!=r&&-1!=t?Math.min(t,r):-1!=r?r:t)){if(n.isNewline)i=!1;else if(n.isNonWhitespace&&(r>-1&&this.RemoveExistingGlue(),t>-1)){let t=this.callStack.elements;for(let e=t.length-1;e>=0;e--){let n=t[e];if(n.type!=a.Function)break;n.functionStartInOutputStream=-1}}}else n.isNewline&&(!this.outputStreamEndsInNewline&&this.outputStreamContainsContent||(i=!1))}if(i){if(null===t)return d(\"obj\");this._outputStream.push(t),this.OutputStreamDirty()}}TrimNewlinesFromOutputStream(){let t=-1,e=this._outputStream.length-1;for(;e>=0;){let n=this._outputStream[e],i=r(n,A),a=r(n,_);if(null!=i||null!=a&&a.isNonWhitespace)break;null!=a&&a.isNewline&&(t=e),e--}if(t>=0)for(e=t;e<this._outputStream.length;){r(this._outputStream[e],_)?this._outputStream.splice(e,1):e++}this.OutputStreamDirty()}RemoveExistingGlue(){for(let t=this._outputStream.length-1;t>=0;t--){let e=this._outputStream[t];if(e instanceof P)this._outputStream.splice(t,1);else if(e instanceof A)break}this.OutputStreamDirty()}get outputStreamEndsInNewline(){if(this._outputStream.length>0)for(let t=this._outputStream.length-1;t>=0;t--){if(this._outputStream[t]instanceof A)break;let e=this._outputStream[t];if(e instanceof _){if(e.isNewline)return!0;if(e.isNonWhitespace)break}}return!1}get outputStreamContainsContent(){for(let t=0;t<this._outputStream.length;t++)if(this._outputStream[t]instanceof _)return!0;return!1}get inStringEvaluation(){for(let t=this._outputStream.length-1;t>=0;t--){let e=r(this._outputStream[t],A);if(e instanceof A&&e.commandType==A.CommandType.BeginString)return!0}return!1}PushEvaluationStack(t){let e=r(t,O);if(e){let t=e.value;if(null===t)return d(\"rawList\");if(null!=t.originNames){t.origins||(t.origins=[]),t.origins.length=0;for(let e of t.originNames){if(null===this.story.listDefinitions)return d(\"StoryState.story.listDefinitions\");let n=this.story.listDefinitions.TryListGetDefinition(e,null);if(null===n.result)return d(\"StoryState def.result\");t.origins.indexOf(n.result)<0&&t.origins.push(n.result)}}}if(null===t)return d(\"obj\");this.evaluationStack.push(t)}PopEvaluationStack(t){if(void 0===t){return u(this.evaluationStack.pop())}if(t>this.evaluationStack.length)throw new Error(\"trying to pop too many objects\");return u(this.evaluationStack.splice(this.evaluationStack.length-t,t))}PeekEvaluationStack(){return this.evaluationStack[this.evaluationStack.length-1]}ForceEnd(){this.callStack.Reset(),this._currentChoices.length=0,this.currentPointer=k.Null,this.previousPointer=k.Null,this.didSafeExit=!0}TrimWhitespaceFromFunctionEnd(){n.Assert(this.callStack.currentElement.type==a.Function);let t=this.callStack.currentElement.functionStartInOutputStream;-1==t&&(t=0);for(let e=this._outputStream.length-1;e>=t;e--){let t=this._outputStream[e],n=r(t,_),i=r(t,A);if(null!=n){if(i)break;if(!n.isNewline&&!n.isInlineWhitespace)break;this._outputStream.splice(e,1),this.OutputStreamDirty()}}}PopCallStack(t=null){this.callStack.currentElement.type==a.Function&&this.TrimWhitespaceFromFunctionEnd(),this.callStack.Pop(t)}SetChosenPath(t,e){this._currentChoices.length=0;let n=this.story.PointerAtPath(t);n.isNull||-1!=n.index||(n.index=0),this.currentPointer=n,e&&this._currentTurnIndex++}StartFunctionEvaluationFromGame(t,e){this.callStack.Push(a.FunctionEvaluationFromGame,this.evaluationStack.length),this.callStack.currentElement.currentPointer=k.StartOf(t),this.PassArgumentsToEvaluationStack(e)}PassArgumentsToEvaluationStack(t){if(null!=t)for(let e=0;e<t.length;e++){if(\"number\"!=typeof t[e]&&\"string\"!=typeof t[e])throw new Error(\"ink arguments when calling EvaluateFunction / ChoosePathStringWithParameters  must be int, float or string\");this.PushEvaluationStack(y.Create(t[e]))}}TryExitFunctionEvaluationFromGame(){return this.callStack.currentElement.type==a.FunctionEvaluationFromGame&&(this.currentPointer=k.Null,this.didSafeExit=!0,!0)}CompleteFunctionEvaluationFromGame(){if(this.callStack.currentElement.type!=a.FunctionEvaluationFromGame)throw new C(\"Expected external function evaluation to be complete. Stack trace: \"+this.callStack.callStackTrace);let t=this.callStack.currentElement.evaluationStackHeightWhenPushed,e=null;for(;this.evaluationStack.length>t;){let t=this.PopEvaluationStack();null===e&&(e=t)}if(this.PopCallStack(a.FunctionEvaluationFromGame),e){if(e instanceof R)return null;let t=s(e,y);return t.valueType==i.DivertTarget?t.valueObject.toString():t.valueObject}return null}AddError(t,e){e?(null==this._currentWarnings&&(this._currentWarnings=[]),this._currentWarnings.push(t)):(null==this._currentErrors&&(this._currentErrors=[]),this._currentErrors.push(t))}OutputStreamDirty(){this._outputStreamTextDirty=!0,this._outputStreamTagsDirty=!0}}class z{constructor(){this.startTime=void 0}get ElapsedMilliseconds(){return void 0===this.startTime?0:(new Date).getTime()-this.startTime}Start(){this.startTime=(new Date).getTime()}Stop(){this.startTime=void 0}}Number.isInteger||(Number.isInteger=function(t){return\"number\"==typeof t&&isFinite(t)&&t>-9007199254740992&&t<9007199254740992&&Math.floor(t)===t});class H extends p{constructor(){let t;super(),this.inkVersionCurrent=19,this.inkVersionMinimumCompatible=18,this._prevContainers=[],this.allowExternalFunctionFallbacks=!1,this._listDefinitions=null,this._variableObservers=null,this._hasValidatedExternals=!1,this._temporaryEvaluationContainer=null,this._asyncContinueActive=!1,this._stateAtLastNewline=null,this._recursiveContinueCount=0,this._profiler=null;let e=null,n=null;if(arguments[0]instanceof N)t=arguments[0],void 0!==arguments[1]&&(e=arguments[1]),this._mainContentContainer=t;else if(\"string\"==typeof arguments[0]){let t=arguments[0];n=JSON.parse(t)}else n=arguments[0];if(null!=e&&(this._listDefinitions=new W(e)),this._externals=new Map,null!==n){let t=n,e=t.inkVersion;if(null==e)throw new Error(\"ink version number not found. Are you sure it's a valid .ink.json file?\");let i=parseInt(e);if(i>this.inkVersionCurrent)throw new Error(\"Version of ink used to build story was newer than the current version of the engine\");if(i<this.inkVersionMinimumCompatible)throw new Error(\"Version of ink used to build story is too old to be loaded by this version of the engine\");i!=this.inkVersionCurrent&&console.warn(\"WARNING: Version of ink used to build story doesn't match current version of engine. Non-critical, but recommend synchronising.\");let a,r=t.root;if(null==r)throw new Error(\"Root node for ink not found. Are you sure it's a valid .ink.json file?\");(a=t.listDefs)&&(this._listDefinitions=j.JTokenToListDefinitions(a)),this._mainContentContainer=s(j.JTokenToRuntimeObject(r),N),this.ResetState()}}get currentChoices(){let t=[];if(null===this._state)return d(\"this._state\");for(let e of this._state.currentChoices)e.isInvisibleDefault||(e.index=t.length,t.push(e));return t}get currentText(){return this.IfAsyncWeCant(\"call currentText since it's a work in progress\"),this.state.currentText}get currentTags(){return this.IfAsyncWeCant(\"call currentTags since it's a work in progress\"),this.state.currentTags}get currentErrors(){return this.state.currentErrors}get currentWarnings(){return this.state.currentWarnings}get hasError(){return this.state.hasError}get hasWarning(){return this.state.hasWarning}get variablesState(){return this.state.variablesState}get listDefinitions(){return this._listDefinitions}get state(){return this._state}StartProfiling(){}EndProfiling(){}ToJsonString(){let t=j.RuntimeObjectToJToken(this._mainContentContainer),e={};return e.inkVersion=this.inkVersionCurrent,e.root=t,null!=this._listDefinitions&&(e.listDefs=j.ListDefinitionsToJToken(this._listDefinitions)),JSON.stringify(e)}ResetState(){this.IfAsyncWeCant(\"ResetState\"),this._state=new U(this),this._state.variablesState.ObserveVariableChange(this.VariableStateDidChangeEvent.bind(this)),this.ResetGlobals()}ResetErrors(){if(null===this._state)return d(\"this._state\");this._state.ResetErrors()}ResetCallstack(){if(this.IfAsyncWeCant(\"ResetCallstack\"),null===this._state)return d(\"this._state\");this._state.ForceEnd()}ResetGlobals(){if(this._mainContentContainer.namedContent.get(\"global decl\")){let t=this.state.currentPointer.copy();this.ChoosePath(new e(\"global decl\"),!1),this.ContinueInternal(),this.state.currentPointer=t}this.state.variablesState.SnapshotDefaultGlobals()}Continue(){return this.ContinueAsync(0),this.currentText}get canContinue(){return this.state.canContinue}get asyncContinueComplete(){return!this._asyncContinueActive}ContinueAsync(t){this._hasValidatedExternals||this.ValidateExternalBindings(),this.ContinueInternal(t)}ContinueInternal(t=0){null!=this._profiler&&this._profiler.PreContinue();let e=t>0;if(this._recursiveContinueCount++,!this._asyncContinueActive){if(this._asyncContinueActive=e,!this.canContinue)throw new C(\"Can't continue - should check canContinue before calling Continue\");this._state.didSafeExit=!1,this._state.ResetOutput(),1==this._recursiveContinueCount&&(this._state.variablesState.batchObservingVariableChanges=!0)}let n=new z;n.Start();let i=!1;do{try{i=this.ContinueSingleStep()}catch(t){if(!(t instanceof C))throw t;this.AddError(t.message,void 0,t.useEndLineNumber);break}if(i)break;if(this._asyncContinueActive&&n.ElapsedMilliseconds>t)break}while(this.canContinue);n.Stop(),!i&&this.canContinue||(null!=this._stateAtLastNewline&&(this.RestoreStateSnapshot(this._stateAtLastNewline),this._stateAtLastNewline=null),this.canContinue||(this.state.callStack.canPopThread&&this.AddError(\"Thread available to pop, threads should always be flat by the end of evaluation?\"),0!=this.state.generatedChoices.length||this.state.didSafeExit||null!=this._temporaryEvaluationContainer||(this.state.callStack.CanPop(a.Tunnel)?this.AddError(\"unexpectedly reached end of content. Do you need a '->->' to return from a tunnel?\"):this.state.callStack.CanPop(a.Function)?this.AddError(\"unexpectedly reached end of content. Do you need a '~ return'?\"):this.state.callStack.canPop?this.AddError(\"unexpectedly reached end of content for unknown reason. Please debug compiler!\"):this.AddError(\"ran out of content. Do you need a '-> DONE' or '-> END'?\"))),this.state.didSafeExit=!1,1==this._recursiveContinueCount&&(this._state.variablesState.batchObservingVariableChanges=!1),this._asyncContinueActive=!1),this._recursiveContinueCount--,null!=this._profiler&&this._profiler.PostContinue()}ContinueSingleStep(){if(null!=this._profiler&&this._profiler.PreStep(),this.Step(),null!=this._profiler&&this._profiler.PostStep(),this.canContinue||this.state.callStack.elementIsEvaluateFromGame||this.TryFollowDefaultInvisibleChoice(),null!=this._profiler&&this._profiler.PreSnapshot(),!this.state.inStringEvaluation){if(null!=this._stateAtLastNewline){if(null===this._stateAtLastNewline.currentTags)return d(\"this._stateAtLastNewline.currentTags\");if(null===this.state.currentTags)return d(\"this.state.currentTags\");let t=this.CalculateNewlineOutputStateChange(this._stateAtLastNewline.currentText,this.state.currentText,this._stateAtLastNewline.currentTags.length,this.state.currentTags.length);if(t==H.OutputStateChange.ExtendedBeyondNewline)return this.RestoreStateSnapshot(this._stateAtLastNewline),!0;t==H.OutputStateChange.NewlineRemoved&&(this._stateAtLastNewline=null)}this.state.outputStreamEndsInNewline&&(this.canContinue?null==this._stateAtLastNewline&&(this._stateAtLastNewline=this.StateSnapshot()):this._stateAtLastNewline=null)}return null!=this._profiler&&this._profiler.PostSnapshot(),!1}CalculateNewlineOutputStateChange(t,e,n,i){if(null===t)return d(\"prevText\");if(null===e)return d(\"currText\");let a=e.length>=t.length&&\"\\n\"==e.charAt(t.length-1);if(n==i&&t.length==e.length&&a)return H.OutputStateChange.NoChange;if(!a)return H.OutputStateChange.NewlineRemoved;if(i>n)return H.OutputStateChange.ExtendedBeyondNewline;for(let n=t.length;n<e.length;n++){let t=e.charAt(n);if(\" \"!=t&&\"\\t\"!=t)return H.OutputStateChange.ExtendedBeyondNewline}return H.OutputStateChange.NoChange}ContinueMaximally(){this.IfAsyncWeCant(\"ContinueMaximally\");let t=new m;for(;this.canContinue;)t.Append(this.Continue());return t.toString()}ContentAtPath(t){return this.mainContentContainer.ContentAtPath(t)}KnotContainerWithName(t){let e=this.mainContentContainer.namedContent.get(t);return e instanceof N?e:null}PointerAtPath(t){if(0==t.length)return k.Null;let e=new k,n=t.length,i=null;return null===t.lastComponent?d(\"path.lastComponent\"):(t.lastComponent.isIndex?(n=t.length-1,i=this.mainContentContainer.ContentAtPath(t,void 0,n),e.container=i.container,e.index=t.lastComponent.index):(i=this.mainContentContainer.ContentAtPath(t),e.container=i.container,e.index=-1),null==i.obj||i.obj==this.mainContentContainer&&n>0?this.Error(\"Failed to find content at path '\"+t+\"', and no approximation of it was possible.\"):i.approximate&&this.Warning(\"Failed to find content at path '\"+t+\"', so it was approximated to: '\"+i.obj.path+\"'.\"),e)}StateSnapshot(){return this.state.Copy()}RestoreStateSnapshot(t){this._state=t}Step(){let t=!0,e=this.state.currentPointer.copy();if(e.isNull)return;let n=r(e.Resolve(),N);for(;n&&(this.VisitContainer(n,!0),0!=n.content.length);)n=r((e=k.StartOf(n)).Resolve(),N);this.state.currentPointer=e.copy(),null!=this._profiler&&this._profiler.Step(this.state.callStack);let i=e.Resolve(),a=this.PerformLogicAndFlowControl(i);if(this.state.currentPointer.isNull)return;a&&(t=!1);let s=r(i,F);if(s){let e=this.ProcessChoice(s);e&&this.state.generatedChoices.push(e),i=null,t=!1}if(i instanceof N&&(t=!1),t){let t=r(i,E);if(t&&-1==t.contextIndex){let e=this.state.callStack.ContextForVariableNamed(t.variableName);i=new E(t.variableName,e)}this.state.inExpressionEvaluation?this.state.PushEvaluationStack(i):this.state.PushToOutputStream(i)}this.NextContent();let l=r(i,A);l&&l.commandType==A.CommandType.StartThread&&this.state.callStack.PushThread()}VisitContainer(t,e){t.countingAtStartOnly&&!e||(t.visitsShouldBeCounted&&this.IncrementVisitCountForContainer(t),t.turnIndexShouldBeCounted&&this.RecordTurnIndexVisitToContainer(t))}VisitChangedContainersDueToDivert(){let t=this.state.previousPointer.copy(),e=this.state.currentPointer.copy();if(e.isNull||-1==e.index)return;if(this._prevContainers.length=0,!t.isNull){let e=r(t.Resolve(),N)||r(t.container,N);for(;e;)this._prevContainers.push(e),e=r(e.parent,N)}let n=e.Resolve();if(null==n)return;let i=r(n.parent,N);for(;i&&(this._prevContainers.indexOf(i)<0||i.countingAtStartOnly);){let t=i.content.length>0&&n==i.content[0];this.VisitContainer(i,t),n=i,i=r(i.parent,N)}}ProcessChoice(t){let e=!0;if(t.hasCondition){let t=this.state.PopEvaluationStack();this.IsTruthy(t)||(e=!1)}let n=\"\",i=\"\";if(t.hasChoiceOnlyContent){i=s(this.state.PopEvaluationStack(),_).value||\"\"}if(t.hasStartContent){n=s(this.state.PopEvaluationStack(),_).value||\"\"}if(t.onceOnly){this.VisitCountForContainer(t.choiceTarget)>0&&(e=!1)}if(!e)return null;let a=new G;return a.targetPath=t.pathOnChoice,a.sourcePath=t.path.toString(),a.isInvisibleDefault=t.isInvisibleDefault,a.threadAtGeneration=this.state.callStack.ForkThread(),a.text=(n+i).replace(/^[ \\t]+|[ \\t]+$/g,\"\"),a}IsTruthy(t){if(t instanceof y){let e=t;if(e instanceof w){let t=e;return this.Error(\"Shouldn't use a divert target (to \"+t.targetPath+\") as a conditional value. Did you intend a function call 'likeThis()' or a read count check 'likeThis'? (no arrows)\"),!1}return e.isTruthy}return!1}PerformLogicAndFlowControl(t){if(null==t)return!1;if(t instanceof I){let e=t;if(e.isConditional){let t=this.state.PopEvaluationStack();if(!this.IsTruthy(t))return!0}if(e.hasVariableTarget){let t=e.variableDivertName,n=this.state.variablesState.GetVariableWithName(t);if(null==n)this.Error(\"Tried to divert using a target from a variable that could not be found (\"+t+\")\");else if(!(n instanceof w)){let e=r(n,T),i=\"Tried to divert to a target from a variable, but the variable (\"+t+\") didn't contain a divert target, it \";e instanceof T&&0==e.value?i+=\"was empty/null (the value 0).\":i+=\"contained '\"+n+\"'.\",this.Error(i)}let i=s(n,w);this.state.divertedPointer=this.PointerAtPath(i.targetPath)}else{if(e.isExternal)return this.CallExternalFunction(e.targetPathString,e.externalArgs),!0;this.state.divertedPointer=e.targetPointer.copy()}return e.pushesToStack&&this.state.callStack.Push(e.stackPushType,void 0,this.state.outputStream.length),this.state.divertedPointer.isNull&&!e.isExternal&&(e&&e.debugMetadata&&null!=e.debugMetadata.sourceName?this.Error(\"Divert target doesn't exist: \"+e.debugMetadata.sourceName):this.Error(\"Divert resolution failed: \"+e)),!0}if(t instanceof A){let e=t;switch(e.commandType){case A.CommandType.EvalStart:this.Assert(!1===this.state.inExpressionEvaluation,\"Already in expression evaluation?\"),this.state.inExpressionEvaluation=!0;break;case A.CommandType.EvalEnd:this.Assert(!0===this.state.inExpressionEvaluation,\"Not in expression evaluation mode\"),this.state.inExpressionEvaluation=!1;break;case A.CommandType.EvalOutput:if(this.state.evaluationStack.length>0){let t=this.state.PopEvaluationStack();if(!(t instanceof R)){let e=new _(t.toString());this.state.PushToOutputStream(e)}}break;case A.CommandType.NoOp:break;case A.CommandType.Duplicate:this.state.PushEvaluationStack(this.state.PeekEvaluationStack());break;case A.CommandType.PopEvaluatedValue:this.state.PopEvaluationStack();break;case A.CommandType.PopFunction:case A.CommandType.PopTunnel:let t=e.commandType==A.CommandType.PopFunction?a.Function:a.Tunnel,n=null;if(t==a.Tunnel){let t=this.state.PopEvaluationStack();null===(n=r(t,w))&&this.Assert(t instanceof R,\"Expected void if ->-> doesn't override target\")}if(this.state.TryExitFunctionEvaluationFromGame())break;if(this.state.callStack.currentElement.type==t&&this.state.callStack.canPop)this.state.PopCallStack(),n&&(this.state.divertedPointer=this.PointerAtPath(n.targetPath));else{let e=new Map;e.set(a.Function,\"function return statement (~ return)\"),e.set(a.Tunnel,\"tunnel onwards statement (->->)\");let n=e.get(this.state.callStack.currentElement.type);this.state.callStack.canPop||(n=\"end of flow (-> END or choice)\");let i=\"Found \"+e.get(t)+\", when expected \"+n;this.Error(i)}break;case A.CommandType.BeginString:this.state.PushToOutputStream(e),this.Assert(!0===this.state.inExpressionEvaluation,\"Expected to be in an expression when evaluating a string\"),this.state.inExpressionEvaluation=!1;break;case A.CommandType.EndString:let i=[],l=0;for(let t=this.state.outputStream.length-1;t>=0;--t){let e=this.state.outputStream[t];l++;let n=r(e,A);if(n&&n.commandType==A.CommandType.BeginString)break;e instanceof _&&i.push(e)}this.state.PopFromOutputStream(l),i=i.reverse();let o=new m;for(let t of i)o.Append(t.toString());this.state.inExpressionEvaluation=!0,this.state.PushEvaluationStack(new _(o.toString()));break;case A.CommandType.ChoiceCount:let u=this.state.generatedChoices.length;this.state.PushEvaluationStack(new T(u));break;case A.CommandType.Turns:this.state.PushEvaluationStack(new T(this.state.currentTurnIndex+1));break;case A.CommandType.TurnsSince:case A.CommandType.ReadCount:let h=this.state.PopEvaluationStack();if(!(h instanceof w)){let t=\"\";h instanceof T&&(t=\". Did you accidentally pass a read count ('knot_name') instead of a target ('-> knot_name')?\"),this.Error(\"TURNS_SINCE / READ_COUNT expected a divert target (knot, stitch, label name), but saw \"+h+t);break}let c,p=s(h,w),v=r(this.ContentAtPath(p.targetPath).correctObj,N);null!=v?c=e.commandType==A.CommandType.TurnsSince?this.TurnsSinceForContainer(v):this.VisitCountForContainer(v):(c=e.commandType==A.CommandType.TurnsSince?-1:0,this.Warning(\"Failed to find container for \"+e.toString()+\" lookup at \"+p.targetPath.toString())),this.state.PushEvaluationStack(new T(c));break;case A.CommandType.Random:{let t=r(this.state.PopEvaluationStack(),T),e=r(this.state.PopEvaluationStack(),T);if(null==e||e instanceof T==!1)return this.Error(\"Invalid value for minimum parameter of RANDOM(min, max)\");if(null==t||e instanceof T==!1)return this.Error(\"Invalid value for maximum parameter of RANDOM(min, max)\");if(null===t.value)return d(\"maxInt.value\");if(null===e.value)return d(\"minInt.value\");let n=t.value-e.value+1;n<=0&&this.Error(\"RANDOM was called with minimum as \"+e.value+\" and maximum as \"+t.value+\". The maximum must be larger\");let i=this.state.storySeed+this.state.previousRandom,a=new K(i).next(),s=a%n+e.value;this.state.PushEvaluationStack(new T(s)),this.state.previousRandom=a;break}case A.CommandType.SeedRandom:let S=r(this.state.PopEvaluationStack(),T);if(null==S||S instanceof T==!1)return this.Error(\"Invalid value passed to SEED_RANDOM\");if(null===S.value)return d(\"minInt.value\");this.state.storySeed=S.value,this.state.previousRandom=0,this.state.PushEvaluationStack(new R);break;case A.CommandType.VisitIndex:let b=this.VisitCountForContainer(this.state.currentPointer.container)-1;this.state.PushEvaluationStack(new T(b));break;case A.CommandType.SequenceShuffleIndex:let E=this.NextSequenceShuffleIndex();this.state.PushEvaluationStack(new T(E));break;case A.CommandType.StartThread:break;case A.CommandType.Done:this.state.callStack.canPopThread?this.state.callStack.PopThread():(this.state.didSafeExit=!0,this.state.currentPointer=k.Null);break;case A.CommandType.End:this.state.ForceEnd();break;case A.CommandType.ListFromInt:let x=r(this.state.PopEvaluationStack(),T),P=s(this.state.PopEvaluationStack(),_);if(null===x)throw new C(\"Passed non-integer when creating a list element from a numerical value.\");let I=null;if(null===this.listDefinitions)return d(\"this.listDefinitions\");let F=this.listDefinitions.TryListGetDefinition(P.value,null);if(!F.exists)throw new C(\"Failed to find LIST called \"+P.value);{if(null===x.value)return d(\"minInt.value\");let t=F.result.TryGetItemWithValue(x.value,f.Null);t.exists&&(I=new O(t.result,x.value))}null==I&&(I=new O),this.state.PushEvaluationStack(I);break;case A.CommandType.ListRange:let V=r(this.state.PopEvaluationStack(),y),L=r(this.state.PopEvaluationStack(),y),D=r(this.state.PopEvaluationStack(),O);if(null===D||null===L||null===V)throw new C(\"Expected list, minimum and maximum for LIST_RANGE\");if(null===D.value)return d(\"targetList.value\");let M=D.value.ListWithSubRange(L.valueObject,V.valueObject);this.state.PushEvaluationStack(new O(M));break;case A.CommandType.ListRandom:{let t=this.state.PopEvaluationStack();if(null===t)throw new C(\"Expected list for LIST_RANDOM\");let e=t.value,n=null;if(null===e)throw d(\"list\");if(0==e.Count)n=new g;else{let t=this.state.storySeed+this.state.previousRandom,i=new K(t).next(),a=i%e.Count,r=e.entries();for(let t=0;t<=a-1;t++)r.next();let s=r.next().value,l={Key:f.fromSerializedKey(s[0]),Value:s[1]};if(null===l.Key.originName)return d(\"randomItem.Key.originName\");(n=new g(l.Key.originName,this)).Add(l.Key,l.Value),this.state.previousRandom=i}this.state.PushEvaluationStack(new O(n));break}default:this.Error(\"unhandled ControlCommand: \"+e)}return!0}if(t instanceof L){let e=t,n=this.state.PopEvaluationStack();return this.state.variablesState.Assign(e,n),!0}if(t instanceof V){let e=t,n=null;if(null!=e.pathForCount){let t=e.containerForCount,i=this.VisitCountForContainer(t);n=new T(i)}else if(null==(n=this.state.variablesState.GetVariableWithName(e.name))){let t=this.state.variablesState.TryGetDefaultVariableValue(e.name);null!=t?(this.Warning(\"Variable not found in save state: '\"+e.name+\"', but seems to have been newly created. Assigning value from latest ink's declaration: \"+t),n=t,this.state.variablesState.SetGlobal(e.name,n)):(this.Warning(\"Variable not found: '\"+e.name+\"'. Using default value of 0 (false). This can happen with temporary variables if the declaration hasn't yet been hit.\"),n=new T(0))}return this.state.PushEvaluationStack(n),!0}if(t instanceof D){let e=t,n=this.state.PopEvaluationStack(e.numberOfParameters),i=e.Call(n);return this.state.PushEvaluationStack(i),!0}return!1}ChoosePathString(t,n=!0,i=[]){if(this.IfAsyncWeCant(\"call ChoosePathString right now\"),n)this.ResetCallstack();else if(this.state.callStack.currentElement.type==a.Function){let e=\"\",n=this.state.callStack.currentElement.currentPointer.container;throw null!=n&&(e=\"(\"+n.path.toString()+\") \"),new Error(\"Story was running a function \"+e+\"when you called ChoosePathString(\"+t+\") - this is almost certainly not not what you want! Full stack trace: \\n\"+this.state.callStack.callStackTrace)}this.state.PassArgumentsToEvaluationStack(i),this.ChoosePath(new e(t))}IfAsyncWeCant(t){if(this._asyncContinueActive)throw new Error(\"Can't \"+t+\". Story is in the middle of a ContinueAsync(). Make more ContinueAsync() calls or a single Continue() call beforehand.\")}ChoosePath(t,e=!0){this.state.SetChosenPath(t,e),this.VisitChangedContainersDueToDivert()}ChooseChoiceIndex(t){t=t;let e=this.currentChoices;this.Assert(t>=0&&t<e.length,\"choice out of range\");let n=e[t];return null===n.threadAtGeneration?d(\"choiceToChoose.threadAtGeneration\"):null===n.targetPath?d(\"choiceToChoose.targetPath\"):(this.state.callStack.currentThread=n.threadAtGeneration,void this.ChoosePath(n.targetPath))}HasFunction(t){try{return null!=this.KnotContainerWithName(t)}catch(t){return!1}}EvaluateFunction(t,e=[],n=!1){if(this.IfAsyncWeCant(\"evaluate a function\"),null==t)throw new Error(\"Function is null\");if(\"\"==t||\"\"==t.trim())throw new Error(\"Function is empty or white space.\");let i=this.KnotContainerWithName(t);if(null==i)throw new Error(\"Function doesn't exist: '\"+t+\"'\");let a=[];a.push.apply(a,this.state.outputStream),this._state.ResetOutput(),this.state.StartFunctionEvaluationFromGame(i,e);let r=new m;for(;this.canContinue;)r.Append(this.Continue());let s=r.toString();this._state.ResetOutput(a);let l=this.state.CompleteFunctionEvaluationFromGame();return n?{returned:l,output:s}:l}EvaluateExpression(t){let e=this.state.callStack.elements.length;this.state.callStack.Push(a.Tunnel),this._temporaryEvaluationContainer=t,this.state.GoToStart();let n=this.state.evaluationStack.length;return this.Continue(),this._temporaryEvaluationContainer=null,this.state.callStack.elements.length>e&&this.state.PopCallStack(),this.state.evaluationStack.length>n?this.state.PopEvaluationStack():null}CallExternalFunction(t,e){if(null===t)return d(\"funcName\");let n=this._externals.get(t),i=null;if(!(void 0!==n)){if(this.allowExternalFunctionFallbacks)return i=this.KnotContainerWithName(t),this.Assert(null!==i,\"Trying to call EXTERNAL function '\"+t+\"' which has not been bound, and fallback ink function could not be found.\"),this.state.callStack.Push(a.Function,void 0,this.state.outputStream.length),void(this.state.divertedPointer=k.StartOf(i));this.Assert(!1,\"Trying to call EXTERNAL function '\"+t+\"' which has not been bound (and ink fallbacks disabled).\")}let r=[];for(let t=0;t<e;++t){let t=s(this.state.PopEvaluationStack(),y).valueObject;r.push(t)}r.reverse();let l=n(r),o=null;null!=l?(o=y.Create(l),this.Assert(null!==o,\"Could not create ink value from returned object of type \"+typeof l)):o=new R,this.state.PushEvaluationStack(o)}BindExternalFunctionGeneral(t,e){this.IfAsyncWeCant(\"bind an external function\"),this.Assert(!this._externals.has(t),\"Function '\"+t+\"' has already been bound.\"),this._externals.set(t,e)}TryCoerce(t){return t}BindExternalFunction(t,e){this.Assert(null!=e,\"Can't bind a null function\"),this.BindExternalFunctionGeneral(t,t=>{this.Assert(t.length>=e.length,\"External function expected \"+e.length+\" arguments\");let n=[];for(let e=0,i=t.length;e<i;e++)n[e]=this.TryCoerce(t[e]);return e.apply(null,n)})}UnbindExternalFunction(t){this.IfAsyncWeCant(\"unbind an external a function\"),this.Assert(this._externals.has(t),\"Function '\"+t+\"' has not been bound.\"),this._externals.delete(t)}ValidateExternalBindings(){let t=null,e=null,n=arguments[1]||new Set;if(arguments[0]instanceof N&&(t=arguments[0]),arguments[0]instanceof p&&(e=arguments[0]),null===t&&null===e)if(this.ValidateExternalBindings(this._mainContentContainer,n),this._hasValidatedExternals=!0,0==n.size)this._hasValidatedExternals=!0;else{let t=\"Error: Missing function binding for external\";t+=n.size>1?\"s\":\"\",t+=\": '\",t+=Array.from(n).join(\"', '\"),t+=\"' \",t+=this.allowExternalFunctionFallbacks?\", and no fallback ink function found.\":\" (ink fallbacks disabled)\",this.Error(t)}else if(null!=t){for(let e of t.content){let t=e;null!=t&&t.hasValidName||this.ValidateExternalBindings(e,n)}for(let[e,i]of t.namedContent)this.ValidateExternalBindings(r(i,p),n)}else if(null!=e){let t=r(e,I);if(t&&t.isExternal){let e=t.targetPathString;if(null===e)return d(\"name\");if(!this._externals.has(e))if(this.allowExternalFunctionFallbacks){this.mainContentContainer.namedContent.has(e)||n.add(e)}else n.add(e)}}}ObserveVariable(t,e){if(this.IfAsyncWeCant(\"observe a new variable\"),null===this._variableObservers&&(this._variableObservers=new Map),!this.state.variablesState.GlobalVariableExistsWithName(t))throw new C(\"Cannot observe variable '\"+t+\"' because it wasn't declared in the ink story.\");this._variableObservers.has(t)?this._variableObservers.get(t).push(e):this._variableObservers.set(t,[e])}ObserveVariables(t,e){for(let n=0,i=t.length;n<i;n++)this.ObserveVariable(t[n],e[n])}RemoveVariableObserver(t,e){if(this.IfAsyncWeCant(\"remove a variable observer\"),null!==this._variableObservers)if(void 0!==e){if(this._variableObservers.has(e)){let n=this._variableObservers.get(e);n.splice(n.indexOf(t),1)}}else{let e=this._variableObservers.keys();for(let n of e){let e=this._variableObservers.get(n);e.splice(e.indexOf(t),1)}}}VariableStateDidChangeEvent(t,e){if(null===this._variableObservers)return;let n=this._variableObservers.get(t);if(void 0!==n){if(!(e instanceof y))throw new Error(\"Tried to get the value of a variable that isn't a standard type\");let i=s(e,y);for(let e of n)e(t,i.valueObject)}}get globalTags(){return this.TagsAtStartOfFlowContainerWithPathString(\"\")}TagsForContentAtPath(t){return this.TagsAtStartOfFlowContainerWithPathString(t)}TagsAtStartOfFlowContainerWithPathString(t){let n=new e(t),i=this.ContentAtPath(n).container;if(null===i)return d(\"flowContainer\");for(;;){let t=i.content[0];if(!(t instanceof N))break;i=t}let a=null;for(let t of i.content){let e=r(t,M);if(!e)break;null==a&&(a=[]),a.push(e.text)}return a}BuildStringOfHierarchy(){let t=new m;return this.mainContentContainer.BuildStringOfHierarchy(t,0,this.state.currentPointer.Resolve()),t.toString()}BuildStringOfContainer(t){let e=new m;return t.BuildStringOfHierarchy(e,0,this.state.currentPointer.Resolve()),e.toString()}NextContent(){if(this.state.previousPointer=this.state.currentPointer.copy(),!this.state.divertedPointer.isNull&&(this.state.currentPointer=this.state.divertedPointer.copy(),this.state.divertedPointer=k.Null,this.VisitChangedContainersDueToDivert(),!this.state.currentPointer.isNull))return;if(!this.IncrementContentPointer()){let t=!1;this.state.callStack.CanPop(a.Function)?(this.state.PopCallStack(a.Function),this.state.inExpressionEvaluation&&this.state.PushEvaluationStack(new R),t=!0):this.state.callStack.canPopThread?(this.state.callStack.PopThread(),t=!0):this.state.TryExitFunctionEvaluationFromGame(),t&&!this.state.currentPointer.isNull&&this.NextContent()}}IncrementContentPointer(){let t=!0,e=this.state.callStack.currentElement.currentPointer.copy();if(e.index++,null===e.container)return d(\"pointer.container\");for(;e.index>=e.container.content.length;){t=!1;let n=r(e.container.parent,N);if(n instanceof N==!1)break;let i=n.content.indexOf(e.container);if(-1==i)break;if((e=new k(n,i)).index++,t=!0,null===e.container)return d(\"pointer.container\")}return t||(e=k.Null),this.state.callStack.currentElement.currentPointer=e.copy(),t}TryFollowDefaultInvisibleChoice(){let t=this._state.currentChoices,e=t.filter(t=>t.isInvisibleDefault);if(0==e.length||t.length>e.length)return!1;let n=e[0];return null===n.targetPath?d(\"choice.targetPath\"):null===n.threadAtGeneration?d(\"choice.threadAtGeneration\"):(this.state.callStack.currentThread=n.threadAtGeneration,this.ChoosePath(n.targetPath,!1),!0)}VisitCountForContainer(t){if(null===t)return d(\"container\");if(!t.visitsShouldBeCounted)return console.warn(\"Read count for target (\"+t.name+\" - on \"+t.debugMetadata+\") unknown. The story may need to be compiled with countAllVisits flag (-c).\"),0;let e=0,n=t.path.toString();return e=this.state.visitCounts.get(n)||e}IncrementVisitCountForContainer(t){let e=0,n=t.path.toString();this.state.visitCounts.has(n)&&(e=this.state.visitCounts.get(n)),e++,this.state.visitCounts.set(n,e)}RecordTurnIndexVisitToContainer(t){let e=t.path.toString();this.state.turnIndices.set(e,this.state.currentTurnIndex)}TurnsSinceForContainer(t){t.turnIndexShouldBeCounted||this.Error(\"TURNS_SINCE() for target (\"+t.name+\" - on \"+t.debugMetadata+\") unknown. The story may need to be compiled with countAllVisits flag (-c).\");let e=t.path.toString(),n=this.state.turnIndices.get(e);return void 0!==n?this.state.currentTurnIndex-n:-1}NextSequenceShuffleIndex(){let t=r(this.state.PopEvaluationStack(),T);if(!(t instanceof T))return this.Error(\"expected number of elements in sequence for shuffle index\"),0;let e=this.state.currentPointer.container;if(null===e)return d(\"seqContainer\");if(null===t.value)return d(\"numElementsIntVal.value\");let n=t.value,i=s(this.state.PopEvaluationStack(),T).value;if(null===i)return d(\"seqCount\");let a=i/n,l=i%n,o=e.path.toString(),u=0;for(let t=0,e=o.length;t<e;t++)u+=o.charCodeAt(t)||0;let h=u+a+this.state.storySeed,c=new K(Math.floor(h)),p=[];for(let t=0;t<n;++t)p.push(t);for(let t=0;t<=l;++t){let e=c.next()%p.length,n=p[e];if(p.splice(e,1),t==l)return n}throw new Error(\"Should never reach here\")}Error(t,e=!1){let n=new C(t);throw n.useEndLineNumber=e,n}Warning(t){this.AddError(t,!0)}AddError(t,e=!1,n=!1){let i=this.currentDebugMetadata,a=e?\"WARNING\":\"ERROR\";if(null!=i){let e=n?i.endLineNumber:i.startLineNumber;t=\"RUNTIME \"+a+\": '\"+i.fileName+\"' line \"+e+\": \"+t}else t=this.state.currentPointer.isNull?\"RUNTIME \"+a+\": \"+t:\"RUNTIME \"+a+\": (\"+this.state.currentPointer+\"): \"+t;this.state.AddError(t,e),e||this.state.ForceEnd()}Assert(t,e=null){if(0==t)throw null==e&&(e=\"Story assert\"),new Error(e+\" \"+this.currentDebugMetadata)}get currentDebugMetadata(){let t,e=this.state.currentPointer;if(!e.isNull&&null!==e.Resolve()&&null!==(t=e.Resolve().debugMetadata))return t;for(let n=this.state.callStack.elements.length-1;n>=0;--n)if(!(e=this.state.callStack.elements[n].currentPointer).isNull&&null!==e.Resolve()&&null!==(t=e.Resolve().debugMetadata))return t;for(let e=this.state.outputStream.length-1;e>=0;--e){if(null!==(t=this.state.outputStream[e].debugMetadata))return t}return null}get mainContentContainer(){return this._temporaryEvaluationContainer?this._temporaryEvaluationContainer:this._mainContentContainer}}!function(t){let e;!function(t){t[t.NoChange=0]=\"NoChange\",t[t.ExtendedBeyondNewline=1]=\"ExtendedBeyondNewline\",t[t.NewlineRemoved=2]=\"NewlineRemoved\"}(e=t.OutputStateChange||(t.OutputStateChange={}))}(H||(H={})),t.InkList=g,t.Story=H,Object.defineProperty(t,\"__esModule\",{value:!0})});\n//# sourceMappingURL=ink-es2015.js.map\n"
  },
  {
    "path": "static/mainink.js",
    "content": "var story;\n\nvar storyContainer = document.querySelectorAll('#incident')[0];\n\nfunction loadStory(storyName) {\n    fetch(storyName)\n        .then(function (response) {\n            return response.text();\n        })\n        .then(function (storyContent) {\n            story = new inkjs.Story(storyContent);\n            continueStory();\n        });\n}\n\nfunction showAfter(delay, el) {\n    setTimeout(function () { el.classList.add(\"show\") }, delay);\n}\n\nfunction scrollToBottom() {\n    var progress = 0.0;\n    var start = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;\n    var dist = document.body.scrollHeight - window.innerHeight - start;\n    if (dist < 0) return;\n\n    var duration = 300 + 300 * dist / 100;\n    var startTime = null;\n    function step(time) {\n        if (startTime == null) startTime = time;\n        var t = (time - startTime) / duration;\n        var lerp = 3 * t * t - 2 * t * t * t;\n        window.scrollTo(0, start + lerp * dist);\n        if (t < 1) requestAnimationFrame(step);\n    }\n    requestAnimationFrame(step);\n}\n\nfunction continueStory() {\n\n    var paragraphIndex = 0;\n    var delay = 0.0;\n\n    // Generate story text - loop through available content\n    while (story.canContinue) {\n\n        // Get ink to generate the next paragraph\n        var paragraphText = story.Continue();\n\n        // Create paragraph element\n        var paragraphElement = document.createElement('p');\n        paragraphElement.innerHTML = paragraphText;\n        storyContainer.appendChild(paragraphElement);\n\n        // Fade in paragraph after a short delay\n        showAfter(delay, paragraphElement);\n\n        delay += 200.0;\n    }\n\n    // Create HTML choices from ink choices\n    story.currentChoices.forEach(function (choice) {\n\n        // Create paragraph with anchor element\n        var choiceParagraphElement = document.createElement('p');\n        choiceParagraphElement.classList.add(\"choice\");\n        choiceParagraphElement.innerHTML = `<a href='#'>${choice.text}</a>`\n        storyContainer.appendChild(choiceParagraphElement);\n\n        // Fade choice in after a short delay\n        showAfter(delay, choiceParagraphElement);\n        delay += 200.0;\n\n        // Click on choice\n        var choiceAnchorEl = choiceParagraphElement.querySelectorAll(\"a\")[0];\n        choiceAnchorEl.addEventListener(\"click\", function (event) {\n\n            // Don't follow <a> link\n            event.preventDefault();\n\n            // Remove all existing choices\n            var existingChoices = storyContainer.querySelectorAll('p.choice');\n            for (var i = 0; i < existingChoices.length; i++) {\n                var c = existingChoices[i];\n                c.parentNode.removeChild(c);\n            }\n\n            // Tell the story where to go next\n            story.ChooseChoiceIndex(choice.index);\n\n            // Aaand loop\n            continueStory();\n        });\n    });\n\n    //scrollToBottom();\n}\n"
  },
  {
    "path": "static/site.webmanifest",
    "content": "{\"name\":\"\",\"short_name\":\"\",\"icons\":[{\"src\":\"/android-chrome-192x192.png\",\"sizes\":\"192x192\",\"type\":\"image/png\"},{\"src\":\"/android-chrome-512x512.png\",\"sizes\":\"512x512\",\"type\":\"image/png\"}],\"theme_color\":\"#ffffff\",\"background_color\":\"#ffffff\",\"display\":\"standalone\"}"
  },
  {
    "path": "static/stopwatch.js",
    "content": "/* Kudos to Billy Brown: https://codepen.io/_Billy_Brown/pen/dbJeh */\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } } var Stopwatch = function () {\n    function Stopwatch(display, results) {\n        _classCallCheck(this, Stopwatch);\n        this.running = false;\n        this.display = display;\n        this.results = results;\n        this.laps = [];\n        this.reset();\n        this.print(this.times);\n    } _createClass(Stopwatch, [{\n        key: 'reset', value: function reset() {\n            this.times = [0, 0, 0];\n        }\n    }, {\n        key: 'start', value: function start() {\n            if (!this.time) this.time = performance.now();\n            if (!this.running) {\n                this.running = true;\n                requestAnimationFrame(this.step.bind(this));\n            }\n        }\n    }, {\n        key: 'lap', value: function lap() {\n            if (!this.running) return;\n            var times = this.times;\n            var li = document.createElement('li');\n            li.innerText = this.format(times);\n            this.results.appendChild(li);\n        }\n    }, {\n        key: 'stop', value: function stop() {\n            this.running = false;\n            this.time = null;\n        }\n    }, {\n        key: 'restart', value: function restart() {\n            if (!this.time) this.time = performance.now();\n            if (!this.running) {\n                this.running = true;\n                requestAnimationFrame(this.step.bind(this));\n            }\n            this.reset();\n        }\n    }, {\n        key: 'clear', value: function clear() {\n            clearChildren(this.results);\n        }\n    }, {\n        key: 'step', value: function step(\n\n            timestamp) {\n            if (!this.running) return;\n            this.calculate(timestamp);\n            this.time = timestamp;\n            this.print();\n            requestAnimationFrame(this.step.bind(this));\n        }\n    }, {\n        key: 'calculate', value: function calculate(\n\n            timestamp) {\n            var diff = timestamp - this.time;\n            // Hundredths of a second are 100 ms\n            this.times[2] += diff / 10;\n            // Seconds are 100 hundredths of a second\n            if (this.times[2] >= 100) {\n                this.times[1] += 1;\n                this.times[2] -= 100;\n            }\n            // Minutes are 60 seconds\n            if (this.times[1] >= 60) {\n                this.times[0] += 1;\n                this.times[1] -= 60;\n            }\n        }\n    }, {\n        key: 'print', value: function print() {\n            this.display.innerText = this.format(this.times);\n        }\n    }, {\n        key: 'format', value: function format(\n\n            times) {\n            return (\n                pad0(times[0], 2) + ':' +\n                pad0(times[1], 2) + ':' +\n                pad0(Math.floor(times[2]), 2));\n        }\n    }]); return Stopwatch;\n}();\n\n\nfunction pad0(value, count) {\n    var result = value.toString();\n    for (; result.length < count; --count) {\n        result = '0' + result;\n    }\n    return result;\n}\n\nfunction clearChildren(node) {\n    while (node.lastChild) {\n        node.removeChild(node.lastChild);\n    }\n}\n\nvar stopwatch = new Stopwatch(\n    document.querySelector('.stopwatch'),\n    document.querySelector('.results'));\n"
  },
  {
    "path": "static/styles.css",
    "content": "html,\nbody {\n  width: 100%;\n  margin: 0;\n  padding: 0;\n\n}\n\nbody {\n    font-family: \"Roboto\", Helvetica, sans-serif;\n    font-weight: 350;\n    background-color: #f5f5f5;\n}\n\nbutton {\n  border:solid 2px #590F20;\n  border-radius:5px;\n  background-color: #e7e7e7;\n  letter-spacing: 1px;\n  border: none;\n  margin: 3px 1px;\n  text-align: center;\n  text-decoration: none;\n  display: inline-block;\n  cursor: pointer;\n  font-size: 15px;\n  padding: 12px 12px;\n}\n\nbutton:first-child {\n    margin-left: 0;\n}\n\nbutton:last-child {\n    margin-right: 0;\n}\n\nbutton:hover {\n  color: rgb(255, 127, 14);\n}\n\ntable {\n    border-collapse: collapse;\n    background-color: white;\n}\n\ntd, th {\n    border: 1px solid #dddddd;\n    text-align: left;\n    padding: 5px;\n}\n\nli a {\n    text-decoration: none;\n}\n\nli a:hover {\n    text-decoration:underline;\n}\n\nheader p {\n    color: #0a0a0a;\n}\n\nheader li {\n  color: #0a0a0a;\n}\n\nsmall a {\n    color: white;\n    text-decoration: underline;\n}\n\nsmall a:hover {\n    text-decoration: underline;\n}\n\nul {\n  margin: 0;\n  padding: 0;\n  list-style-type: none;\n}\n\nh1 {\n  margin-bottom: 5px;\n}\n\nh2 {\n  margin-bottom: 10px;\n  color: rgba(0,0,0,.54);\n}\n\nh3, h4 {\n  margin-top: 5px;\n  margin-bottom: 5px;\n  color: rgba(0,0,0,.54);\n}\n\nlabel {\n  display: inline-block;\n  max-width: 100%;\n  padding: 5px;\n  font-weight: bold;\n}\n\ntext {\n    pointer-events:none;\n}\n\n.center {\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.results {\n  font-size: 20px;\n  margin: 15px;\n  padding: 0;\n  bottom: 0;\n  left: 50%;\n}\n\n.results li {\n  color: #666;\n  position: relative;\n  border-bottom: 0.5px solid #333;\n}\n\n.result li::before {\n  visibility: hidden;\n  color: inherit;\n  line-height: 3em;\n  position: absolute;\n  left: 0;\n  top: 0;\n}\n\na {\n  text-decoration: none;\n}\n\na:hover {\n  text-decoration: underline;\n  color: rgb(255, 127, 14);\n}\n\np a {\n    color: rgb(255,64,129);;\n}\n\nul a {\n    color: rgb(255,64,129);;\n}\n\n.br3 {\n    border-radius: .5rem;\n    box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);\n}\n\n.br-100 {\n    border-radius: 100%;\n}\n\n.bw1 {\n    border-width: .125rem;\n}\n\n.cf:before, .cf:after {\n    content: \" \";\n    display: table;\n}\n\n.cf:after {\n    clear: both;\n}\n\n.cf {\n    *zoom: 1;\n}\n\n.fl {\n    float: left;\n    _display: inline;\n}\n\n.w-100 {\n    width: 100%;\n}\n\n.tc {\n    text-align: center;\n}\n\n@media screen and (min-width: 50em) {\n    .w-50-ns {\n        width: 50%;\n    }\n}\n\n@media screen and (min-width: 50em) {\n    .w-30-ns {\n        width: 30%;\n    }\n}\n\n@media screen and (min-width: 50em) {\n    .w-40-ns {\n        width: 40%;\n    }\n}\n\n.f2 {\n    font-size: 2.2rem;\n    color: #721329;\n}\n\n@media screen and (min-width: 40em) and (max-width: 60em) {\n    .f2-m {\n        font-size: 2.2rem;\n    }\n}\n\n@media screen and (min-width: 60em) {\n    .f-headline-l2 {\n        font-size: 2.2rem;\n    }\n}\n\n.f3 {\n    font-size: 1.5rem;\n}\n\n@media screen and (min-width: 50em) and (max-width: 60em) {\n    .f1-m {\n        font-size: 1.5rem;\n    }\n}\n\n@media screen and (min-width: 60em) {\n    .f-headline-l {\n        font-size: 1.5rem;\n    }\n}\n\n.white-ft {\n    color: white;\n}\n\n.athelas {\n    font-family: athelas, georgia, serif;\n}\n\n.pa4 {\n    padding: 1rem;\n}\n\n.i {\n    font-style: italic;\n}\n\n.fw1 {\n    font-weight: 100;\n}\n\n.fw4 {\n    font-weight: 400;\n}\n\n.f5 {\n    font-size: 1rem;\n}\n\n.h2 {\n    height: 2rem;\n}\n\n.black-80 {\n    color: rgba(0, 0, 0, .8);\n}\n\n.pv4 {\n    padding-top: 1rem;\n    padding-bottom: 1rem;\n}\n\n.f1 {\n    font-size: 2rem;\n}\n\n.ff2 {\n    font-size: 1.15rem;\n}\n\n.db {\n  display: block;\n}\n\n.mid-gray {\n  color: #555;\n}\n\n.ph3 {\n  padding-left: 1rem;\n  padding-right: 1rem;\n}\n\n.container {\n  position: relative;\n  margin: 40px auto;\n  font-size: 16px;\n}\n\n.ba {\n  border-style: solid;\n  border-width: 1px;\n}\n\n.bg-blue {\n    background-color: rgb(63,81,181);\n}\n\n.bg-white {\n    background-color: #fff;\n}\n\n.br3 {\n    border-radius: .5rem;\n}\n\n.br-100 {\n    border-radius: 100%;\n}\n\n.bw1 {\n    border-width: .125rem;\n}\n\n.b--black-10 {\n    border-color: rgba(0, 0, 0, .1);\n}\n\n.b--black-30 {\n  border-color: rgba(0, 0, 0, .3);\n}\n\n.b--dotted {\n  border-style: dotted;\n}\n\n.bt-0 {\n  border-top-width: 0;\n}\n\n.br-0 {\n  border-right-width: 0;\n}\n\n.bl-0 {\n  border-left-width: 0;\n}\n\n.mw3 {\n    max-width: 4rem;\n}\n\n.mw5 {\n    max-width: 16rem;\n}\n\n.lh-copy {\n  line-height: 1.5;\n}\n\n.list  {\n  display:list-item;\n  list-style-type: none;\n}\n\n.list label {\n  display:list-item;\n  list-style-type: none;\n}\n\n.pa3 {\n  padding: 1rem;\n}\n\n.pv3 {\n  padding-top: 1rem;\n  padding-bottom: 0.5rem;\n}\n\n.pl0 {\n  padding-left: 0;\n}\n\n.f4 {\n  font-size: 1rem;\n}\n\n.mw6 {\n  max-width: 32rem;\n}\n\n@media screen and (min-width: 30em) {\n    .pa4-ns {\n        padding: 2rem;\n    }\n}\n\n.mb {\n    margin-bottom: 20px;\n}\n\n.pv5 {\n    padding-top: 4rem;\n    padding-bottom: 4rem;\n}\n\n.ph4 {\n    padding-left: 2rem;\n    padding-right: 2rem;\n}\n\n.mv4 {\n    margin-top: 2rem;\n    margin-bottom: 0.5rem;\n}\n\n.mv3 {\n    margin-top: 0.5rem;\n    margin-bottom: 2rem;\n}\n\n.mbr {\n    margin-right: 1rem;\n}\n\n@media screen and (min-width: 60em) {\n    .pv6-l {\n        padding-top: 8rem;\n        padding-bottom: 8rem;\n    }\n}\n\n.mw-h {\n  max-width: 35rem;\n}\n\n@media screen and (min-width: 50em) {\n  .mw {\n    max-width: 55rem;\n  }\n}\n.flex {\n  display: flex;\n}\n\n.items-center {\n  align-items: center;\n}\n\n.justify-center {\n  justify-content: center;\n}\n\n.w1 {\n  width: 1rem;\n}\n\n.navy {\n  color: #001b44;\n}\n\n.bg-lightest-blue {\n  background-color: #cdecff;\n}\n\n.pa4 {\n  padding: 2rem;\n}\n\n.ml3 {\n  margin-left: .5rem;\n}\n\n.timing {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-weight: 300;\n  text-align: center;\n}\n\n.timing ul {\n      list-style-type: none;\n}\n\n.timing button {\n  padding: 12px 23px;\n  cursor: pointer;\n  font-size: 16px;\n  border: 1px solid #353535;\n  background-color: #353535;\n  color: #ccc;\n  border-radius: 100%;\n  text-align: center;\n  line-height: 35px;\n}\n\n.stopwatch {\n  font-size: 2rem;\n}\n\n#start {\n  background-color: #4caf50;\n  color:white\n}\n\n#start:hover {\n  background-color: #81c784;\n  color:white\n}\n\n#stop {\n  background-color: #f44336;\n  color:white\n}\n\n#stop:hover {\n  background-color: #e57373;\n  color:white\n}\n\n#restart {\n  background-color: #2196f3;\n  color:white\n}\n\n#restart:hover {\n  background-color: #b9d9f3;\n  color:white\n}\n\n#wheel {\n  width: 100%;\n  margin-left: 5px;\n}\n\n#incident {\n    margin-top: 10px;\n    word-wrap: break-word;\n    line-height: 1.5;\n}\n\n#incident p {\n    font-size: .875rem\n}\n\n.link {\n  text-decoration: none;\n  color: white;\n  transition: color .15s ease-in;\n}\n\n.link:link, .link:visited {\n  transition: color .15s ease-in;\n}\n\n.link:hover {\n  transition: color .15s ease-in;\n  color: #f44336;\n}\n\n.link:active {\n  transition: color .15s ease-in;\n}\n\n.link:focus {\n  transition: color .15s ease-in;\n  outline: 1px dotted currentColor;\n}\n\n@media screen and (min-width: 30em) and (max-width: 60em) {\n  .ph5-m {\n      padding-left: 4rem;\n      padding-right: 4rem;\n  }\n}\n\n@media screen and (min-width: 60em) {\n  .ph6-l {\n      padding-left: 8rem;\n      padding-right: 8rem;\n  }\n}\n\n@media screen and (min-width: 30em) {\n  .w-40-ns {\n      width: 40%;\n  }\n}\n\n@media screen and (min-width: 30em) {\n  .w-33-ns {\n      width: 33.33333%;\n  }\n}\n\n@media screen and (min-width: 30em) {\n  .w-20-ns {\n      width: 20%;\n  }\n}\n\n@media screen and (min-width: 30em) {\n  .w-10-ns {\n      width: 10%;\n  }\n}\n\n/* Slight modifications from:\n* https://www.cssscript.com/beautiful-checkbox-and-radio-button-replacement-with-pure-css-magic-check/\n*/\n@keyframes hover-color {\n  from {\n    border-color: #c0c0c0; }\n  to {\n    border-color: #81c784; }\n}\n\n.magic-checkbox {\n  position: absolute;\n  display: none;\n }\n\n.magic-checkbox[disabled] {\n  cursor: not-allowed; }\n\n\n.magic-checkbox + label {\n  position: relative;\n  display: block;\n  cursor: pointer;\n}\n\n.magic-checkbox + label:hover:before {\n    animation-duration: 0.4s;\n    animation-fill-mode: both;\n    animation-name: hover-color;\n}\n\n.magic-checkbox + label:before {\n    position: absolute;\n    top: 0;\n    left: 0;\n    display: inline-block;\n    width: 30px;\n    height: 30px;\n    content: '';\n    border: 1px solid #c0c0c0;\n}\n\n.magic-checkbox + label:after {\n    position: absolute;\n    display: none;\n    content: '';\n}\n\n.magic-checkbox[disabled] + label {\n  cursor: not-allowed;\n  color: #e4e4e4;\n}\n\n.magic-checkbox[disabled] + label:hover,\n.magic-checkbox[disabled] + label:before,\n.magic-checkbox[disabled] + label:after {\n  cursor: not-allowed;\n}\n\n.magic-checkbox[disabled] + label:hover:before {\n  border: 1px solid #e4e4e4;\n  animation-name: none;\n}\n\n.magic-checkbox[disabled] + label:before {\n  border-color: #e4e4e4;\n}\n\n.magic-checkbox:checked + label:before {\n  animation-name: none;\n}\n\n.magic-checkbox:checked + label:after {\n  display: block;\n}\n\n.magic-checkbox + label:before {\n  border-radius: 3px;\n}\n\n.magic-checkbox + label:after {\n  top: 2px;\n  left: 11px;\n  box-sizing: border-box;\n  width: 10px;\n  height: 20px;\n  transform: rotate(45deg);\n  border-width: 2px;\n  border-style: solid;\n  border-color: #fff;\n  border-top: 0;\n  border-left: 0;\n}\n\n.magic-checkbox:checked + label:before {\n  background: #388E3C;\n}\n\n.magic-checkbox:checked[disabled] + label:before {\n  border:  #388E3C;\n  background:  #388E3C;\n}\n\n.magic-checkbox + label {\n    color: rgb(255,64,129);\n    font-weight: bold;\n}\n\n.magic-checkbox + label:hover{\n  color: #353535;\n  -moz-transition: all 0.2s ease-in;\n  -o-transition: all 0.2s ease-in;\n  -webkit-transition: all 0.2s ease-in;\n  transition: all 0.2s ease-in;\n}\n\n.magic-checkbox:checked + label {\n  color: #353535;\n}\n\n/* Modified: https://codepen.io/jo-asakura/pen/stFHi */\n.pie-wrapper {\n  height: 1em;\n  width: 1em;\n  float: left;\n  position: relative;\n}\n\n.pie-wrapper:nth-child(3n + 1) {\n  clear: both;\n}\n\n.pie-wrapper .pie {\n  height: 100%;\n  width: 100%;\n  clip: rect(0, 1em, 1em, 0.5em);\n  left: 0;\n  position: absolute;\n  top: 0;\n}\n.pie-wrapper .pie .half-circle {\n  height: 100%;\n  width: 100%;\n  border: 0.1em solid #3498db;\n  border-radius: 50%;\n  clip: rect(0, 0.5em, 1em, 0);\n  left: 0;\n  position: absolute;\n  top: 0;\n}\n.pie-wrapper .label {\n  border-radius: 50%;\n  bottom: 0.4em;\n  background: none;\n  color: #7f8c8d;\n  cursor: default;\n  display: block;\n  font-size: 0.25em;\n  left: 0.4em;\n  line-height: 2.8em;\n  position: absolute;\n  right: 0.4em;\n  text-align: center;\n  top: 0.4em;\n}\n.pie-wrapper .label .smaller {\n  color: #bdc3c7;\n  font-size: .45em;\n  padding-bottom: 20px;\n  vertical-align: super;\n}\n.pie-wrapper .shadow {\n  height: 100%;\n  width: 100%;\n  border: 0.1em solid #bdc3c7;\n  border-radius: 50%;\n}\n\n.pie-wrapper.progress-25 .pie .half-circle {\n  border-color: #e65100;\n}\n.pie-wrapper.progress-25 .pie .left-side {\n  -webkit-transform: rotate(90deg);\n          transform: rotate(90deg);\n}\n.pie-wrapper.progress-25 .pie .right-side {\n  display: none;\n}\n\n.pie-wrapper.progress-50 .pie .half-circle {\n  border-color: #ffc107;\n}\n.pie-wrapper.progress-50 .pie .left-side {\n  -webkit-transform: rotate(180deg);\n          transform: rotate(180deg);\n}\n.pie-wrapper.progress-50 .pie .right-side {\n  display: none;\n}\n\n.pie-wrapper.progress-75 .pie {\n  clip: rect(auto, auto, auto, auto);\n}\n.pie-wrapper.progress-75 .pie .half-circle {\n  border-color: #ffd54f;\n}\n.pie-wrapper.progress-75 .pie .left-side {\n  -webkit-transform: rotate(270deg);\n          transform: rotate(270deg);\n}\n.pie-wrapper.progress-75 .pie .right-side {\n  -webkit-transform: rotate(180deg);\n          transform: rotate(180deg);\n}\n.pie-wrapper.progress-100 .pie {\n  clip: rect(auto, auto, auto, auto);\n}\n.pie-wrapper.progress-100 .pie .half-circle {\n  border-color: #4caf50;\n}\n.pie-wrapper.progress-100 .pie .left-side {\n  -webkit-transform: rotate(360deg);\n          transform: rotate(360deg);\n}\n.pie-wrapper.progress-100 .pie .right-side {\n  -webkit-transform: rotate(180deg);\n          transform: rotate(180deg);\n}\n\n*,\n*:before,\n*:after {\n  box-sizing: border-box;\n}\n\n.sz {\n  font-size: 10em;\n  display: inline-block;\n}\n\nfooter {\n  color: #9e9e9e;\n  background-color: #424242;\n  margin-top: 2rem;\n}\n"
  },
  {
    "path": "static/wheel.js",
    "content": "/* This is a modified version of Jeremy Rue's Wheel of Fortune\n * http://bl.ocks.org/jrue/a2aaf36b3c096925ccbf */\n\nfunction custom_colors(n) {\n    var colors = [\"#388E3C\", \"#1976D2\", \"#D32F2F\", \"#FFA000\", \"#388E3C\", \"#990099\", \"#0099c6\", \"#C2185B\", \"#81C784\", \"#D32F2F\", \"#1976D2\", \"#994499\", \"#4DD0E1\", \"#AED581\", \"#536DFE\", \"#FBC02D\", \"#C62828\", \"#AB47BC\", \"#66BB6A\", \"#90A4AE\", \"#0D47A1\"];\n    return colors[n % colors.length];\n}\n\nvar padding = { top: 20, right: 40, bottom: 0, left: 0 },\n    w = 500 - padding.left - padding.right,\n    h = 500 - padding.top - padding.bottom,\n    r = Math.min(w, h) / 2,\n    rotation = 0,\n    oldrotation = 0,\n    picked = 100000,\n    oldpick = [];\n\nd3.json(\"./incidents/general_incidents.json\", function (error, data) {\n    if (error) throw error;\n    var svg = d3.select(\"#wheel\")\n        .append(\"svg\")\n        .data([data])\n        .attr(\"viewBox\", \"0 0 500 500\");\n\n    var container = svg.append(\"g\")\n        .attr(\"transform\", \"translate(\" + (w / 2 + padding.left) + \",\" + (h / 2 + padding.top) + \")\");\n\n    var vis = container\n        .append(\"g\");\n\n    var pie = d3.layout.pie().sort(null).value(function (d) { return 1; });\n\n    // declare an arc generator function\n    var arc = d3.svg.arc().outerRadius(r);\n\n    // select paths, use arc generator to draw\n    var arcs = vis.selectAll(\"g.slice\")\n        .data(pie)\n        .enter()\n        .append(\"g\")\n        .attr(\"class\", \"slice\");\n\n\n    arcs.append(\"path\")\n        .attr(\"fill\", function (d, i) { return custom_colors(i); })\n        .attr(\"d\", function (d) { return arc(d); });\n\n    // add the text\n    arcs.append(\"text\").attr(\"transform\", function (d) {\n        d.innerRadius = 0;\n        d.outerRadius = r;\n        d.angle = (d.startAngle + d.endAngle) / 2;\n        return \"rotate(\" + (d.angle * 180 / Math.PI - 90) + \")translate(\" + (d.outerRadius - 10) + \")\";\n    })\n        .attr(\"text-anchor\", \"end\")\n        .text(function (d, i) {\n            return data[i].title;\n        });\n    container.on(\"click\", spin);\n\n    function spin(d) {\n        container.on(\"click\", null);\n        //all slices have been seen, all done\n        if (oldpick.length == data.length) {\n            container.on(\"click\", null);\n            return;\n        }\n\n        var ps = 360 / data.length,\n            pieslice = Math.round(1440 / data.length),\n            rng = Math.floor((Math.random() * 1440) + 360);\n\n        rotation = (Math.round(rng / ps) * ps);\n        picked = Math.round(data.length - (rotation % 360) / ps);\n        picked = picked >= data.length ? (picked % data.length) : picked;\n\n        if (oldpick.indexOf(picked) !== -1) {\n            d3.select(this).call(spin);\n            return;\n        } else {\n            oldpick.push(picked);\n        }\n\n        rotation += 90 - Math.round(ps / 2);\n        vis.transition()\n            .duration(3000)\n            .attrTween(\"transform\", rotTween)\n            .each(\"end\", function () {\n                //mark incident as seen\n                d3.select(\".slice:nth-child(\" + (picked + 1) + \") path\")\n                    .attr(\"fill\", \"#111\");\n                // if Ink story is provided, override the actual scenario.\n                if (data[picked].inkstory != undefined) {\n                    //populate incident\n                    d3.select(\"#incident p\")\n                        .html(\"<h4 class=\\\"f4 center mw6\\\">\" + data[picked].title + \"</h4>\" + \"<div id=\\\"play-area\\\"> <ol id =\\\"choices\\\"><ol></div>\");\n                    container.on(\"click\", spin, stopwatch.reset(), stopwatch.start(), changeControls(), loadStory(data[picked].inkstory));\n                   } else {\n                    //populate incident\n                    d3.select(\"#incident p\")\n                        .html(\"<h4 class=\\\"f4 center mw6\\\">\" + data[picked].title + \"</h4>\" + data[picked].scenario);\n                    container.on(\"click\", spin, stopwatch.reset(), stopwatch.start(), changeControls());\n                }\n                oldrotation = rotation;\n            });\n    }\n\n    //make arrow\n    svg.append(\"g\")\n        .attr(\"transform\", \"translate(\" + (w + padding.left + padding.right) + \",\" + ((h / 2) + padding.top) + \")\")\n        .append(\"path\")\n        .attr(\"d\", \"M-\" + (r * .15) + \",0L0,\" + (r * .05) + \"L0,-\" + (r * .05) + \"Z\")\n        .style({ \"fill\": \"black\" });\n\n    //draw spin circle\n    container.append(\"circle\")\n        .attr(\"cx\", 0)\n        .attr(\"cy\", 0)\n        .attr(\"r\", 30)\n        .style({ \"fill\": \"white\", \"cursor\": \"pointer\" });\n\n    //spin text\n    container.append(\"text\")\n        .attr(\"x\", 0)\n        .attr(\"y\", 10)\n        .attr(\"text-anchor\", \"middle\")\n        .text(\"SPIN\")\n        .style({ \"color\": \"white\", \"font-weight\": \"bold\", \"font-size\": \"18px\" });\n\n    function rotTween(to) {\n        var i = d3.interpolate(oldrotation % 360, rotation);\n        return function (t) {\n            return \"rotate(\" + i(t) + \")\";\n        };\n    }\n\n});\n"
  }
]