module Game exposing (Model, init, Msg(..), update, view, subscriptions)

import Html exposing (Html, div, text, br, h1)
import Html.Attributes exposing (class)
import Html.App as App
import Time exposing (Time)
import Level

--MODEL

type alias Level =
    Level.Model

type alias Model =
    { level : Level
    }

init : Int -> Int -> Model
init cols rows =
    { level = Level.init cols rows 0
    }

--UPDATE

type Msg
    = LevelMsg Level.Msg
    | Tick Time

update : Msg -> Model -> Model
update msg model =
    case msg of
        LevelMsg lMsg ->
            { model | level = Level.update lMsg model.level }

        Tick t ->
            { model | level = Level.update (Level.Tick t) model.level }

--SUBSCRIPTIONS

subscriptions : Model -> Sub Msg
subscriptions model =
    Time.every (10 * Time.millisecond) Tick

--VIEW

view : Model -> Html Msg
view model =
    div [ class "game-box" ]
        [ h1 [] [ text "Lights Out" ]
        , App.map LevelMsg (Level.view model.level)
        , br [] []
        , text <| "Moves: " ++ toString (List.length model.level.history)
        , br [] []
        , text <| "Time: " ++ toString (floor << Time.inSeconds <| model.level.elapsedTime)
        ]

Add type for routing between the current level, main menu and pause menu.

module Game exposing (Model, init, Msg(..), update, view, subscriptions)

import Html exposing (Html, div, text, br, h1)
import Html.Attributes exposing (class)
import Html.App as App
import Time exposing (Time)
import Level

--MODEL

type alias Level =
    Level.Model

type View
    = GameView
    | MainMenu
    | Pause

type alias Model =
    { level : Level
    }

init : Int -> Int -> Model
init cols rows =
    { level = Level.init cols rows 0
    }

--UPDATE

type Msg
    = LevelMsg Level.Msg
    | Tick Time

update : Msg -> Model -> Model
update msg model =
    case msg of
        LevelMsg lMsg ->
            { model | level = Level.update lMsg model.level }

        Tick t ->
            { model | level = Level.update (Level.Tick t) model.level }

--SUBSCRIPTIONS

subscriptions : Model -> Sub Msg
subscriptions model =
    Time.every (10 * Time.millisecond) Tick

--VIEW

view : Model -> Html Msg
view model =
    div [ class "game-box" ]
        [ h1 [] [ text "Lights Out" ]
        , App.map LevelMsg (Level.view model.level)
        , br [] []
        , text <| "Moves: " ++ toString (List.length model.level.history)
        , br [] []
        , text <| "Time: " ++ toString (floor << Time.inSeconds <| model.level.elapsedTime)
        ]


import Html.App as App
import Html exposing (Html)

import IdeaFight.LandingPage as LandingPage

type Model = LandingPageModel LandingPage.Model
type Msg   = LandingPageMsg LandingPage.Msg

mapTEA : (modela -> modelb) -> (msga -> msgb) -> (modela, Cmd msga) -> (modelb, Cmd msgb)
mapTEA modelTransform msgTransform (oldModel, oldCmd) =
  (modelTransform oldModel, Cmd.map msgTransform oldCmd)

init : (Model, Cmd Msg)
init = mapTEA LandingPageModel LandingPageMsg <| LandingPage.init

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  let _ = Debug.log "model" model in
  case (msg, model) of
    (LandingPageMsg msg, LandingPageModel model) -> mapTEA LandingPageModel LandingPageMsg <| LandingPage.update msg model

subscriptions : Model -> Sub Msg
subscriptions model =
  case model of
    LandingPageModel model -> Sub.map LandingPageMsg <| LandingPage.subscriptions model

view : Model -> Html Msg
view model =
  case model of
    LandingPageModel model -> App.map LandingPageMsg <| LandingPage.view model

main : Program Never
main = App.program {
    init = init,
    update = update,
    subscriptions = subscriptions,
    view = view
  }

Add simple binding for compete subapp

import Html.App as App
import Html exposing (Html)

import IdeaFight.LandingPage as LandingPage
import IdeaFight.Compete as Compete

type Model = LandingPageModel LandingPage.Model | CompeteModel Compete.Model
type Msg   = LandingPageMsg LandingPage.Msg | CompeteMsg Compete.Msg

mapTEA : (modela -> modelb) -> (msga -> msgb) -> (modela, Cmd msga) -> (modelb, Cmd msgb)
mapTEA modelTransform msgTransform (oldModel, oldCmd) =
  (modelTransform oldModel, Cmd.map msgTransform oldCmd)

init : (Model, Cmd Msg)
init = mapTEA LandingPageModel LandingPageMsg <| LandingPage.init

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case (msg, model) of
    (LandingPageMsg msg, LandingPageModel model) -> mapTEA LandingPageModel LandingPageMsg <| LandingPage.update msg model
    (CompeteMsg msg, CompeteModel model)         -> mapTEA CompeteModel CompeteMsg         <| Compete.update msg model

    (_, _) -> Debug.crash "Model-Message mismatch"

subscriptions : Model -> Sub Msg
subscriptions model =
  case model of
    LandingPageModel model -> Sub.map LandingPageMsg <| LandingPage.subscriptions model
    CompeteModel model -> Sub.map CompeteMsg <| Compete.subscriptions model

view : Model -> Html Msg
view model =
  case model of
    LandingPageModel model -> App.map LandingPageMsg <| LandingPage.view model
    CompeteModel model -> App.map CompeteMsg <| Compete.view model

main : Program Never
main = App.program {
    init = init,
    update = update,
    subscriptions = subscriptions,
    view = view
  }


module Update (..) where

import Models exposing (..)
import Debug
import Actions exposing (..)
import Effects exposing (Effects)
import Routing
import Mailboxes exposing (..)
import Meals.Update
import Meals.Effects

update : Action -> AppModel -> ( AppModel, Effects Action )
update action model =
  case (Debug.log "update" action) of
    MealsAction subAction ->
      let
        updateModel =
          { meals = model.meals
          , currentMeal = model.currentMeal
          , errorAddress = Signal.forwardTo actionsMailbox.address ShowError
          , deleteConfirmationAddress = deleteConfirmationMailbox.address
          }

        ( updatedMeals, updatedCurrentMeal, fx ) =
          Meals.Update.update subAction updateModel
      in
        ( { model | meals = updatedMeals, currentMeal = updatedCurrentMeal }, Effects.map MealsAction fx )

    RoutingAction subAction ->
      let
        ( updatedRouting, fx ) =
          Routing.update subAction model.routing

        dataFx =
          case updatedRouting.route of
            Routing.MealShowRoute mealId ->
              Effects.map MealsAction (Meals.Effects.fetchOne mealId)

            _ ->
              Effects.none

        combinedFx =
          Effects.batch [ dataFx, Effects.map RoutingAction fx ]
      in
        ( { model | routing = updatedRouting }, combinedFx )

    ShowError message ->
      ( { model | errorMessage = message }, Effects.none )

    NoOp ->
      ( model, Effects.none )

Fix edit route not fetching data

module Update (..) where

import Models exposing (..)
import Debug
import Actions exposing (..)
import Effects exposing (Effects)
import Routing
import Mailboxes exposing (..)
import Meals.Update
import Meals.Effects

update : Action -> AppModel -> ( AppModel, Effects Action )
update action model =
  case (Debug.log "update" action) of
    MealsAction subAction ->
      let
        updateModel =
          { meals = model.meals
          , currentMeal = model.currentMeal
          , errorAddress = Signal.forwardTo actionsMailbox.address ShowError
          , deleteConfirmationAddress = deleteConfirmationMailbox.address
          }

        ( updatedMeals, updatedCurrentMeal, fx ) =
          Meals.Update.update subAction updateModel
      in
        ( { model | meals = updatedMeals, currentMeal = updatedCurrentMeal }, Effects.map MealsAction fx )

    RoutingAction subAction ->
      let
        ( updatedRouting, fx ) =
          Routing.update subAction model.routing

        dataFx =
          case updatedRouting.route of
            Routing.MealShowRoute mealId ->
              Effects.map MealsAction (Meals.Effects.fetchOne mealId)

            Routing.MealEditRoute mealId ->
              Effects.map MealsAction (Meals.Effects.fetchOne mealId)

            _ ->
              Effects.none

        combinedFx =
          Effects.batch [ dataFx, Effects.map RoutingAction fx ]
      in
        ( { model | routing = updatedRouting }, combinedFx )

    ShowError message ->
      ( { model | errorMessage = message }, Effects.none )

    NoOp ->
      ( model, Effects.none )


module Main exposing (..)

import Navigation
import View
import Update
import Model exposing (Model)
import Types exposing (User)
import Route
import Msg exposing (Msg(..))
import Task
import Material
import Http
import Decoders

main : Program Never
main =
    Navigation.program (Navigation.makeParser Route.locFor)
        { init = Model.init
        , update = Update.update
        , urlUpdate = urlUpdate
        , view = View.view
        , subscriptions = subscriptions
        }

subscriptions : Model -> Sub Msg
subscriptions model =
    Material.subscriptions Mdl model

urlUpdate : Maybe Route.Location -> Model -> ( Model, Cmd Msg )
urlUpdate route model =
    let
        newModel =
            { model | route = route }
    in
        case route of
            Just (Route.Users) ->
                -- Pretend we did an API call and it got us some new users
                newModel ! [ fetchUsers newModel ]

            _ ->
                newModel ! []

fetchUsers : Model -> Cmd Msg
fetchUsers newModel =
    -- This "error condition" that just says we got no users is dumb, we should log something and inform the UI
    Task.perform (always (GotUsers [])) GotUsers (Http.get Decoders.usersDecoder "http://localhost:4000/users")

fetchMockUsers : Model -> Cmd Msg
fetchMockUsers newModel =
    Task.perform
        (always <| GotUsers (mockUser :: newModel.users))
        (always <| GotUsers (mockUser :: newModel.users))
        (Task.succeed ())

mockUser : User
mockUser =
    { name = "Jumpy McFiddlepants" }

Stop using the API for now

module Main exposing (..)

import Navigation
import View
import Update
import Model exposing (Model)
import Types exposing (User)
import Route
import Msg exposing (Msg(..))
import Task
import Material
import Http
import Decoders

main : Program Never
main =
    Navigation.program (Navigation.makeParser Route.locFor)
        { init = Model.init
        , update = Update.update
        , urlUpdate = urlUpdate
        , view = View.view
        , subscriptions = subscriptions
        }

subscriptions : Model -> Sub Msg
subscriptions model =
    Material.subscriptions Mdl model

urlUpdate : Maybe Route.Location -> Model -> ( Model, Cmd Msg )
urlUpdate route model =
    let
        newModel =
            { model | route = route }
    in
        case route of
            Just (Route.Users) ->
                -- Pretend we did an API call and it got us some new users
                newModel ! [ fetchMockUsers newModel ]

            _ ->
                newModel ! []

fetchUsers : Model -> Cmd Msg
fetchUsers model =
    -- This "error condition" that just says we got no users is dumb, we should log something and inform the UI
    Task.perform (always (GotUsers [])) GotUsers (Http.get Decoders.usersDecoder "http://localhost:4000/users")

fetchMockUsers : Model -> Cmd Msg
fetchMockUsers model =
    Task.perform
        (always <| GotUsers (mockUser :: model.users))
        (always <| GotUsers (mockUser :: model.users))
        (Task.succeed ())

mockUser : User
mockUser =
    { name = "Jumpy McFiddlepants" }


module Nav.Nav exposing (..)

import Navigation
import UrlParser exposing (Parser, (</>), oneOf, map, s, string, parseHash, top)
import Nav.Model exposing (Page(..))

toHash : Page -> String
toHash page =
    case page of
        Components ->
            "#"

        Component env system component server ->
            "#component/" ++ env ++ "/" ++ system ++ "/" ++ component ++ "/" ++ server

hashParser : Navigation.Location -> Page
hashParser location =
    Maybe.withDefault Components <| parseHash pageParser location

pageParser : Parser (Page -> a) a
pageParser =
    oneOf
        [ map Components top
        , map Component (s "component" </> string </> string </> string </> string)
        ]

Use String.join instead of ++

module Nav.Nav exposing (..)

import Navigation
import UrlParser exposing (Parser, (</>), oneOf, map, s, string, parseHash, top)
import Nav.Model exposing (Page(..))
import String exposing (join)

toHash : Page -> String
toHash page =
    case page of
        Components ->
            "#"

        Component env system component server ->
            join "/" [ "#component", env, system, component, server ]

hashParser : Navigation.Location -> Page
hashParser location =
    Maybe.withDefault Components <| parseHash pageParser location

pageParser : Parser (Page -> a) a
pageParser =
    oneOf
        [ map Components top
        , map Component (s "component" </> string </> string </> string </> string)
        ]


module Toolbox.Update exposing (..)

import Dict
import Http
import Set
import Toolbox.Types exposing (Model, IngredientID, Response)

type Msg
    = DownloadedIngredients Response
    | DownloadFailed Http.Error
    | SelectIngredient IngredientID
    | NoOp

update : Msg -> Model -> ( Model, Cmd Msg )
update action model =
    case action of
        DownloadedIngredients maybeResponse ->
            ( responseToModel model maybeResponse
            , Cmd.none
            )

        -- TODO: handle HTTP errors
        DownloadFailed _ ->
            ( model, Cmd.none )

        SelectIngredient id ->
            ( { model | selectedIds = updateIds id model.selectedIds }
            , Cmd.none
            )

        NoOp ->
            ( model, Cmd.none )

updateIds : IngredientID -> Set.Set IngredientID -> Set.Set IngredientID
updateIds id selectedIds =
    if Set.member id selectedIds then
        Set.remove id selectedIds
    else if Set.size selectedIds < 4 then
        Set.insert id selectedIds
    else
        selectedIds

enumerate : List a -> List ( Int, a )
enumerate list =
    let
        ids =
            [1..(List.length list - 1)]
    in
        List.map2 (,) ids list

responseToModel : Model -> Response -> Model
responseToModel model response =
    { model | ingredients = enumerate response.ingredients |> Dict.fromList }

Allow to select max 3 ingredients.

module Toolbox.Update exposing (..)

import Dict
import Http
import Set
import Toolbox.Types exposing (Model, IngredientID, Response)

type Msg
    = DownloadedIngredients Response
    | DownloadFailed Http.Error
    | SelectIngredient IngredientID
    | NoOp

update : Msg -> Model -> ( Model, Cmd Msg )
update action model =
    case action of
        DownloadedIngredients maybeResponse ->
            ( responseToModel model maybeResponse
            , Cmd.none
            )

        -- TODO: handle HTTP errors
        DownloadFailed _ ->
            ( model, Cmd.none )

        SelectIngredient id ->
            ( { model | selectedIds = updateIds id model.selectedIds }
            , Cmd.none
            )

        NoOp ->
            ( model, Cmd.none )

updateIds : IngredientID -> Set.Set IngredientID -> Set.Set IngredientID
updateIds id selectedIds =
    if Set.member id selectedIds then
        Set.remove id selectedIds
    else if Set.size selectedIds < 3 then
        Set.insert id selectedIds
    else
        selectedIds

enumerate : List a -> List ( Int, a )
enumerate list =
    let
        ids =
            [1..(List.length list - 1)]
    in
        List.map2 (,) ids list

responseToModel : Model -> Response -> Model
responseToModel model response =
    { model | ingredients = enumerate response.ingredients |> Dict.fromList }


main = draw <~ ball

-- Draw the sky, ball, and ground
draw ball =
  collage 200 400
   [ rect 200 400 |> filled (rgb 135 206 250)
   , circle 15    |> filled red
                  |> move (0, ball.height - 160)
   , rect 200 50  |> filled green
                  |> move (0,-200)
   ]

-- Physics
gravity = 140
bounceVelocity = 250

step time ball =
  { ball | height   <- ball.height + ball.velocity * time,
           velocity <- if | ball.height < 0 -> bounceVelocity
                          | otherwise -> ball.velocity - gravity * time }

ball = foldp step {height=0, velocity=bounceVelocity}
                  (inSeconds <~ fps 30)

Make the bounce world skinnier

main = draw <~ ball

-- Draw the sky, ball, and ground
draw ball =
  collage 150 400
   [ rect 150 400 |> filled (rgb 135 206 250)
   , circle 15    |> filled red
                  |> move (0, ball.height - 160)
   , rect 150 50  |> filled green
                  |> move (0,-200)
   ]

-- Physics
gravity = 140
bounceVelocity = 250

step time ball =
  { ball | height   <- ball.height + ball.velocity * time,
           velocity <- if | ball.height < 0 -> bounceVelocity
                          | otherwise -> ball.velocity - gravity * time }

ball = foldp step {height=0, velocity=bounceVelocity}
                  (inSeconds <~ fps 30)


module Main exposing (..)

import Browser
import Html exposing (Html, text, div, h1, img)
import Html.Attributes exposing (src)

---- MODEL ----

type alias Model =
    {}

init : ( Model, Cmd Msg )
init =
    ( {}, Cmd.none )

---- UPDATE ----

type Msg
    = NoOp

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    ( model, Cmd.none )

---- VIEW ----

view : Model -> Html Msg
view model =
    div []
        [ img [ src "/logo.svg" ] []
        , h1 [] [ text "Your Elm App is working!" ]
        ]

---- PROGRAM ----

main : Program () Model Msg
main =
    Browser.element
        { view = view
        , init = \_ -> init
        , update = update
        , subscriptions = always Sub.none
        }

Add counter example in Elm

module Main exposing (Model, Msg(..), init, main, update, view)

import Browser
import Html exposing (Html, button, div, h1, img, text)
import Html.Attributes exposing (src)
import Html.Events exposing (onClick)

---- MODEL ----

type alias Model =
    Int

init : ( Model, Cmd Msg )
init =
    ( 0, Cmd.none )

---- UPDATE ----

type Msg
    = Increment
    | Decrement

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Increment ->
            ( model + 1, Cmd.none )

        Decrement ->
            ( model - 1, Cmd.none )

---- VIEW ----

view : Model -> Browser.Document Msg
view model =
    { title = "Trackflix"
    , body =
        [ div []
            [ img [ src "/logo.svg" ] []
            , h1 [] [ text "Your Elm App is working!" ]
            ]
        , div []
            [ button [ onClick Decrement ] [ text "-" ]
            , div [] [ text (String.fromInt model) ]
            , button [ onClick Increment ] [ text "+" ]
            ]
        ]
    }

---- PROGRAM ----

main : Program () Model Msg
main =
    Browser.document
        { view = view
        , init = \_ -> init
        , update = update
        , subscriptions = always Sub.none
        }


import Mouse
import Window

main = lift2 scene Window.dimensions clickLocations

-- for a good time, remove "sampleOn Mouse.clicks" ;)
clickLocations = foldp (::) [] (sampleOn Mouse.clicks Mouse.position)

scene (w,h) locs =
  let drawPentagon (x,y) =
          ngon 5 20 |> filled (hsva (toFloat x) 1 1 0.7)
                    |> move (toFloat x - toFloat w / 2, toFloat h / 2 - toFloat y)
                    |> rotate (toFloat x)
  in  layers [ collage w h (map drawPentagon locs)
             , plainText "Click to stamp a pentagon." ]

Make example clearer and thinner

import Mouse
import Window

main : Signal Element
main = lift2 scene Window.dimensions clickLocations

clickLocations : Signal [(Int,Int)]
clickLocations = foldp (::) [] (sampleOn Mouse.clicks Mouse.position)

scene : (Int,Int) -> [(Int,Int)] -> Element
scene (w,h) locs =
  let drawPentagon (x,y) =
          ngon 5 20
            |> filled (hsva (toFloat x) 1 1 0.7)
            |> move (toFloat x - toFloat w/2, toFloat h/2 - toFloat y)
            |> rotate (toFloat x)
  in
      layers [ collage w h (map drawPentagon locs)
             , plainText "Click to stamp a pentagon."
             ]


module Simulator.Input where

import Json.Decode as Json exposing (..)

import Simulator.Cell exposing (Cell)
import Simulator.Unit exposing (Unit)

type alias Input =
  { id: Int
  , width: Int
  , height: Int
  , filled: List Cell
  , units: List Unit
  , sourceSeeds: List Int
  , sourceLength: Int
  }

parse : String -> Maybe Input
parse inputString =
  Result.toMaybe (decodeString decoder inputString)

decoder : Decoder Input
decoder =
  object7 Input
    ("id" := int)
    ("width" := int)
    ("height" := int)
    ("filled" := list cell)
    ("units" := list unit)
    ("sourceSeeds" := list int)
    ("sourceLength" := int)

cell : Decoder Cell
cell =
  object2 (,)
    ("x" := int)
    ("y" := int)

unit : Decoder Unit
unit =
  object2 Unit
    ("members" := list cell)
    ("pivot" := cell)

Convert coordinates when reading input

module Simulator.Input where

import Json.Decode as Json exposing (..)

import Simulator.Cell exposing (Cell, fromInputCell, InputCell(..))
import Simulator.Unit exposing (Unit)

type alias Input =
  { id: Int
  , width: Int
  , height: Int
  , filled: List Cell
  , units: List Unit
  , sourceSeeds: List Int
  , sourceLength: Int
  }

parse : String -> Maybe Input
parse inputString =
  Result.toMaybe (decodeString decoder inputString)

decoder : Decoder Input
decoder =
  object7 Input
    ("id" := int)
    ("width" := int)
    ("height" := int)
    ("filled" := list cell)
    ("units" := list unit)
    ("sourceSeeds" := list int)
    ("sourceLength" := int)

cell : Decoder Cell
cell =
  let
    convert x y = fromInputCell (InputCell (x, y))
  in
    object2 convert
      ("x" := int)
      ("y" := int)

unit : Decoder Unit
unit =
  object2 Unit
    ("members" := list cell)
    ("pivot" := cell)


import Html exposing (..)
import Html.Events exposing (onClick)
import StartApp

main =
  StartApp.start { model = init, view = view, update = update }

-- Model

type alias AppState =
  { nextID : Int
  , layers : List ( ID, String )
  }

type alias ID = Int

init : AppState
init =
  { layers = [(0, "one"), (1, "two")]
  , nextID = 2
  }

-- Views

view : Signal.Address Action -> AppState -> Html
view address model =
  div []
        [ ul []
             (List.map (viewLayer address) model.layers)
        , button [ onClick address Add ] [ text "+" ]
        ]

viewLayer : Signal.Address Action -> ( ID, String ) -> Html
viewLayer address (id, layer) =
  li []
     [ text layer
     , button [ onClick address (Remove id) ] [ text "x" ] ]

-- Actions

type Action
  = Add
  | Remove ID

update : Action -> AppState -> AppState
update action model =
  case action of
    Add -> { model | layers <- model.layers ++ [(model.nextID, "another")]
                   , nextID <- model.nextID + 1 }
    Remove id -> { model | layers <- List.filter (\(layerID, _) -> layerID /= id) model.layers }

Change in formatting, so it doesn't look like the ( is being backslash-escaped

import Html exposing (..)
import Html.Events exposing (onClick)
import StartApp

main =
  StartApp.start { model = init, view = view, update = update }

-- Model

type alias AppState =
  { nextID : Int
  , layers : List ( ID, String )
  }

type alias ID = Int

init : AppState
init =
  { layers = [(0, "one"), (1, "two")]
  , nextID = 2
  }

-- Views

view : Signal.Address Action -> AppState -> Html
view address model =
  div []
        [ ul []
             (List.map (viewLayer address) model.layers)
        , button [ onClick address Add ] [ text "+" ]
        ]

viewLayer : Signal.Address Action -> ( ID, String ) -> Html
viewLayer address (id, layer) =
  li []
     [ text layer
     , button [ onClick address (Remove id) ] [ text "x" ] ]

-- Actions

type Action
  = Add
  | Remove ID

update : Action -> AppState -> AppState
update action model =
  case action of
    Add -> { model | layers <- model.layers ++ [(model.nextID, "another")]
                   , nextID <- model.nextID + 1 }
    Remove id -> { model | layers <- List.filter (\ (layerID, _) -> layerID /= id) model.layers }


port module Keystone exposing (..)

import Html exposing (..)
import Html.App as Html
import Html.Attributes as Att exposing (..)
-- import Html.Events exposing (onClick, onInput, onCheck)
-- import String

main : Program Never
main =
  Html.program
   { init = init
   , view = view
   , update = update
   , subscriptions = subscriptions}

init : (Model, Cmd Msg)
init =
   (Model, Cmd.none)

port notify : String -> Cmd msg

-- Request a parse of the full input text
port parse : (String -> msg) -> Sub msg

subscriptions : Model -> Sub Msg
subscriptions model =
  parse Parse

type alias Model = { }

type Msg = Reset
  | Parse String

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    Reset -> (model, Cmd.none)
    Parse text -> (model, notify text) -- TODO Implement this

view : Model -> Html Msg
view model =
    div [ id "main", class "col-lg-6" ] [ text "Keystone! Yeah!" ]

Fix compilation errors from Elm upgrade.

port module Keystone exposing (..)

import Html exposing (..)
import Html.Attributes as Att exposing (..)
-- import Html.Events exposing (onClick, onInput, onCheck)
-- import String

main : Program Never Model Msg
main =
  program
   { init = init
   , view = view
   , update = update
   , subscriptions = subscriptions}

init : (Model, Cmd Msg)
init =
   (Model, Cmd.none)

port notify : String -> Cmd msg

-- Request a parse of the full input text
port parse : (String -> msg) -> Sub msg

subscriptions : Model -> Sub Msg
subscriptions model =
  parse Parse

type alias Model = { }

type Msg = Reset
  | Parse String

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    Reset -> (model, Cmd.none)
    Parse text -> (model, notify text) -- TODO Implement this

view : Model -> Html Msg
view model =
    div [ id "main", class "col-lg-6" ] [ text "Keystone! Yeah!" ]


module Dreamwriter.View.CurrentDoc (view) where

import Dreamwriter.Doc (..)
import Dreamwriter.Action (..)

import Html (..)
import Html.Attributes (..)
import Html.Events (..)
import Html.Tags (..)

view : Doc -> Html
view currentDoc =
  div [key "current-doc-view", id "current-doc-view"] [
    div [id "title", onclick navigateToTitleInput.handle (always ())]
      [text currentDoc.title],

    viewOutline currentDoc.chapters,

    div [id "add-chapter", class "flaticon-add139"] []
  ]

viewOutline : [Chapter] -> Html
viewOutline chapters =
  ul [id "outline"] <| indexedMap viewChapter chapters

viewChapter : Int -> Chapter -> Html
viewChapter index chapter = li [
    key ("chapter" ++ (show index)),
    title chapter.heading,
    onclick navigateToChapterIdInput.handle (always chapter.id)
  ] [text chapter.heading]

Make add-chapter a span so it doesn't take up the whole line.

module Dreamwriter.View.CurrentDoc (view) where

import Dreamwriter.Doc (..)
import Dreamwriter.Action (..)

import Html (..)
import Html.Attributes (..)
import Html.Events (..)
import Html.Tags (..)

view : Doc -> Html
view currentDoc =
  div [key "current-doc-view", id "current-doc-view"] [
    div [id "title", onclick navigateToTitleInput.handle (always ())]
      [text currentDoc.title],

    viewOutline currentDoc.chapters,

    span [id "add-chapter", class "flaticon-add139"] []
  ]

viewOutline : [Chapter] -> Html
viewOutline chapters =
  ul [id "outline"] <| indexedMap viewChapter chapters

viewChapter : Int -> Chapter -> Html
viewChapter index chapter = li [
    key ("chapter" ++ (show index)),
    title chapter.heading,
    onclick navigateToChapterIdInput.handle (always chapter.id)
  ] [text chapter.heading]


module Char where

import Native.Char as Native

-- True for upper case letters.
isUpper : Char -> Bool
isUpper = Native.isUpper

-- True for lower case letters.
isLower : Char -> Bool
isLower = Native.isLower

-- True for ASCII digits (`0..9`).
isDigit : Char -> Bool
isDigit = Native.isDigit

-- True for ASCII octal digits (`0..7`).
isOctDigit : Char -> Bool
isOctDigit = Native.isOctDigit

-- True for ASCII hexadecimal digits (`0..9a..fA..F`).
isHexDigit : Char -> Bool
isHexDigit = Native.isHexDigit

-- Convert to upper case.
toUpper : Char -> Char
toUpper = Native.toUpper

-- Convert to lower case.
toLower : Char -> Char
toLower = Native.toLower

-- Convert to upper case, according to any locale-specific case mappings.
toLocaleUpper : Char -> Char
toLocaleUpper = Native.toLocaleUpper

-- Convert to lower case, according to any locale-specific case mappings.
toLocaleLower : Char -> Char
toLocaleLower = Native.toLocaleLower

type KeyCode = Int

-- Convert to unicode.
toCode : Char -> Int
toCode = Native.toCode

-- Convert from unicode.
fromCode : Int -> Char
fromCode = Native.fromCode

Correct types (Int back to KeyCode)

module Char where

import Native.Char as Native

-- True for upper case letters.
isUpper : Char -> Bool
isUpper = Native.isUpper

-- True for lower case letters.
isLower : Char -> Bool
isLower = Native.isLower

-- True for ASCII digits (`0..9`).
isDigit : Char -> Bool
isDigit = Native.isDigit

-- True for ASCII octal digits (`0..7`).
isOctDigit : Char -> Bool
isOctDigit = Native.isOctDigit

-- True for ASCII hexadecimal digits (`0..9a..fA..F`).
isHexDigit : Char -> Bool
isHexDigit = Native.isHexDigit

-- Convert to upper case.
toUpper : Char -> Char
toUpper = Native.toUpper

-- Convert to lower case.
toLower : Char -> Char
toLower = Native.toLower

-- Convert to upper case, according to any locale-specific case mappings.
toLocaleUpper : Char -> Char
toLocaleUpper = Native.toLocaleUpper

-- Convert to lower case, according to any locale-specific case mappings.
toLocaleLower : Char -> Char
toLocaleLower = Native.toLocaleLower

type KeyCode = Int

-- Convert to unicode.
toCode : Char -> KeyCode
toCode = Native.toCode

-- Convert from unicode.
fromCode : KeyCode -> Char
fromCode = Native.fromCode


import Website.Skeleton (skeleton)
import Window

port title : String
port title = "Using Signals"

main = skeleton "Learn" (content << min 600) <~ Window.dimensions

content w = width w [markdown|

# Using Signals

Signals are values that change over time. You can learn more about the basics
of signals in [this post][frp] and in [the examples](/Examples.elm). This post
focuses on common design patterns that you will definitely see when programming
with signals in Elm.

[frp]: /learn/What-is-FRP.elm

To be continued!

|]

Write up "The Typical Pattern"

import Website.Skeleton (skeleton)
import Window

port title : String
port title = "Using Signals"

main = skeleton "Learn" (content << min 600) <~ Window.dimensions

content w = width w [markdown|

# Using Signals

Signals are values that change over time. You can learn more about the basics
of signals in [this post][frp] and in [the examples](/Examples.elm). This post
focuses on common design patterns that you will definitely see when programming
with signals in Elm.

[frp]: /learn/What-is-FRP.elm

## The Typical Pattern

When writing Elm code, it is usually best to use signals as little as possible.
They help you handle inputs from the world and manage state, but when it comes
to writing nice modular code, you should primarily use normal functions and
values.

Okay, but what about the part that *does* use signals?

The state of your application will live primarily in a single [`foldp`][foldp].
This `foldp` will take in some signal of “inputs” that indicate
how your application state should be updated.

[foldp]: http://library.elm-lang.org/catalog/elm-lang-Elm/latest/Signal#foldp

Say those inputs include `Mouse.clicks` and time deltas. We need to put these
signals together in a way that will update our `foldp` correctly. It may seem
tempting to write something like this:

```haskell
inputs : Signal ((), Float)
inputs =
    lift2 (,) Mouse.clicks (fps 40)
```

The `inputs` signal will now update whenever `Mouse.clicks` or `(fps 40)`
update. That means we cannot know who triggered the update. Should I react to a
click or a time delta?!

Instead you want to model the kinds of updates that can be done and
[`merge`][merge] them all together.

[merge]: http://library.elm-lang.org/catalog/elm-lang-Elm/latest/Signal#merge

```haskell
type Update = Click | TimeDelta Float

inputs : Signal Update
inputs =
    merge
        (lift (always Click) Mouse.clicks)
        (lift TimeDelta (fps 40))
```

When writing large applications, use the techniques described
[here](/learn/Architecture.elm) to make this basic approach modular as your
codebase grows.

|]


module IdeaFight.Compete exposing (Model, Msg, init, update, subscriptions, view)

import IdeaFight.Shuffle as Shuffle

import Html.App as App
import Html exposing (Html, text)

import Random
import String

type alias Model = List String
type Msg = ShuffledContents (List String)

init : String -> (Model, Cmd Msg)
init contents =
  let lines = String.lines contents
  in ([], Random.generate ShuffledContents <| Shuffle.shuffle lines)

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    ShuffledContents contents -> (contents, Cmd.none)

subscriptions : Model -> Sub Msg
subscriptions _ = Sub.none

view : Model -> Html Msg
view model = text <| toString model

main : Program Never
main = App.program {
    init = init "one\ntwo\nthree\nfour\nfive\nsix\nseven\neight",
    update = update,
    subscriptions = subscriptions,
    view = view
  }

Introduce numTop model member for compete subapp

module IdeaFight.Compete exposing (Model, Msg, init, update, subscriptions, view)

import IdeaFight.Shuffle as Shuffle

import Html.App as App
import Html exposing (Html, text)

import Random
import String

type alias Model = (List String, Int)
type Msg = ShuffledContents (List String)

init : String -> (Model, Cmd Msg)
init contents =
  let lines = String.lines contents
  in (([], 3), Random.generate ShuffledContents <| Shuffle.shuffle lines)

update : Msg -> Model -> (Model, Cmd Msg)
update msg (_, numTop) =
  case msg of
    ShuffledContents contents -> ((contents, numTop), Cmd.none)

subscriptions : Model -> Sub Msg
subscriptions _ = Sub.none

view : Model -> Html Msg
view model = text <| toString model

main : Program Never
main = App.program {
    init = init "one\ntwo\nthree\nfour\nfive\nsix\nseven\neight",
    update = update,
    subscriptions = subscriptions,
    view = view
  }


module Test.Reporter.Console.Format.Color exposing (formatEquality)

import Test.Reporter.Highlightable as Highlightable exposing (Highlightable(..))
import Test.Runner.Node.Vendor.Console as Console

formatEquality : List (Highlightable String) -> List (Highlightable String) -> ( String, String )
formatEquality highlightedExpected highlightedActual =
    let
        formattedExpected =
            highlightedExpected
                |> List.map fromHighlightable
                |> String.join ""

        formattedActual =
            highlightedActual
                |> List.map fromHighlightable
                |> String.join ""
    in
    ( formattedExpected, formattedActual )

fromHighlightable : Highlightable String -> String
fromHighlightable =
    Highlightable.resolve
        -- Cyan seems to look readable with both white and black text on top,
        -- so it should work with both dark and light console themes
        { fromHighlighted = Console.bgCyan
        , fromPlain = identity
        }

Use inverted colors over cyan for accessible diffs

module Test.Reporter.Console.Format.Color exposing (formatEquality)

import Test.Reporter.Highlightable as Highlightable exposing (Highlightable(..))
import Test.Runner.Node.Vendor.Console as Console

formatEquality : List (Highlightable String) -> List (Highlightable String) -> ( String, String )
formatEquality highlightedExpected highlightedActual =
    let
        formattedExpected =
            highlightedExpected
                |> List.map fromHighlightable
                |> String.join ""

        formattedActual =
            highlightedActual
                |> List.map fromHighlightable
                |> String.join ""
    in
    ( formattedExpected, formattedActual )

fromHighlightable : Highlightable String -> String
fromHighlightable =
    Highlightable.resolve
        -- Cyan seems to look readable with both white and black text on top,
        -- so it should work with both dark and light console themes
        { fromHighlighted = Console.colorsInverted
        , fromPlain = identity
        }


{- This Source Code Form is subject to the terms of the Mozilla Public License,
   v. 2.0. If a copy of the MPL was not distributed with this file, you can
   obtain one at http://mozilla.org/MPL/2.0/.

   Copyright 2016 by Ian Mackenzie
   ian.e.mackenzie@gmail.com
-}

module Main exposing (..)

import ElmTest exposing (..)
import Tests.Vector2d
import Tests.Vector3d
import Tests.Direction2d
import Tests.Direction3d
import Tests.Point2d
import Tests.Point3d

testSuites =
    [ Tests.Vector2d.suite
    , Tests.Vector3d.suite
    , Tests.Direction2d.suite
    , Tests.Direction3d.suite
    , Tests.Point2d.suite
    , Tests.Point3d.suite
    ]

main =
    runSuiteHtml (suite "OpenSolid Core Tests" testSuites)

Make test code a bit more explicit

{- This Source Code Form is subject to the terms of the Mozilla Public License,
   v. 2.0. If a copy of the MPL was not distributed with this file, you can
   obtain one at http://mozilla.org/MPL/2.0/.

   Copyright 2016 by Ian Mackenzie
   ian.e.mackenzie@gmail.com
-}

module Main exposing (..)

import ElmTest
import Tests.Vector2d
import Tests.Vector3d
import Tests.Direction2d
import Tests.Direction3d
import Tests.Point2d
import Tests.Point3d

testSuites =
    [ Tests.Vector2d.suite
    , Tests.Vector3d.suite
    , Tests.Direction2d.suite
    , Tests.Direction3d.suite
    , Tests.Point2d.suite
    , Tests.Point3d.suite
    ]

main =
    ElmTest.runSuiteHtml (ElmTest.suite "OpenSolid Core Tests" testSuites)


module App.Update exposing (update)

import App.Messages exposing (..)
import App.Model exposing (..)
import Components.Update
import Detail.Update
import Nav.Requests exposing (getSystemStatus, getDetails)
import Nav.Model exposing (..)

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        UpdateUrl page ->
            updatePage page model

        GetSystemStatus ->
            ( model, getSystemStatus model.flags.url )

        SystemStatus (Err _) ->
            ( model, Cmd.none )

        SystemStatus (Ok components) ->
            ( { model | components = components }, Cmd.none )

        ComponentsMsg componentsMsg ->
            let
                componentsModel =
                    Components.Update.update componentsMsg model.components
            in
                ( { model | components = componentsModel }, Cmd.none )

        DetailMsg detailMsg ->
            let
                ( detailModel, cmd ) =
                    Detail.Update.update detailMsg model.detail

                mappedCmd =
                    Cmd.map DetailMsg cmd
            in
                ( { model | detail = detailModel }, mappedCmd )

updatePage : Page -> Model -> ( Model, Cmd Msg )
updatePage page model =
    case page of
        Components as page ->
            ( { model | page = page }, getSystemStatus model.flags.url )

        (Component env system component server) as page ->
            let
                cmd =
                    Cmd.map DetailMsg <| getDetails model.flags.url env system component server
            in
                ( { model | page = page }, cmd )

Clear component details when navigating away from component

module App.Update exposing (update)

import App.Messages exposing (..)
import App.Model exposing (..)
import Components.Update
import Detail.Update
import Detail.Model
import Nav.Requests exposing (getSystemStatus, getDetails)
import Nav.Model exposing (..)

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        UpdateUrl page ->
            updatePage page model

        GetSystemStatus ->
            ( model, getSystemStatus model.flags.url )

        SystemStatus (Err _) ->
            ( model, Cmd.none )

        SystemStatus (Ok components) ->
            ( { model | components = components }, Cmd.none )

        ComponentsMsg componentsMsg ->
            let
                componentsModel =
                    Components.Update.update componentsMsg model.components
            in
                ( { model | components = componentsModel }, Cmd.none )

        DetailMsg detailMsg ->
            let
                ( detailModel, cmd ) =
                    Detail.Update.update detailMsg model.detail

                mappedCmd =
                    Cmd.map DetailMsg cmd
            in
                ( { model | detail = detailModel }, mappedCmd )

updatePage : Page -> Model -> ( Model, Cmd Msg )
updatePage page m =
    let
        model =
            leftPage m.page m
    in
        case page of
            Components as page ->
                ( { model | page = page }, getSystemStatus model.flags.url )

            (Component env system component server) as page ->
                let
                    cmd =
                        Cmd.map DetailMsg <| getDetails model.flags.url env system component server
                in
                    ( { model | page = page }, cmd )

leftPage : Page -> Model -> Model
leftPage oldPage model =
    case oldPage of
        Component _ _ _ _ ->
            { model | detail = Detail.Model.init }

        _ ->
            model


import Graphics.Element exposing (Element)
import ElmTest exposing (elementRunner, suite, test, assertEqual)
import Date

--
a = {name = "Alice"}
b = {name = "Bob", supervisor = a}
c = {a | birthday = Date.fromString "1998-12-31"}

main : Element
main =
  elementRunner <| suite "Exploring records"
    [ test "one" <| .name a `assertEqual` "Alice"
    , test "two" <| .supervisor b `assertEqual` a
    ]

Complete the intro record example in Elm

import ElmTest exposing (elementRunner, suite, defaultTest, assertEqual)
import List exposing (map)

boss = {name = "Alice", salary = 200000 }
worker = {name = "Bob", salary = 50000, supervisor = boss}
newWorker = {worker | name = "Carol" }

payrollTax : {a | salary : Float} -> Float
payrollTax {salary} =
  salary * 0.15

main =
  elementRunner <| suite "Exploring records" <| map defaultTest
    [ "Alice"  `assertEqual` .name boss
    , boss `assertEqual` worker.supervisor
    , 7500.0 `assertEqual` payrollTax worker
    , boss `assertEqual` newWorker.supervisor
    ]


module OpenSolid.Direction2d
  ( Direction2d(Direction2d)
  , none
  , polar
  , xDirection
  , yDirection
  , xComponent
  , yComponent
  , components
  , normalDirection
  ) where

type Direction2d =
  Direction2d Float Float

none: Direction2d
none =
  Direction2d 0 0

polar: Float -> Direction2d
polar angle =
  Direction2d (cos angle) (sin angle)

xDirection: Direction2d
xDirection =
  Direction2d 1 0

yDirection: Direction2d
yDirection =
  Direction2d 0 1

xComponent: Direction2d -> Float
xComponent (Direction2d x y) =
  x

yComponent: Direction2d -> Float
yComponent (Direction2d x y) =
  y

components: Direction2d -> (Float, Float)
components (Direction2d x y) =
  (x, y)

normalDirection: Direction2d -> Direction2d
normalDirection (Direction2d x y) =
  Direction2d (-y) x

Rearrange to put constants first

module OpenSolid.Direction2d
  ( Direction2d(Direction2d)
  , none
  , xDirection
  , yDirection
  , polar
  , xComponent
  , yComponent
  , components
  , normalDirection
  ) where

type Direction2d =
  Direction2d Float Float

none: Direction2d
none =
  Direction2d 0 0

xDirection: Direction2d
xDirection =
  Direction2d 1 0

yDirection: Direction2d
yDirection =
  Direction2d 0 1

polar: Float -> Direction2d
polar angle =
  Direction2d (cos angle) (sin angle)

xComponent: Direction2d -> Float
xComponent (Direction2d x y) =
  x

yComponent: Direction2d -> Float
yComponent (Direction2d x y) =
  y

components: Direction2d -> (Float, Float)
components (Direction2d x y) =
  (x, y)

normalDirection: Direction2d -> Direction2d
normalDirection (Direction2d x y) =
  Direction2d (-y) x


module App.Update exposing (update)

import App.Messages exposing (..)
import App.Model exposing (..)
import Components.Update
import Detail.Update
import Nav.Requests exposing (getSystemStatus, getDetails)
import Nav.Model exposing (..)

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        UpdateUrl (Components as page) ->
            ( { model | page = page }, getSystemStatus model.flags.url )

        UpdateUrl ((Component env system component server) as page) ->
            let
                cmd =
                    Cmd.map DetailMsg <| getDetails model.flags.url env system component server
            in
                ( { model | page = page }, cmd )

        GetSystemStatus ->
            ( model, getSystemStatus model.flags.url )

        SystemStatus (Err _) ->
            ( model, Cmd.none )

        SystemStatus (Ok components) ->
            ( { model | components = components }, Cmd.none )

        ComponentsMsg componentsMsg ->
            let
                componentsModel =
                    Components.Update.update componentsMsg model.components
            in
                ( { model | components = componentsModel }, Cmd.none )

        DetailMsg detailMsg ->
            let
                ( detailModel, cmd ) =
                    Detail.Update.update detailMsg model.detail

                mappedCmd =
                    Cmd.map DetailMsg cmd
            in
                ( { model | detail = detailModel }, mappedCmd )

Move page update logic into separate function

module App.Update exposing (update)

import App.Messages exposing (..)
import App.Model exposing (..)
import Components.Update
import Detail.Update
import Nav.Requests exposing (getSystemStatus, getDetails)
import Nav.Model exposing (..)

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        UpdateUrl page ->
            updatePage page model

        GetSystemStatus ->
            ( model, getSystemStatus model.flags.url )

        SystemStatus (Err _) ->
            ( model, Cmd.none )

        SystemStatus (Ok components) ->
            ( { model | components = components }, Cmd.none )

        ComponentsMsg componentsMsg ->
            let
                componentsModel =
                    Components.Update.update componentsMsg model.components
            in
                ( { model | components = componentsModel }, Cmd.none )

        DetailMsg detailMsg ->
            let
                ( detailModel, cmd ) =
                    Detail.Update.update detailMsg model.detail

                mappedCmd =
                    Cmd.map DetailMsg cmd
            in
                ( { model | detail = detailModel }, mappedCmd )

updatePage : Page -> Model -> ( Model, Cmd Msg )
updatePage page model =
    case page of
        Components as page ->
            ( { model | page = page }, getSystemStatus model.flags.url )

        (Component env system component server) as page ->
            let
                cmd =
                    Cmd.map DetailMsg <| getDetails model.flags.url env system component server
            in
                ( { model | page = page }, cmd )


module Dreamwriter.Model where

import Dreamwriter (Identifier)

data LeftSidebarView = CurrentDocView | OpenMenuView

type MsSinceEpoch = Int
type HtmlString   = String

-- TODO make this a proper ADT once outbound ports can accept them
type FullscreenState = Bool

type AppState =
  { leftSidebarView : LeftSidebarView
  , docs         : [Doc]
  , currentDoc   : Maybe Doc
  , currentDocId : Maybe Identifier
  , currentNote  : Maybe Note
  , notes        : [Note]
  , fullscreen   : FullscreenState
  }

emptyState : AppState
emptyState =
  { leftSidebarView = CurrentDocView
  , docs         = []
  , currentDoc   = Nothing
  , currentDocId = Nothing
  , currentNote  = Nothing
  , notes        = []
  , fullscreen   = False
  }

type Note =
  { id               : Identifier
  , title            : String
  , creationTime     : MsSinceEpoch
  , lastModifiedTime : MsSinceEpoch
  }

type Doc =
  { id               : Identifier
  , title            : String
  , description      : HtmlString
  , chapters         : [Chapter]
  , words            : Int
  , creationTime     : MsSinceEpoch
  , lastModifiedTime : MsSinceEpoch
  }

type Chapter =
  { id               : Identifier
  , heading          : String
  , words            : Int
  , creationTime     : MsSinceEpoch
  , lastModifiedTime : MsSinceEpoch
  }

Add a Dict of snapshots to AppState.

module Dreamwriter.Model where

import Dreamwriter (Identifier)
import Dict

data LeftSidebarView = CurrentDocView | OpenMenuView

type MsSinceEpoch = Int
type HtmlString   = String

-- TODO make this a proper ADT once outbound ports can accept them
type FullscreenState = Bool

type AppState =
  { leftSidebarView : LeftSidebarView
  , docs         : [Doc]
  , currentDoc   : Maybe Doc
  , currentDocId : Maybe Identifier
  , currentNote  : Maybe Note
  , notes        : [Note]
  , fullscreen   : FullscreenState
  , snapshots    : Dict.Dict Identifier Snapshot
  }

emptyState : AppState
emptyState =
  { leftSidebarView = CurrentDocView
  , docs         = []
  , currentDoc   = Nothing
  , currentDocId = Nothing
  , currentNote  = Nothing
  , notes        = []
  , fullscreen   = False
  , snapshots    = Dict.empty
  }

type Note =
  { id               : Identifier
  , title            : String
  , creationTime     : MsSinceEpoch
  , lastModifiedTime : MsSinceEpoch
  }

type Doc =
  { id               : Identifier
  , title            : String
  , description      : HtmlString
  , chapters         : [Chapter]
  , words            : Int
  , creationTime     : MsSinceEpoch
  , lastModifiedTime : MsSinceEpoch
  }

type Chapter =
  { id               : Identifier
  , heading          : String
  , words            : Int
  , creationTime     : MsSinceEpoch
  , lastModifiedTime : MsSinceEpoch
  , snapshotId       : Identifier
  }

type Snapshot =
  { id               : Identifier
  , html             : String
  }


module Main exposing (main)

import Html exposing (..)
import Html.Attributes exposing (..)
import ChartCard
import Samples

main : Program Never Model Msg
main =
    Html.beginnerProgram
        { model = model
        , view = view
        , update = update
        }

-- MODEL

type alias Model =
    List ChartCard.Model

model : Model
model =
    [ ChartCard.init Samples.allOfMe
    , ChartCard.init Samples.allOfMe
    ]

-- MSG

type Msg
    = ChartCard Int ChartCard.Msg

-- UPDATE

update : Msg -> Model -> Model
update msg model =
    case msg of
        ChartCard msgIndex nestedMsg ->
            List.indexedMap
                (\index item ->
                    if index == msgIndex then
                        ChartCard.update nestedMsg item
                    else
                        item
                )
                model

-- VIEW

view : Model -> Html Msg
view model =
    div []
        [ h1 []
            [ text "Music chart viewer/editor" ]
        , p []
            [ text "Source code on "
            , a [ href "https://github.com/openchordcharts/chart-editor" ]
                [ text "GitHub" ]
            ]
        , section []
            (List.indexedMap
                (\index item -> Html.map (ChartCard index) (ChartCard.view item))
                model
            )
        ]

Rename ChartCard to ChartCardMsg to explicit it's a Msg

module Main exposing (main)

import Html exposing (..)
import Html.Attributes exposing (..)
import ChartCard
import Samples

main : Program Never Model Msg
main =
    Html.beginnerProgram
        { model = model
        , view = view
        , update = update
        }

-- MODEL

type alias Model =
    List ChartCard.Model

model : Model
model =
    [ ChartCard.init Samples.allOfMe
    , ChartCard.init Samples.allOfMe
    ]

-- MSG

type Msg
    = ChartCardMsg Int ChartCard.Msg

-- UPDATE

update : Msg -> Model -> Model
update msg model =
    case msg of
        ChartCardMsg msgIndex nestedMsg ->
            List.indexedMap
                (\index item ->
                    if index == msgIndex then
                        ChartCard.update nestedMsg item
                    else
                        item
                )
                model

-- VIEW

view : Model -> Html Msg
view model =
    div []
        [ h1 []
            [ text "Music chart viewer/editor" ]
        , p []
            [ text "Source code on "
            , a [ href "https://github.com/openchordcharts/chart-editor" ]
                [ text "GitHub" ]
            ]
        , section []
            (List.indexedMap
                (\index chartModel -> Html.map (ChartCardMsg index) (ChartCard.view chartModel))
                model
            )
        ]


module Views.Retro.Contents exposing (view)

import Bitwise
import Bulma
import Char
import Data.Content exposing (Content)
import Html exposing (Html)
import Html.Attributes as Attr

view : List Content -> Html msg
view contents =
    contents
        |> List.map contentView
        |> List.intersperse (Html.hr [] [])
        |> Bulma.content []

contentView : Content -> Html msg
contentView content =
    Bulma.content []
        [ Html.p [ Attr.class "title is-6" ]
            [ Html.span
                [ Attr.class "indicator"
                , Attr.style [ ( "background-color", stringToColour content.author ) ]
                ]
                []
            , Html.text content.author
            ]
        , Html.p [] [ Html.text content.text ]
        ]

stringToColour : String -> String
stringToColour str =
    let
        hashChar char prev =
            Char.toCode char + (Bitwise.shiftLeftBy 5 prev - prev)

        hash =
            String.foldl hashChar 0 str

        part i =
            Bitwise.and (Bitwise.shiftRightBy (i * 8) hash) 0xFF
                |> toString
                |> String.padLeft 2 '0'
                |> (\x -> String.slice -2 (String.length x) x)
    in
    "#" ++ part 0 ++ part 1 ++ part 2

Add link to where code was lifted

module Views.Retro.Contents exposing (view)

import Bitwise
import Bulma
import Char
import Data.Content exposing (Content)
import Html exposing (Html)
import Html.Attributes as Attr

view : List Content -> Html msg
view contents =
    contents
        |> List.map contentView
        |> List.intersperse (Html.hr [] [])
        |> Bulma.content []

contentView : Content -> Html msg
contentView content =
    Bulma.content []
        [ Html.p [ Attr.class "title is-6" ]
            [ Html.span
                [ Attr.class "indicator"
                , Attr.style [ ( "background-color", stringToColour content.author ) ]
                ]
                []
            , Html.text content.author
            ]
        , Html.p [] [ Html.text content.text ]
        ]

{-| Translation of <https://stackoverflow.com/questions/3426404/create-a-hexadecimal-colour-based-on-a-string-with-javascript>
-}
stringToColour : String -> String
stringToColour str =
    let
        hashChar char prev =
            Char.toCode char + (Bitwise.shiftLeftBy 5 prev - prev)

        hash =
            String.foldl hashChar 0 str

        part i =
            Bitwise.and (Bitwise.shiftRightBy (i * 8) hash) 0xFF
                |> toString
                |> String.padLeft 2 '0'
                |> (\x -> String.slice -2 (String.length x) x)
    in
    "#" ++ part 0 ++ part 1 ++ part 2


module Main exposing (main)

import Html.App
import App.Model exposing (App)
import App.View
import App.Action exposing (Action(UpdateTrackList))
import Ports.Ports exposing (updateTrackList)

main : Program Never
main =
    Html.App.program
        { init = App.Model.initial
        , view = App.View.render
        , update = App.Model.update
        , subscriptions = subscriptions
        }

subscriptions : App -> Sub Action
subscriptions trackList =
    updateTrackList UpdateTrackList

Use `Sub.batch` to process many ports if needed.

module Main exposing (main)

import Html.App
import App.Model exposing (App)
import App.View
import App.Action exposing (Action(UpdateTrackList))
import Ports.Ports exposing (updateTrackList)

main : Program Never
main =
    Html.App.program
        { init = App.Model.initial
        , view = App.View.render
        , update = App.Model.update
        , subscriptions = subscriptions
        }

subscriptions : App -> Sub Action
subscriptions _ =
    Sub.batch [ updateTrackList UpdateTrackList ]


import Html.App as App
import Html exposing (Html, br, div, text)

import IdeaFight.PartialForest as Forest
import IdeaFight.Shuffle as Shuffle

import Random
import Time

type alias Model = Forest.Forest Int
type Msg = ShuffleMe (List Int) | Tick

stepForest : Forest.Forest comparable -> Forest.Forest comparable
stepForest forest =
  let (a, b) = Forest.getNextPair forest
  in Forest.choose forest <| max a b

init : (Model, Cmd Msg)
init = (Forest.empty, Random.generate ShuffleMe (Shuffle.shuffle [1..8]))

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    ShuffleMe values -> (Forest.fromList values, Cmd.none)
    Tick -> (stepForest model, Cmd.none)

subscriptions : Model -> Sub Msg
subscriptions _ = Time.every (Time.second * 5) <| always Tick

view : Model -> Html Msg
view model = div [] [
    text <| toString <| Forest.topNCount model,
    br [] [],
    Forest.drawForest model
  ]

main : Program Never
main = App.program {
    init = init,
    update = update,
    subscriptions = subscriptions,
    view = view
  }

Rename Tick to Advance in forest test

import Html.App as App
import Html exposing (Html, br, div, text)

import IdeaFight.PartialForest as Forest
import IdeaFight.Shuffle as Shuffle

import Random
import Time

type alias Model = Forest.Forest Int
type Msg = ShuffleMe (List Int) | Advance

stepForest : Forest.Forest comparable -> Forest.Forest comparable
stepForest forest =
  let (a, b) = Forest.getNextPair forest
  in Forest.choose forest <| max a b

init : (Model, Cmd Msg)
init = (Forest.empty, Random.generate ShuffleMe (Shuffle.shuffle [1..8]))

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    ShuffleMe values -> (Forest.fromList values, Cmd.none)
    Advance -> (stepForest model, Cmd.none)

subscriptions : Model -> Sub Msg
subscriptions _ = Time.every (Time.second * 5) <| always Advance

view : Model -> Html Msg
view model = div [] [
    text <| toString <| Forest.topNCount model,
    br [] [],
    Forest.drawForest model
  ]

main : Program Never
main = App.program {
    init = init,
    update = update,
    subscriptions = subscriptions,
    view = view
  }


import Graphics.Input (Input, input)
import Graphics.Input.Field (Content, noContent, field, defaultStyle, Forward, Backward)
import String
import Window

main : Signal Element
main = display <~ Window.dimensions ~ content.signal

content : Input Content
content = input noContent

display : (Int,Int) -> Content -> Element
display (w,h) fieldContent =
    color lightOrange <| container w h middle <| flow down
    [ container 300 60 middle <| plainText "Type in either field to reverse text:"
    , myField id "Forward" fieldContent
    , myField reverse "Backward" (reverse fieldContent)
    ]

myField : (Content -> Content) -> String -> Content -> Element
myField handler placeHolder fieldContent =
    container 300 50 middle <|
    field defaultStyle content.handle handler placeHolder fieldContent

reverse : Content -> Content
reverse content =
    let len = String.length content.string in
    { string = String.reverse content.string
    , selection = { start = len - content.selection.end
                  , end = len - content.selection.start
                  , direction = case content.selection.direction of
                                  Forward -> Backward
                                  Backward -> Forward
                  }
    }

Make the reversal example more fun and informative

import Graphics.Input (Input, input)
import Graphics.Input.Field (Content, noContent, field, defaultStyle, Forward, Backward)
import String
import Window

main : Signal Element
main = display <~ Window.dimensions ~ content.signal

content : Input Content
content = input noContent

display : (Int,Int) -> Content -> Element
display (w,h) fieldContent =
    let txt = container 300 60 middle . width 300 . centered . toText in
    color lightOrange <| container w h middle <| flow down
    [ txt "Type in either field to reverse text:"
    , myField id "Forward" fieldContent
    , myField reverse "Backward" (reverse fieldContent)
    , txt "Lookup palindromes and emordnilaps to try to make sentences!"
    ]

myField : (Content -> Content) -> String -> Content -> Element
myField handler placeHolder fieldContent =
    container 300 50 middle <|
    field defaultStyle content.handle handler placeHolder fieldContent

reverse : Content -> Content
reverse content =
    let len = String.length content.string in
    { string = String.reverse content.string
    , selection = { start = len - content.selection.end
                  , end = len - content.selection.start
                  , direction = case content.selection.direction of
                                  Forward -> Backward
                                  Backward -> Forward
                  }
    }


module Ref exposing (resolveReference)

import Json.Schema.Definitions exposing (Schema(ObjectSchema, BooleanSchema), SubSchema, Schemata(Schemata))

resolveReference : Schema -> String -> Maybe Schema
resolveReference schema ref =
    schema
        |> whenObjectSchema
        |> Maybe.andThen
            (\os ->
                if ref == "#" then
                    Just schema
                else if ref |> String.startsWith "#/definitions/" then
                    os.definitions
                        |> Maybe.andThen (findDefinition ref)
                        --|> debugSubSchema "find def?"
                        |>
                            Maybe.andThen
                                (\def ->
                                    case def.ref of
                                        Just r ->
                                            resolveReference schema r

                                        Nothing ->
                                            Just <| ObjectSchema def
                                )
                else
                    Nothing
            )

findDefinition : String -> Schemata -> Maybe SubSchema
findDefinition ref (Schemata defs) =
    defs
        |> List.foldl
            (\( key, def ) res ->
                if res == Nothing && ("#/definitions/" ++ key) == ref then
                    whenObjectSchema def
                else
                    res
            )
            Nothing

whenObjectSchema : Schema -> Maybe SubSchema
whenObjectSchema schema =
    case schema of
        ObjectSchema os ->
            Just os

        BooleanSchema _ ->
            Nothing

Add ability to resolve boolean schema

module Ref exposing (resolveReference)

import Json.Schema.Definitions exposing (Schema(ObjectSchema, BooleanSchema), SubSchema, Schemata(Schemata))

resolveReference : Schema -> String -> Maybe Schema
resolveReference schema ref =
    schema
        |> whenObjectSchema
        |> Maybe.andThen
            (\os ->
                if ref == "#" then
                    Just schema
                else if ref |> String.startsWith "#/definitions/" then
                    os.definitions
                        |> Maybe.andThen (findDefinition ref)
                        |> Maybe.andThen
                            (\def ->
                                case def of
                                    ObjectSchema oss ->
                                        case oss.ref of
                                            Just r ->
                                                resolveReference def r

                                            Nothing ->
                                                Just def

                                    BooleanSchema _ ->
                                        Just def
                            )
                else
                    Nothing
            )

findDefinition : String -> Schemata -> Maybe Schema
findDefinition ref (Schemata defs) =
    defs
        |> List.foldl
            (\( key, def ) res ->
                if res == Nothing && ("#/definitions/" ++ key) == ref then
                    Just def
                else
                    res
            )
            Nothing

whenObjectSchema : Schema -> Maybe SubSchema
whenObjectSchema schema =
    case schema of
        ObjectSchema os ->
            Just os

        BooleanSchema _ ->
            Nothing


module Utils.HttpUtils exposing (..)

import HttpBuilder exposing (..)

httpErrorToString : HttpBuilder.Error String -> String
httpErrorToString error =
    case error of
        UnexpectedPayload str ->
            """ Internal Error!
          You can't do anything about this, contact someone who does tech stuff!
      """

        NetworkError ->
            """ Network Error! Make sure you have an internet connection and try again.
          If that does not work, contact someone who administrates your BNK installation!
      """

        Timeout ->
            """ Network Error! Make sure you have an internet connection and try again.
          If that does not work, contact someone who administrates your BNK installation!
      """

        BadResponse response ->
            if response.data == "UsernamePasswordWrong" then
                "Wrong username or password!"
            else
                toString response.data

Add userExists error to httpErrorToString

module Utils.HttpUtils exposing (..)

import HttpBuilder exposing (..)

httpErrorToString : HttpBuilder.Error String -> String
httpErrorToString error =
    case error of
        UnexpectedPayload str ->
            """ Internal Error!
          You can't do anything about this, contact someone who does tech stuff!
      """

        NetworkError ->
            """ Network Error! Make sure you have an internet connection and try again.
          If that does not work, contact someone who administrates your BNK installation!
      """

        Timeout ->
            """ Network Error! Make sure you have an internet connection and try again.
          If that does not work, contact someone who administrates your BNK installation!
      """

        BadResponse response ->
            case response.data of
                "UsernamePasswordWrong" ->
                    "Wrong username or password!"

                "UserExists" ->
                    "An account with this username already exists"

                _ ->
                    toString response.data
            else
                toString response.data


module Chain exposing (Model, init, update, subscriptions)

import Html exposing (Html)
import Piece exposing (Msg)
import AnimationFrame
import Time exposing (Time)
import Style

type alias Model =
    List Piece.Model

init : ( Model, Cmd Msg )
init =
    ( [], Cmd.none )

subscriptions : Model -> Sub Msg
subscriptions model =
    AnimationFrame.times Animate

type Msg
    = Show
    | Animate Time
    | Up
    | Right
    | Down
    | Left

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    let
        result =
            case msg of
                Up ->
                    model

                Right ->
                    model

                Down ->
                    model

                Left ->
                    model

                Show ->
                    model

                Animate time ->
                    model
    in
        ( result, Cmd.none )

Remove unneeded exposing of Piece.Msg

module Chain exposing (Model, init, update, subscriptions)

import Html exposing (Html)
import Piece
import AnimationFrame
import Time exposing (Time)
import Style

type alias Model =
    List Piece.Model

init : ( Model, Cmd Msg )
init =
    ( [], Cmd.none )

subscriptions : Model -> Sub Msg
subscriptions model =
    AnimationFrame.times Animate

type Msg
    = Show
    | Animate Time
    | Up
    | Right
    | Down
    | Left

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    let
        result =
            case msg of
                Up ->
                    model

                Right ->
                    model

                Down ->
                    model

                Left ->
                    model

                Show ->
                    model

                Animate time ->
                    model
    in
        ( result, Cmd.none )


module Data.Attribution
    exposing
        ( Attribution
        , toHtml
        )

import Html exposing (Html, li, a, text)
import Html.Attributes exposing (href)

type alias Attribution =
    { name : String
    , author : String
    , link : String
    }

toHtml : Attribution -> Html msg
toHtml attribution =
    li []
        [ a [ href attribution.link ]
            [ text attribution.name
            , text " by "
            , text attribution.author
            ]
        ]

Add nofollow to icon links

module Data.Attribution
    exposing
        ( Attribution
        , toHtml
        )

import Html exposing (Html, li, a, text)
import Html.Attributes exposing (href, rel)

type alias Attribution =
    { name : String
    , author : String
    , link : String
    }

toHtml : Attribution -> Html msg
toHtml attribution =
    li []
        [ a [ rel "nofollow", href attribution.link ]
            [ text attribution.name
            , text " by "
            , text attribution.author
            ]
        ]


import Time exposing (Time,second)
import Html exposing (Html,text)
import Set exposing (Set)
import Random

-- Model
type alias Coordinate = (Int, Int)

type alias Model =
    { alive : Set Coordinate
    , width : Int
    , height : Int}

init : (Model, Cmd Msg)
init =
  let
      width = 10
      widthCoordinateGenerator = Random.int 0 <| width - 1
      height = 10
      heightCoordinateGenerator = Random.int 0 <| height - 1
      locationGenerator = Random.pair widthCoordinateGenerator heightCoordinateGenerator
      listGenerator = Random.list (width * height // 2) locationGenerator
  in
    ({alive = Set.empty
    , width = width
    , height = height}, Random.generate Genesis listGenerator)

-- Messages
type Msg
    = Tick Time
    | Genesis (List(Coordinate))

-- View
view : Model -> Html Msg
view matrix = text "banana"

-- Update
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
    case msg of
        Tick _ -> (model, Cmd.none)
        Genesis points ->
          ( { model | alive = Set.fromList points }
          , Cmd.none)

-- Subscriptions
subscriptions : Model -> Sub Msg
subscriptions model =
    Time.every second Tick

-- Main
main : Program Never Model Msg
main =
    Html.program
        { init = init
        , view = view
        , update = update
        , subscriptions = subscriptions
        }

Change view to a temporary representation

import Time exposing (Time,second)
import Html exposing (Html,text)
import Set exposing (Set)
import Random

-- Model
type alias Coordinate = (Int, Int)

type alias Model =
    { alive : Set Coordinate
    , width : Int
    , height : Int}

init : (Model, Cmd Msg)
init =
  let
      width = 10
      widthCoordinateGenerator = Random.int 0 <| width - 1
      height = 10
      heightCoordinateGenerator = Random.int 0 <| height - 1
      locationGenerator = Random.pair widthCoordinateGenerator heightCoordinateGenerator
      listGenerator = Random.list (width * height // 2) locationGenerator
  in
    ({alive = Set.empty
    , width = width
    , height = height}, Random.generate Genesis listGenerator)

-- Messages
type Msg
    = Tick Time
    | Genesis (List(Coordinate))

-- View
view : Model -> Html Msg
view model = text <| toString model

-- Update
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
    case msg of
        Tick _ -> (model, Cmd.none)
        Genesis points ->
          ( { model | alive = Set.fromList points }
          , Cmd.none)

-- Subscriptions
subscriptions : Model -> Sub Msg
subscriptions model =
    Time.every second Tick

-- Main
main : Program Never Model Msg
main =
    Html.program
        { init = init
        , view = view
        , update = update
        , subscriptions = subscriptions
        }


module State exposing (..)

import Types exposing (..)
import Spotify

init : ( Model, Cmd Msg )
init =
    ( { query = Nothing
      , albums = []
      }
    , Cmd.none
    )

search : String -> Cmd Msg
search q =
    if String.length q >= 3 then
        Spotify.albumSearch q
    else
        Cmd.none

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        NoOp ->
            model ! []

        Search q ->
            ( { model | query = Just q }
            , search q
            )

        SearchResult (Ok albums) ->
            ( { model | albums = albums }
            , Cmd.none
            )

        SearchResult _ ->
            model ! []

Reset results when search is cleared

module State exposing (..)

import Types exposing (..)
import Spotify

init : ( Model, Cmd Msg )
init =
    ( { query = Nothing
      , albums = []
      }
    , Cmd.none
    )

search : String -> Cmd Msg
search q =
    if String.length q >= 3 then
        Spotify.albumSearch q
    else
        Cmd.none

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        NoOp ->
            model ! []

        Search q ->
            ( { model
                | query = Just q
                , albums = []
              }
            , search q
            )

        SearchResult (Ok albums) ->
            ( { model | albums = albums }
            , Cmd.none
            )

        SearchResult _ ->
            model ! []


module App.View exposing (..)

import Html exposing (..)
import Html.Attributes exposing (..)

import App.Types exposing (..)
import App.Input.View as Input
import App.Entries.View as Entries
import App.Control.View as Control

view : Model -> Html Msg
view model =
    div []
        [ Input.view model.input
        , Entries.view model.entries
        , Control.view model.control
        ]

Add view functions for header and footer

module App.View exposing (..)

import Html exposing (..)
import Html.Attributes exposing (..)

import App.Types exposing (..)
import App.Input.View as Input
import App.Entries.View as Entries
import App.Control.View as Control

view : Model -> Html Msg
view model =
    div []
        [ title
        , Input.view model.input
        , Entries.view model.entries
        , Control.view model.control
        , infoFooter
        ]

title : Html Msg
title =
    header []
        [ h1 []
            [ a [ href "https://github.com/jackrzhang/lister-elm" ]
                [ text "lister"]
            ]
        ]

infoFooter : Html Msg
infoFooter =
    footer [ id "info" ]
        [ p []
            [ text "Written by "
            , a [ href "https://github.com/jackrzhang" ] [ text "Jack Zhang" ]
            ]
        , p []
            [ text "Built with "
            , a [ href "http://elm-lang.org" ] [ text "Elm" ]
            ]
        ]


{- This Source Code Form is subject to the terms of the Mozilla Public License,
   v. 2.0. If a copy of the MPL was not distributed with this file, you can
   obtain one at http://mozilla.org/MPL/2.0/.

   Copyright 2016 by Ian Mackenzie
   ian.e.mackenzie@gmail.com
-}

module Main exposing (..)

import ElmTest exposing (..)
import Tests.Vector2d
import Tests.Vector3d
import Tests.Point2d
import Tests.Point3d

main =
    let
        tests =
            suite "OpenSolid Core Tests"
                [ Tests.Vector2d.suite
                , Tests.Vector3d.suite
                , Tests.Point2d.suite
                , Tests.Point3d.suite
                ]
    in
        runSuiteHtml tests

Add direction tests to main suite

{- This Source Code Form is subject to the terms of the Mozilla Public License,
   v. 2.0. If a copy of the MPL was not distributed with this file, you can
   obtain one at http://mozilla.org/MPL/2.0/.

   Copyright 2016 by Ian Mackenzie
   ian.e.mackenzie@gmail.com
-}

module Main exposing (..)

import ElmTest exposing (..)
import Tests.Vector2d
import Tests.Vector3d
import Tests.Direction2d
import Tests.Direction3d
import Tests.Point2d
import Tests.Point3d

testSuites =
    [ Tests.Vector2d.suite
    , Tests.Vector3d.suite
    , Tests.Direction2d.suite
    , Tests.Direction3d.suite
    , Tests.Point2d.suite
    , Tests.Point3d.suite
    ]

main =
    runSuiteHtml (suite "OpenSolid Core Tests" testSuites)


module SublistExample where
import List exposing (..)
import String

sublist : List a -> List a -> String
sublist alist blist =
  if alist == blist then "Equal" else
    if alist == [] then "Sublist" else
      if blist == [] then  "Superlist" else
        if inList alist blist then "Superlist" else
          if inList blist alist then "Sublist" else "Unequal"

inList : List a -> List a -> Bool
inList alist blist =
  let getLastInList sublist =
    case (List.tail sublist) of
      Just list -> list
      Nothing -> []

  in
    if (List.length alist) < (List.length blist) then False else
      if (List.take (List.length blist) alist) == blist then True else
        inList (getLastInList alist) blist

Remove unnecessary code from Sublist example

module SublistExample where
import List exposing (..)
import String

sublist : List a -> List a -> String
sublist alist blist =
  if alist == blist then "Equal" else
    if inList alist blist then "Superlist" else
      if inList blist alist then "Sublist" else "Unequal"

inList : List a -> List a -> Bool
inList alist blist =
  let getLastInList sublist =
    case (List.tail sublist) of
      Just list -> list
      Nothing -> []

  in
    if (List.length alist) < (List.length blist) then False else
      if (List.take (List.length blist) alist) == blist then True else
        inList (getLastInList alist) blist


module Music.Chord exposing (..)

import Music.Note as Note exposing (Note, Interval)

-- TYPES

type Chord
    = Chord Note Quality

type Quality
    = Major
    | Minor
    | Sixth
    | Seventh
    | MinorSeventh
    | HalfDiminished

qualities : List Quality
qualities =
    [ Major, Minor, Sixth, Seventh, MinorSeventh, HalfDiminished ]

-- FUNCTIONS

transpose : Interval -> Chord -> Chord
transpose interval (Chord note quality) =
    Chord (Note.transpose interval note) quality

toString : Chord -> String
toString (Chord note quality) =
    let
        qualityToString : Quality -> String
        qualityToString quality =
            case quality of
                Major ->
                    ""

                Minor ->
                    "m"

                Sixth ->
                    "6"

                Seventh ->
                    "7"

                MinorSeventh ->
                    "m7"

                    "m7b5"
                HalfDiminished ->
    in
        Note.toString note ++ qualityToString quality

Change representation of half-diminished chords

module Music.Chord exposing (..)

import Music.Note as Note exposing (Note, Interval)

-- TYPES

type Chord
    = Chord Note Quality

type Quality
    = Major
    | Minor
    | Sixth
    | Seventh
    | MinorSeventh
    | HalfDiminished

qualities : List Quality
qualities =
    [ Major, Minor, Sixth, Seventh, MinorSeventh, HalfDiminished ]

-- FUNCTIONS

transpose : Interval -> Chord -> Chord
transpose interval (Chord note quality) =
    Chord (Note.transpose interval note) quality

toString : Chord -> String
toString (Chord note quality) =
    let
        qualityToString : Quality -> String
        qualityToString quality =
            case quality of
                Major ->
                    ""

                Minor ->
                    "m"

                Sixth ->
                    "6"

                Seventh ->
                    "7"

                MinorSeventh ->
                    "m7"

                HalfDiminished ->
                    "ø"
    in
        Note.toString note ++ qualityToString quality


module Players.Edit exposing (..)

import Html exposing (..)
import Html.Attributes exposing (class, href, value)
import Models exposing (Player)
import Msgs exposing (Msg)

view : Player -> Html Msg
view player =
    div []
        [ nav player
        , form player
        ]

nav : Player -> Html Msg
nav _ =
    div [ class "clearfix mb2 white bg-black p1" ]
        []

form : Player -> Html Msg
form player =
    div [ class "m3" ]
        [ h1 [] [ text player.name ]
        , formLevel player
        ]

formLevel : Player -> Html Msg
formLevel player =
    div [ class "clearfix py1" ]
        [ div [ class "col col-5" ] [ text "Level" ]
        , div [ class "col col-7" ]
            [ span [ class "h2 bold" ] [ text (toString player.level) ]
            , btnLevelDecrease player
            , btnLevelIncrease player
            ]
        ]

btnLevelDecrease : Player -> Html Msg
btnLevelDecrease player =
    a [ class "btn ml1 h1" ]
        [ i [ class "fa fa-minus-circle" ] [] ]

btnLevelIncrease : Player -> Html Msg
btnLevelIncrease player =
    a [ class "btn ml1 h1" ]
        [ i [ class "fa fa-plus-circle" ] [] ]

Embed link for top page

module Players.Edit exposing (..)

import Html exposing (..)
import Html.Attributes exposing (class, href, value)
import Models exposing (Player)
import Msgs exposing (Msg)
import Routing exposing (playersPath)

view : Player -> Html Msg
view player =
    div []
        [ nav player
        , form player
        ]

nav : Player -> Html Msg
nav _ =
    div [ class "clearfix mb2 white bg-black p1" ]
        [ listBtn ]

form : Player -> Html Msg
form player =
    div [ class "m3" ]
        [ h1 [] [ text player.name ]
        , formLevel player
        ]

formLevel : Player -> Html Msg
formLevel player =
    div [ class "clearfix py1" ]
        [ div [ class "col col-5" ] [ text "Level" ]
        , div [ class "col col-7" ]
            [ span [ class "h2 bold" ] [ text (toString player.level) ]
            , btnLevelDecrease player
            , btnLevelIncrease player
            ]
        ]

btnLevelDecrease : Player -> Html Msg
btnLevelDecrease player =
    a [ class "btn ml1 h1" ]
        [ i [ class "fa fa-minus-circle" ] [] ]

btnLevelIncrease : Player -> Html Msg
btnLevelIncrease player =
    a [ class "btn ml1 h1" ]
        [ i [ class "fa fa-plus-circle" ] [] ]

listBtn : Html Msg
listBtn =
    a [ class "btn regular", href playersPath ]
        [ i [ class "fa fa-chevron-left mr1" ] []
        , text "List"
        ]


module Caldwell.Constants exposing (..)

-- Libraries
import Css exposing (hex, Color, Rem)

-- Source

import Caldwell.Types exposing (Page(..))

-- Paddings / Margins

gutterSize : Rem
gutterSize =
    Css.rem 1

titleHeight : Rem
titleHeight =
    Css.rem 3

-- Colors

white : Color
white =
    hex "#FFFFFF"

lightGrey : Color
lightGrey =
    hex "#AAAAAA"

grey : Color
grey =
    hex "#777777"

darkGrey : Color
darkGrey =
    hex "#333333"

black : Color
black =
    hex "#000000"

pageList : List Page
pageList =
    [ Home
    , Music
    , Shows
    , About
    , Contact
    ]

intOfPages : Int
intOfPages = List.length pageList

floatOfPages : Float
floatOfPages = toFloat intOfPages

-- Cross FileType Names
-- (EG: HTML / CSS selectors with same names.)

caldwellBackground : String
caldwellBackground =
    "caldwell-background"

caldwellCalendar : String
caldwellCalendar =
    "caldwell-calendar"

blackOverlay : String
blackOverlay =
    "black-overlay"

container : String
container =
    "container"

Fix header font size so my head doesn't get chopped on mobile.

module Caldwell.Constants exposing (..)

-- Libraries
import Css exposing (hex, Color, Rem)

-- Source

import Caldwell.Types exposing (Page(..))

-- Paddings / Margins

gutterSize : Rem
gutterSize =
    Css.rem 1

titleHeight : Rem
titleHeight =
    Css.rem 2.7

-- Colors

white : Color
white =
    hex "#FFFFFF"

lightGrey : Color
lightGrey =
    hex "#AAAAAA"

grey : Color
grey =
    hex "#777777"

darkGrey : Color
darkGrey =
    hex "#333333"

black : Color
black =
    hex "#000000"

pageList : List Page
pageList =
    [ Home
    , Music
    , Shows
    , About
    , Contact
    ]

intOfPages : Int
intOfPages = List.length pageList

floatOfPages : Float
floatOfPages = toFloat intOfPages

-- Cross FileType Names
-- (EG: HTML / CSS selectors with same names.)

caldwellBackground : String
caldwellBackground =
    "caldwell-background"

caldwellCalendar : String
caldwellCalendar =
    "caldwell-calendar"

blackOverlay : String
blackOverlay =
    "black-overlay"

container : String
container =
    "container"


module Main exposing (main)

import Html exposing (..)

main =
    view initialModel

type State
    = Open
    | Closed

initialModel : { state : State, values : List String }
initialModel =
    { state = Open
    , values = fruits
    }

fruits : List String
fruits =
    [ "bananas"
    , "apples"
    , "oranges"
    , "peaches"
    , "strawberries"
    ]

view : { state : State, values : List String } -> Html a
view model =
    case model.state of
        Open ->
            viewOpen model

        Closed ->
            viewClosed model

viewOpen : { state : State, values : List String } -> Html a
viewOpen model =
    div []
        [ p [] [ text "Click to Open" ]
        , ul [] (List.map dropdownItem model.values)
        ]

viewClosed : Html a
viewClosed =
    div []
        [ p [] [ text "Click to Close" ]
        ]

dropdownItem : String -> Html a
dropdownItem value =
    li [] [ text value ]

Add a `Model` type alias

module Main exposing (main)

import Html exposing (..)

main =
    view initialModel

type State
    = Open
    | Closed

type alias Model =
    { state : State, values : List String }

initialModel : Model
initialModel =
    { state = Open
    , values = fruits
    }

fruits : List String
fruits =
    [ "bananas"
    , "apples"
    , "oranges"
    , "peaches"
    , "strawberries"
    ]

view : Model -> Html a
view model =
    case model.state of
        Open ->
            viewOpen model

        Closed ->
            viewClosed

viewOpen : Model -> Html a
viewOpen model =
    div []
        [ p [] [ text "Click to Open" ]
        , ul [] (List.map dropdownItem model.values)
        ]

viewClosed : Html a
viewClosed =
    div []
        [ p [] [ text "Click to Close" ]
        ]

dropdownItem : String -> Html a
dropdownItem value =
    li [] [ text value ]


module Models (..) where

import Meals.Models exposing (Meal)
import Routing

type alias AppModel =
  { meals : List Meal
  , routing : Routing.Model
  }

initialModel : AppModel
initialModel =
  { meals = [ Meal 1 "Sufuruoka" [] ]
  , routing = Routing.initialModel
  }

Add some ingredients to initial model

module Models (..) where

import Meals.Models exposing (Meal, MealIngredient)
import Ingredients.Models exposing (Ingredient)
import Routing

type alias AppModel =
  { meals : List Meal
  , routing : Routing.Model
  }

initialModel : AppModel
initialModel =
  { meals =
      [ Meal
          1
          "Sufuruoka"
          [ MealIngredient (Ingredient 1 "Mako") 5
          , MealIngredient (Ingredient 2 "Hajo") 2
          ]
      ]
  , routing = Routing.initialModel
  }


module Views.BreakProgress exposing (view)

import Break
import Element exposing (Device)
import Element.Attributes as Attr
import Element.Events
import Setup.Msg as Msg
import Setup.Settings as Settings
import Styles exposing (StyleElement)

circleView : Styles.CircleFill -> StyleElement
circleView circleFill =
    Element.el (Styles.Circle circleFill) [ Attr.width (Attr.px 12), Attr.height (Attr.px 18) ] Element.empty

view : { model | intervalsSinceBreak : Int, settings : Settings.Data } -> Styles.StyleElement
view { intervalsSinceBreak, settings } =
    let
        remainingIntervals =
            Break.timersBeforeNext intervalsSinceBreak settings.intervalsPerBreak

        intervalBadges =
            List.range 1 settings.intervalsPerBreak
                |> List.map (\index -> index > intervalsSinceBreak)
                |> List.map
                    (\incompleteInterval ->
                        if incompleteInterval then
                            circleView Styles.Hollow
                        else
                            circleView Styles.Filled
                    )
    in
    Element.row
        Styles.None
        [ Attr.spacing 0
        , Element.Events.onClick Msg.ResetBreakData
        ]
        intervalBadges

Make remaining break interval indicators responsive.

module Views.BreakProgress exposing (view)

import Break
import Element exposing (Device)
import Element.Attributes as Attr
import Element.Events
import Setup.Msg as Msg
import Setup.Settings as Settings
import Styles exposing (StyleElement)

circleView : { model | device : Device } -> Styles.CircleFill -> StyleElement
circleView { device } circleFill =
    let
        width =
            Styles.responsiveForWidth device ( 6, 20 ) |> Attr.px

        height =
            Styles.responsiveForWidth device ( 10, 25 ) |> Attr.px
    in
    Element.el (Styles.Circle circleFill) [ Attr.width width, Attr.height height ] Element.empty

view : { model | intervalsSinceBreak : Int, settings : Settings.Data, device : Device } -> Styles.StyleElement
view ({ intervalsSinceBreak, settings } as model) =
    let
        remainingIntervals =
            Break.timersBeforeNext intervalsSinceBreak settings.intervalsPerBreak

        intervalBadges =
            List.range 1 settings.intervalsPerBreak
                |> List.map (\index -> index > intervalsSinceBreak)
                |> List.map
                    (\incompleteInterval ->
                        if incompleteInterval then
                            circleView model Styles.Hollow
                        else
                            circleView model Styles.Filled
                    )
    in
    Element.row
        Styles.None
        [ Attr.spacing 0
        , Element.Events.onClick Msg.ResetBreakData
        ]
        intervalBadges


module Rails (send) where

{-|

# Http
@docs send

-}

import Http exposing (Value(..))
import Task exposing (Task)
import Json.Decode exposing (Decoder)

-- Http

{-| Utility for working with rails. Wraps Http.send passing an Authenticity Token
along with the type of request and a way to decode results.

-}
send : String -> Decoder value -> String -> String -> Http.Body -> Task Http.Error value
send authToken decoder verb url body =
    let
        requestSettings =
            { verb = verb
            , headers = ["X-CSRF-Token" => authToken
                        , "Content-Type" => "application/json"
                        , "Accept" => "application/json, text/javascript, */*; q=0.01"
                        , "X-Requested-With" => "XMLHttpRequest"
                        ]
            , url = url
            , body = body
            }

        emptyBodyToNull response =
            -- Translate an empty body into "null" for JSON parsing
            if response.value == Text "" then
                { response | value <- Text "null" }
            else
                response
    in
        Http.send Http.defaultSettings requestSettings
            |> Task.map emptyBodyToNull
            |> Http.fromJson decoder

(=>) = (,)

Revert "Translate empty body to null."

module Rails (send) where

{-|

# Http
@docs send

-}

import Http
import Task exposing (Task)
import Json.Decode exposing (Decoder)

-- Http

{-| Utility for working with rails. Wraps Http.send passing an Authenticity Token
along with the type of request and a way to decode results.

-}
send : String -> Decoder value -> String -> String -> Http.Body -> Task Http.Error value
send authToken decoder verb url body =
    let
        requestSettings =
            { verb = verb
            , headers = ["X-CSRF-Token" => authToken
                        , "Content-Type" => "application/json"
                        , "Accept" => "application/json, text/javascript, */*; q=0.01"
                        , "X-Requested-With" => "XMLHttpRequest"
                        ]
            , url = url
            , body = body
            }

    in
        Http.send Http.defaultSettings requestSettings
            |> Http.fromJson decoder

(=>) = (,)


import Color (..)
import Graphics.Element (..)
import Graphics.Input (dropDown)
import Signal
import Text

main : Signal Element
main =
  Signal.map display (Signal.subscribe style)

style : Signal.Channel (Text.Text -> Text.Text)
style =
  Signal.channel identity

display : (Text.Text -> Text.Text) -> Element
display transform =
  let msg = Text.fromString "Choose a style for the following text: "
  in
      flow down
        [ Text.leftAligned (msg ++ transform (Text.fromString "Hello, World!"))
        , dropDown options
        ]

options : List (String, Signal.Message)
options =
    [ option "plain"      identity
    , option "underline"  (Text.line Text.Under)
    , option "italic"     Text.italic
    , option "bold"       Text.bold
    , option "red"        (Text.color red)
    , option "monospace"  Text.monospace
    , option "Georgia"    (Text.typeface ["georgia", "palatino", "serif"])
    ]

option : String -> (Text.Text -> Text.Text) -> (String, Signal.Message)
option name transform =
  (name, Signal.send style transform)

Update for latest Input.dropDown API

import Color (..)
import Graphics.Element (..)
import Graphics.Input (dropDown)
import Signal
import Text

main : Signal Element
main =
  Signal.map display (Signal.subscribe style)

style : Signal.Channel (Text.Text -> Text.Text)
style =
  Signal.channel identity

display : (Text.Text -> Text.Text) -> Element
display transform =
  let msg = Text.fromString "Choose a style for the following text: "
  in
      flow down
        [ Text.leftAligned (msg ++ transform (Text.fromString "Hello, World!"))
        , dropDown (Signal.send style) options
        ]

options : List (String, Text.Text -> Text.Text)
options =
    [ "plain"     := identity
    , "underline" := Text.line Text.Under
    , "italic"    := Text.italic
    , "bold"      := Text.bold
    , "red"       := Text.color red
    , "monospace" := Text.monospace
    , "Georgia"   := Text.typeface ["georgia", "palatino", "serif"]
    ]

(:=) name transform =
    (name, transform)


port module BasicWorker exposing (..)

import Html.App
import Html

main : Program Never
main =
    Html.App.program
        { init = ( "", report "it's alive!" )
        , view = \_ -> Html.text ""
        , update = \_ _ -> ( "", Cmd.none )
        , subscriptions = (\_ -> Sub.none)
        }

port report : String -> Cmd a

Replace Html.App.program not available in 0.18 to Platform.program

port module BasicWorker exposing (..)

import Html
import Platform

main : Program Never String msg
main =
    Platform.program
        { init = ( "", report "it's alive!" )
        , update = \_ _ -> ( "", Cmd.none )
        , subscriptions = (\_ -> Sub.none)
        }

port report : String -> Cmd a


module AllSyntax.Declarations (..) where

expressionDefinition _ _ =
  ()

expressionDefinitionNoPatterns =
  ()

expressionDefinitionsInLet =
  let
    def1 =
      ()

    def2 =
      ()
  in
    ()

expressionTypeAnnotation : ()
expressionTypeAnnotation =
  ()

Add tests for type declarations

module AllSyntax.Declarations (..) where

type DataType
  = Ctor1
  | Ctor2 ()
  | Ctor3 (List ()) ()

type DataTypeWithParams a b c
  = Ctor1'
  | Ctor2' a
  | Ctor3' b c

type alias TypeAlias =
  { x : Int, y : Int }

expressionDefinition _ _ =
  ()

expressionDefinitionNoPatterns =
  ()

expressionDefinitionsInLet =
  let
    def1 =
      ()

    def2 =
      ()
  in
    ()

expressionTypeAnnotation : ()
expressionTypeAnnotation =
  ()


module Game.Account.Requests exposing (Response(..), receive)

import Game.Account.Requests.ServerIndex as ServerIndex
import Game.Account.Messages exposing (..)

type Response
    = ServerIndexResponse ServerIndex.Response

receive : RequestMsg -> Response
receive response =
    case response of
        ServerIndexRequest ( code, data ) ->
            data
                |> ServerIndex.receive code
                |> ServerIndexResponse

        LogoutRequest _ ->
            Debug.crash "Logout has no response"

Fix random crash at logout (server randomly replies logout topic).

module Game.Account.Requests exposing (Response(..), receive)

import Game.Account.Requests.ServerIndex as ServerIndex
import Game.Account.Messages exposing (..)

type Response
    = ServerIndexResponse ServerIndex.Response
    | NoOpResponse

receive : RequestMsg -> Response
receive response =
    case response of
        ServerIndexRequest ( code, data ) ->
            data
                |> ServerIndex.receive code
                |> ServerIndexResponse

        LogoutRequest _ ->
            NoOpResponse