diff --git a/Elm/.gitignore b/Elm/.gitignore
new file mode 100644
index 0000000000..cc1f8d3394
--- /dev/null
+++ b/Elm/.gitignore
@@ -0,0 +1,3 @@
+node_modules
+elm-stuff
+build
diff --git a/Elm/elm-watch.json b/Elm/elm-watch.json
new file mode 100644
index 0000000000..25a31f79d2
--- /dev/null
+++ b/Elm/elm-watch.json
@@ -0,0 +1,12 @@
+{
+ "targets": {
+ "Main": {
+ "inputs": [
+ "src/Main.elm"
+ ],
+ "output": "build/main.js"
+ }
+ },
+ "port": 54321,
+ "serve": "."
+}
\ No newline at end of file
diff --git a/Elm/elm.json b/Elm/elm.json
new file mode 100644
index 0000000000..4863b9981b
--- /dev/null
+++ b/Elm/elm.json
@@ -0,0 +1,30 @@
+{
+ "type": "application",
+ "source-directories": [
+ "src"
+ ],
+ "elm-version": "0.19.1",
+ "dependencies": {
+ "direct": {
+ "elm/browser": "1.0.2",
+ "elm/core": "1.0.5",
+ "elm/html": "1.0.0",
+ "elm/random": "1.0.0",
+ "miniBill/elm-rope": "1.0.0"
+ },
+ "indirect": {
+ "elm/json": "1.1.3",
+ "elm/time": "1.0.0",
+ "elm/url": "1.0.0",
+ "elm/virtual-dom": "1.0.3"
+ }
+ },
+ "test-dependencies": {
+ "direct": {
+ "elm-explorations/test": "2.1.1"
+ },
+ "indirect": {
+ "elm/bytes": "1.0.8"
+ }
+ }
+}
diff --git a/Elm/index.html b/Elm/index.html
new file mode 100644
index 0000000000..b6ac0dfcf9
--- /dev/null
+++ b/Elm/index.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ Trivia
+
+
+
+
+
+
+
diff --git a/Elm/package.json b/Elm/package.json
new file mode 100644
index 0000000000..1e8072f97b
--- /dev/null
+++ b/Elm/package.json
@@ -0,0 +1,6 @@
+{
+ "devDependencies": {
+ "elm-test": "^0.19.1-revision12",
+ "elm-watch": "^1.2.0-beta.3"
+ }
+}
diff --git a/Elm/src/Game.elm b/Elm/src/Game.elm
new file mode 100644
index 0000000000..899f099775
--- /dev/null
+++ b/Elm/src/Game.elm
@@ -0,0 +1,370 @@
+module Game exposing (Game, add, init, roll, wasCorrectlyAnswered, wrongAnswer)
+
+import Array exposing (Array)
+import Rope exposing (Rope)
+
+
+type alias Game =
+ { players : Array String
+ , places : Array Int
+ , purses : Array Int
+ , inPenaltyBox : Array Bool
+ , popQuestions : Array String
+ , scienceQuestions : Array String
+ , sportsQuestions : Array String
+ , rockQuestions : Array String
+ , currentPlayer : Int
+ , isGettingOutOfPenaltyBox : Bool
+ }
+
+
+init : ( Game, Rope String )
+init =
+ ( List.range 0 49
+ |> List.foldl
+ (\i this ->
+ { this
+ | popQuestions = Array.push ("Pop Question " ++ String.fromInt i) this.popQuestions
+ , scienceQuestions = Array.push ("Science Question " ++ String.fromInt i) this.scienceQuestions
+ , sportsQuestions = Array.push ("Sports Question " ++ String.fromInt i) this.sportsQuestions
+ , rockQuestions = Array.push (createRockQuestion i) this.rockQuestions
+ }
+ )
+ { players = Array.empty
+ , places = Array.repeat 6 0
+ , purses = Array.repeat 6 0
+ , inPenaltyBox = Array.repeat 6 False
+ , popQuestions = Array.empty
+ , scienceQuestions = Array.empty
+ , sportsQuestions = Array.empty
+ , rockQuestions = Array.empty
+ , currentPlayer = 0
+ , isGettingOutOfPenaltyBox = False
+ }
+ , Rope.empty
+ )
+
+
+createRockQuestion : Int -> String
+createRockQuestion i =
+ "Rock Question " ++ String.fromInt i
+
+
+isPlayable : Game -> Bool
+isPlayable this =
+ howManyPlayers this >= 2
+
+
+add : String -> Game -> ( Game, Rope String )
+add playerName this =
+ let
+ newGame =
+ { this
+ | players = Array.push playerName this.players
+ , places = Array.set (howManyPlayers this) 0 this.places
+ , purses = Array.set (howManyPlayers this) 0 this.purses
+ , inPenaltyBox = Array.set (howManyPlayers this) False this.inPenaltyBox
+ }
+ in
+ ( newGame
+ , Rope.fromList
+ [ playerName ++ " was added"
+ , "They are player number " ++ String.fromInt (Array.length newGame.players)
+ ]
+ )
+
+
+howManyPlayers : Game -> Int
+howManyPlayers game =
+ Array.length game.players
+
+
+roll : Int -> Game -> ( Game, Rope String )
+roll roll_ this =
+ let
+ initialLogs =
+ [ getUnsafe this.players this.currentPlayer ++ " is the current player"
+ , "They have rolled a " ++ String.fromInt roll_
+ ]
+ |> Rope.fromList
+
+ ( next, logs ) =
+ if getUnsafe this.inPenaltyBox this.currentPlayer then
+ if modBy 2 roll_ /= 0 then
+ let
+ next_ =
+ { this
+ | isGettingOutOfPenaltyBox = True
+ , places = Array.set this.currentPlayer (getUnsafe this.places this.currentPlayer + roll_) this.places
+ , inPenaltyBox = Array.set this.currentPlayer False this.inPenaltyBox
+ }
+
+ next__ =
+ if getUnsafe next_.places this.currentPlayer > 11 then
+ { next_ | places = Array.set this.currentPlayer (getUnsafe next_.places this.currentPlayer - 12) next_.places }
+
+ else
+ next_
+
+ ( next___, askLogs ) =
+ askQuestion next__
+ in
+ ( next___
+ , [ getUnsafe this.players this.currentPlayer ++ " is getting out of the penalty box"
+ , getUnsafe next__.players next__.currentPlayer ++ "'s new location is " ++ String.fromInt (getUnsafe next__.places next__.currentPlayer)
+ , "The category is " ++ currentCategory next__
+ ]
+ |> Rope.fromList
+ |> Rope.prependTo askLogs
+ )
+
+ else
+ ( { this
+ | isGettingOutOfPenaltyBox = False
+ }
+ , (getUnsafe this.players this.currentPlayer ++ " is not getting out of the penalty box")
+ |> Rope.singleton
+ )
+
+ else
+ let
+ next_ =
+ { this
+ | places = Array.set this.currentPlayer (getUnsafe this.places this.currentPlayer + roll_) this.places
+ }
+
+ next__ =
+ if getUnsafe next_.places this.currentPlayer > 11 then
+ { next_ | places = Array.set this.currentPlayer (getUnsafe next_.places this.currentPlayer - 12) next_.places }
+
+ else
+ next_
+
+ ( next___, askLogs ) =
+ askQuestion next__
+ in
+ ( next___
+ , [ getUnsafe next__.players next__.currentPlayer ++ "'s new location is " ++ String.fromInt (getUnsafe next__.places next__.currentPlayer)
+ , "The category is " ++ currentCategory next__
+ ]
+ |> Rope.fromList
+ |> Rope.prependTo askLogs
+ )
+ in
+ ( next, Rope.appendTo initialLogs logs )
+
+
+askQuestion : Game -> ( Game, Rope String )
+askQuestion game =
+ let
+ ( popNext, popLogs ) =
+ if currentCategory game == "Pop" then
+ ( { game | popQuestions = removeFirst game.popQuestions }
+ , Array.get 0 game.popQuestions
+ |> Maybe.withDefault "--- out of Pop questions ---"
+ |> Rope.singleton
+ )
+
+ else
+ ( game, Rope.empty )
+
+ ( scienceNext, scienceLogs ) =
+ if currentCategory popNext == "Science" then
+ ( { popNext | scienceQuestions = removeFirst popNext.scienceQuestions }
+ , Array.get 0 popNext.scienceQuestions
+ |> Maybe.withDefault "--- out of Science questions ---"
+ |> Rope.singleton
+ )
+
+ else
+ ( game, Rope.empty )
+
+ ( sportsNext, sportsLogs ) =
+ if currentCategory scienceNext == "Sports" then
+ ( { scienceNext | sportsQuestions = removeFirst scienceNext.sportsQuestions }
+ , Array.get 0 scienceNext.sportsQuestions
+ |> Maybe.withDefault "--- out of Sports questions ---"
+ |> Rope.singleton
+ )
+
+ else
+ ( game, Rope.empty )
+
+ ( rockNext, rockLogs ) =
+ if currentCategory sportsNext == "Rock" then
+ ( { sportsNext | rockQuestions = removeFirst sportsNext.rockQuestions }
+ , Array.get 0 sportsNext.rockQuestions
+ |> Maybe.withDefault "--- out of Rock questions ---"
+ |> Rope.singleton
+ )
+
+ else
+ ( game, Rope.empty )
+ in
+ ( rockNext
+ , Rope.appendTo
+ (Rope.appendTo popLogs scienceLogs)
+ (Rope.appendTo sportsLogs rockLogs)
+ )
+
+
+currentCategory : Game -> String
+currentCategory this =
+ if getUnsafe this.places this.currentPlayer == 0 then
+ "Pop"
+
+ else if getUnsafe this.places this.currentPlayer == 4 then
+ "Pop"
+
+ else if getUnsafe this.places this.currentPlayer == 8 then
+ "Pop"
+
+ else if getUnsafe this.places this.currentPlayer == 1 then
+ "Science"
+
+ else if getUnsafe this.places this.currentPlayer == 5 then
+ "Science"
+
+ else if getUnsafe this.places this.currentPlayer == 9 then
+ "Science"
+
+ else if getUnsafe this.places this.currentPlayer == 2 then
+ "Sports"
+
+ else if getUnsafe this.places this.currentPlayer == 6 then
+ "Sports"
+
+ else if getUnsafe this.places this.currentPlayer == 10 then
+ "Sports"
+
+ else
+ "Rock"
+
+
+wasCorrectlyAnswered : Game -> ( Bool, Game, Rope String )
+wasCorrectlyAnswered this =
+ if getUnsafe this.inPenaltyBox this.currentPlayer then
+ if this.isGettingOutOfPenaltyBox then
+ let
+ next =
+ { this | purses = Array.set this.currentPlayer (getUnsafe this.purses this.currentPlayer + 1) this.purses }
+
+ winner =
+ didPlayerWin next
+
+ next_ =
+ { next
+ | currentPlayer = next.currentPlayer + 1
+ }
+
+ next__ =
+ if next_.currentPlayer == Array.length next_.players then
+ { next_ | currentPlayer = 0 }
+
+ else
+ next_
+ in
+ ( winner
+ , next__
+ , [ "Answer was corrent!!!!"
+ , getUnsafe next.players next.currentPlayer ++ " now has " ++ String.fromInt (getUnsafe next.purses next.currentPlayer) ++ " Gold Coins."
+ ]
+ |> Rope.fromList
+ )
+
+ else
+ let
+ next =
+ { this
+ | currentPlayer = this.currentPlayer + 1
+ }
+
+ next_ =
+ if next.currentPlayer == Array.length next.players then
+ { next | currentPlayer = 0 }
+
+ else
+ next
+ in
+ ( True
+ , next_
+ , Rope.empty
+ )
+
+ else
+ let
+ next =
+ { this | purses = Array.set this.currentPlayer (getUnsafe this.purses this.currentPlayer + 1) this.purses }
+
+ winner =
+ didPlayerWin next
+
+ next_ =
+ { next
+ | currentPlayer = next.currentPlayer + 1
+ }
+
+ next__ =
+ if next_.currentPlayer == Array.length next_.players then
+ { next_ | currentPlayer = 0 }
+
+ else
+ next_
+ in
+ ( winner
+ , next__
+ , [ "Answer was corrent!!!!"
+ , getUnsafe next.players next.currentPlayer ++ " now has " ++ String.fromInt (getUnsafe next.purses next.currentPlayer) ++ " Gold Coins."
+ ]
+ |> Rope.fromList
+ )
+
+
+wrongAnswer : Game -> ( Bool, Game, Rope String )
+wrongAnswer this =
+ let
+ next =
+ { this
+ | inPenaltyBox = Array.set this.currentPlayer True this.inPenaltyBox
+ , currentPlayer = this.currentPlayer + 1
+ }
+
+ next_ =
+ if next.currentPlayer == Array.length next.players then
+ { next | currentPlayer = 0 }
+
+ else
+ next
+ in
+ ( True
+ , next_
+ , [ "Question was incorrectly answered"
+ , getUnsafe this.players this.currentPlayer ++ " was sent to the penalty box"
+ ]
+ |> Rope.fromList
+ )
+
+
+didPlayerWin : Game -> Bool
+didPlayerWin this =
+ not (getUnsafe this.purses this.currentPlayer == 6)
+
+
+
+-- Utilities to make the Array API more like imperative code
+-- You _should_ clean these up
+
+
+removeFirst : Array a -> Array a
+removeFirst array =
+ Array.slice 1 (Array.length array) array
+
+
+getUnsafe : Array a -> Int -> a
+getUnsafe arr index =
+ case Array.get index arr of
+ Nothing ->
+ Debug.todo <| "Out of boundary: " ++ String.fromInt index ++ " out of " ++ String.fromInt (Array.length arr)
+
+ Just e ->
+ e
diff --git a/Elm/src/Main.elm b/Elm/src/Main.elm
new file mode 100644
index 0000000000..77761eb542
--- /dev/null
+++ b/Elm/src/Main.elm
@@ -0,0 +1,81 @@
+module Main exposing (main, run)
+
+import Game exposing (Game)
+import Html exposing (Html, div, p, text)
+import Random exposing (Seed)
+import Rope exposing (Rope)
+
+
+main : Html msg
+main =
+ view run
+
+
+run : Rope String
+run =
+ let
+ ( game, initialLogs ) =
+ Game.init
+ |> andThen (Game.add "Chet")
+ |> andThen (Game.add "Pat")
+ |> andThen (Game.add "Sue")
+ in
+ go game initialLogs (Random.initialSeed 0)
+
+
+go : Game -> Rope String -> Seed -> Rope String
+go game queue seed =
+ let
+ ( upToFive, seed_ ) =
+ Random.step (Random.int 1 5) seed
+
+ ( upToEight, seed__ ) =
+ Random.step (Random.int 0 8) seed_
+
+ ( game_, rollLogs ) =
+ Game.roll (upToFive + 1) game
+
+ ( notAWinner, game__, answerLogs ) =
+ if upToEight == 7 then
+ Game.wrongAnswer game_
+
+ else
+ Game.wasCorrectlyAnswered game_
+
+ nextGame =
+ game__
+
+ nextQueue =
+ Rope.appendTo
+ (Rope.appendTo queue rollLogs)
+ answerLogs
+
+ nextSeed =
+ seed__
+ in
+ if notAWinner then
+ go nextGame nextQueue nextSeed
+
+ else
+ nextQueue
+
+
+view : Rope String -> Html msg
+view games =
+ games
+ |> Rope.toList
+ |> List.map (\line -> p [] [ text line ])
+ |> div []
+
+
+
+-- This part is used to collect the logs, you can ignore it
+
+
+andThen : (a -> ( b, Rope String )) -> ( a, Rope String ) -> ( b, Rope String )
+andThen f ( x, xlog ) =
+ let
+ ( fx, fxlog ) =
+ f x
+ in
+ ( fx, Rope.appendTo xlog fxlog )
diff --git a/Elm/tests/EndToEnd.elm b/Elm/tests/EndToEnd.elm
new file mode 100644
index 0000000000..fbfbc542bf
--- /dev/null
+++ b/Elm/tests/EndToEnd.elm
@@ -0,0 +1,151 @@
+module EndToEnd exposing (suite)
+
+import Expect
+import Main
+import Rope
+import Test exposing (Test, test)
+
+
+suite : Test
+suite =
+ test "Main test" <|
+ \_ ->
+ Main.run
+ |> Rope.toList
+ |> Expect.equal
+ game
+
+
+game : List String
+game =
+ [ "Chet was added"
+ , "They are player number 1"
+ , "Pat was added"
+ , "They are player number 2"
+ , "Sue was added"
+ , "They are player number 3"
+ , "Chet is the current player"
+ , "They have rolled a 5"
+ , "Chet's new location is 5"
+ , "The category is Science"
+ , "Science Question 0"
+ , "Answer was corrent!!!!"
+ , "Chet now has 1 Gold Coins."
+ , "Pat is the current player"
+ , "They have rolled a 3"
+ , "Pat's new location is 3"
+ , "The category is Rock"
+ , "Rock Question 0"
+ , "Answer was corrent!!!!"
+ , "Pat now has 1 Gold Coins."
+ , "Sue is the current player"
+ , "They have rolled a 6"
+ , "Sue's new location is 6"
+ , "The category is Sports"
+ , "Sports Question 0"
+ , "Answer was corrent!!!!"
+ , "Sue now has 1 Gold Coins."
+ , "Chet is the current player"
+ , "They have rolled a 6"
+ , "Chet's new location is 11"
+ , "The category is Rock"
+ , "Rock Question 1"
+ , "Answer was corrent!!!!"
+ , "Chet now has 2 Gold Coins."
+ , "Pat is the current player"
+ , "They have rolled a 5"
+ , "Pat's new location is 8"
+ , "The category is Pop"
+ , "Pop Question 0"
+ , "Question was incorrectly answered"
+ , "Pat was sent to the penalty box"
+ , "Sue is the current player"
+ , "They have rolled a 6"
+ , "Sue's new location is 0"
+ , "The category is Pop"
+ , "Pop Question 0"
+ , "Answer was corrent!!!!"
+ , "Sue now has 2 Gold Coins."
+ , "Chet is the current player"
+ , "They have rolled a 3"
+ , "Chet's new location is 2"
+ , "The category is Sports"
+ , "Sports Question 0"
+ , "Answer was corrent!!!!"
+ , "Chet now has 3 Gold Coins."
+ , "Pat is the current player"
+ , "They have rolled a 5"
+ , "Pat is getting out of the penalty box"
+ , "Pat's new location is 1"
+ , "The category is Science"
+ , "Science Question 0"
+ , "Answer was corrent!!!!"
+ , "Pat now has 2 Gold Coins."
+ , "Sue is the current player"
+ , "They have rolled a 2"
+ , "Sue's new location is 2"
+ , "The category is Sports"
+ , "Sports Question 0"
+ , "Answer was corrent!!!!"
+ , "Sue now has 3 Gold Coins."
+ , "Chet is the current player"
+ , "They have rolled a 3"
+ , "Chet's new location is 5"
+ , "The category is Science"
+ , "Science Question 0"
+ , "Question was incorrectly answered"
+ , "Chet was sent to the penalty box"
+ , "Pat is the current player"
+ , "They have rolled a 3"
+ , "Pat's new location is 4"
+ , "The category is Pop"
+ , "Pop Question 0"
+ , "Answer was corrent!!!!"
+ , "Pat now has 3 Gold Coins."
+ , "Sue is the current player"
+ , "They have rolled a 5"
+ , "Sue's new location is 7"
+ , "The category is Rock"
+ , "Rock Question 2"
+ , "Answer was corrent!!!!"
+ , "Sue now has 4 Gold Coins."
+ , "Chet is the current player"
+ , "They have rolled a 4"
+ , "Chet is not getting out of the penalty box"
+ , "Pat is the current player"
+ , "They have rolled a 5"
+ , "Pat's new location is 9"
+ , "The category is Science"
+ , "Science Question 0"
+ , "Answer was corrent!!!!"
+ , "Pat now has 4 Gold Coins."
+ , "Sue is the current player"
+ , "They have rolled a 6"
+ , "Sue's new location is 1"
+ , "The category is Science"
+ , "Science Question 0"
+ , "Answer was corrent!!!!"
+ , "Sue now has 5 Gold Coins."
+ , "Chet is the current player"
+ , "They have rolled a 5"
+ , "Chet is getting out of the penalty box"
+ , "Chet's new location is 10"
+ , "The category is Sports"
+ , "Sports Question 0"
+ , "Answer was corrent!!!!"
+ , "Chet now has 4 Gold Coins."
+ , "Pat is the current player"
+ , "They have rolled a 5"
+ , "Pat's new location is 2"
+ , "The category is Sports"
+ , "Sports Question 0"
+ , "Answer was corrent!!!!"
+ , "Pat now has 5 Gold Coins."
+ , "Sue is the current player"
+ , "They have rolled a 6"
+ , "Sue's new location is 7"
+ , "The category is Rock"
+ , "Rock Question 3"
+ , "Answer was corrent!!!!"
+ , "Sue now has 6 Gold Coins."
+ ]
diff --git a/Elm/yarn.lock b/Elm/yarn.lock
new file mode 100644
index 0000000000..cf63f426e0
--- /dev/null
+++ b/Elm/yarn.lock
@@ -0,0 +1,310 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+ansi-styles@^4.1.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
+ integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
+ dependencies:
+ color-convert "^2.0.1"
+
+anymatch@~3.1.2:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
+ integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
+ dependencies:
+ normalize-path "^3.0.0"
+ picomatch "^2.0.4"
+
+balanced-match@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
+ integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+
+binary-extensions@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
+ integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
+
+brace-expansion@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
+ integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
+ dependencies:
+ balanced-match "^1.0.0"
+
+braces@~3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
+ integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
+ dependencies:
+ fill-range "^7.0.1"
+
+chalk@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
+ integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
+ dependencies:
+ ansi-styles "^4.1.0"
+ supports-color "^7.1.0"
+
+chokidar@^3.5.3:
+ version "3.5.3"
+ resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
+ integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
+ dependencies:
+ anymatch "~3.1.2"
+ braces "~3.0.2"
+ glob-parent "~5.1.2"
+ is-binary-path "~2.1.0"
+ is-glob "~4.0.1"
+ normalize-path "~3.0.0"
+ readdirp "~3.6.0"
+ optionalDependencies:
+ fsevents "~2.3.2"
+
+color-convert@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
+ integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+ dependencies:
+ color-name "~1.1.4"
+
+color-name@~1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
+ integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+
+commander@^9.4.1:
+ version "9.5.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30"
+ integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==
+
+cross-spawn@^7.0.3:
+ version "7.0.3"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
+ integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
+ dependencies:
+ path-key "^3.1.0"
+ shebang-command "^2.0.0"
+ which "^2.0.1"
+
+elm-solve-deps-wasm@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/elm-solve-deps-wasm/-/elm-solve-deps-wasm-1.0.2.tgz#cabd3cadf344295944b8d046a857b6ee05e12aaf"
+ integrity sha512-qnwo7RO9IO7jd9SLHvIy0rSOEIlc/tNMTE9Cras0kl+b161PVidW4FvXo0MtXU8GAKi/2s/HYvhcnpR/NNQ1zw==
+
+elm-test@^0.19.1-revision12:
+ version "0.19.1-revision12"
+ resolved "https://registry.yarnpkg.com/elm-test/-/elm-test-0.19.1-revision12.tgz#8932cf58b388cff8d23c7cf2b80adc66249aa797"
+ integrity sha512-5GV3WkJ8R/faOP1hwElQdNuCt8tKx2+1lsMrdeIYWSFz01Kp9gJl/R6zGtp4QUyrUtO8KnHsxjHrQNUf2CHkrg==
+ dependencies:
+ chalk "^4.1.2"
+ chokidar "^3.5.3"
+ commander "^9.4.1"
+ cross-spawn "^7.0.3"
+ elm-solve-deps-wasm "^1.0.2"
+ glob "^8.0.3"
+ graceful-fs "^4.2.10"
+ split "^1.0.1"
+ which "^2.0.2"
+ xmlbuilder "^15.1.1"
+
+elm-watch@^1.2.0-beta.3:
+ version "1.2.0-beta.3"
+ resolved "https://registry.yarnpkg.com/elm-watch/-/elm-watch-1.2.0-beta.3.tgz#60d3689cd368035397bf6a6d24dd80148ef1743f"
+ integrity sha512-08DLRXCeu1s2nvbrNlo9Npn6dvwJwq61DiNC5rprYbTVkB0b0OKNVVUVidzouesiQHpRDRBnED9ejo4gp9ft3g==
+ dependencies:
+ chokidar "^3.5.3"
+ cross-spawn "^7.0.3"
+ tiny-decoders "^7.0.1"
+ ws "^8.12.0"
+
+fill-range@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
+ integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
+ dependencies:
+ to-regex-range "^5.0.1"
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+ integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
+
+fsevents@~2.3.2:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
+ integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
+
+glob-parent@~5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
+ integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+ dependencies:
+ is-glob "^4.0.1"
+
+glob@^8.0.3:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e"
+ integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^5.0.1"
+ once "^1.3.0"
+
+graceful-fs@^4.2.10:
+ version "4.2.11"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
+ integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
+
+has-flag@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
+ integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+
+inflight@^1.0.4:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+ integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
+ dependencies:
+ once "^1.3.0"
+ wrappy "1"
+
+inherits@2:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+is-binary-path@~2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
+ integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
+ dependencies:
+ binary-extensions "^2.0.0"
+
+is-extglob@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+ integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
+
+is-glob@^4.0.1, is-glob@~4.0.1:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
+ integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
+ dependencies:
+ is-extglob "^2.1.1"
+
+is-number@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
+ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+ integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
+
+minimatch@^5.0.1:
+ version "5.1.6"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96"
+ integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==
+ dependencies:
+ brace-expansion "^2.0.1"
+
+normalize-path@^3.0.0, normalize-path@~3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
+ integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
+
+once@^1.3.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
+ dependencies:
+ wrappy "1"
+
+path-key@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
+ integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
+
+picomatch@^2.0.4, picomatch@^2.2.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
+ integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+
+readdirp@~3.6.0:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
+ integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
+ dependencies:
+ picomatch "^2.2.1"
+
+shebang-command@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
+ integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
+ dependencies:
+ shebang-regex "^3.0.0"
+
+shebang-regex@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
+ integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
+
+split@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9"
+ integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==
+ dependencies:
+ through "2"
+
+supports-color@^7.1.0:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
+ integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
+ dependencies:
+ has-flag "^4.0.0"
+
+through@2:
+ version "2.3.8"
+ resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
+ integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
+
+tiny-decoders@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/tiny-decoders/-/tiny-decoders-7.0.1.tgz#ce80d377a214a5c46ffdd37b3b14f64e91215210"
+ integrity sha512-P1LaHTLASl/lCrdtwgAAVwxt4bEAPmxpf9HMQrlCkAseaT8oH8oxm8ndy4nx5rLTcL5U/Qxp1a+FDoQfS/ZgQQ==
+
+to-regex-range@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
+ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+ dependencies:
+ is-number "^7.0.0"
+
+which@^2.0.1, which@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
+ integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
+ dependencies:
+ isexe "^2.0.0"
+
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+ integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
+
+ws@^8.12.0:
+ version "8.14.2"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f"
+ integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==
+
+xmlbuilder@^15.1.1:
+ version "15.1.1"
+ resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz#9dcdce49eea66d8d10b42cae94a79c3c8d0c2ec5"
+ integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==