Commits: 9

Use tad-lispy/springs

I've published it 😎

index a5f4ae6..f19e8dc 100644
--- a/elm.json
+++ b/elm.json
@@ -25,6 +25,7 @@
=            "ianmackenzie/elm-geometry-svg": "1.0.2",
=            "mdgriffith/elm-markup": "2.0.6",
=            "mdgriffith/elm-ui": "1.1.0",
+            "tad-lispy/springs": "1.0.4",
=            "turboMaCk/any-dict": "1.0.1"
=        },
=        "indirect": {
index a8f1e95..18f4a42 100644
--- a/src/Examples/CartesianCoordinates.elm
+++ b/src/Examples/CartesianCoordinates.elm
@@ -69,8 +69,8 @@ type alias Flags =
=
=init : Flags -> ( Model, Cmd Msg )
=init () =
-    ( { x = Spring.create 20 20
-      , y = Spring.create 20 20
+    ( { x = Spring.create { strength = 20, dampness = 5 }
+      , y = Spring.create { strength = 20, dampness = 5 }
=      }
=    , Cmd.none
=    )
index eb30eb9..0ffec3a 100644
--- a/src/Main.elm
+++ b/src/Main.elm
@@ -138,7 +138,7 @@ init flags url key =
=      , key = key
=      , content = content
=      , examples = examplesModel
-      , scroll = Spring.create 20 20
+      , scroll = Spring.create { strength = 20, dampness = 4 }
=      , viewport =
=            { width = 800, height = 600 }
=      }
deleted file mode 100644
index 0b7bdc3..0000000
--- a/src/Spring.elm
+++ /dev/null
@@ -1,248 +0,0 @@
-module Spring exposing
-    ( Spring
-    , animate
-    , atRest
-    , create
-    , jumpTo
-    , setTarget
-    , target
-    , value
-    )
-
-{-| A rough model of a mass attached to a spring, as described by [Hooke's law](https://en.wikipedia.org/wiki/Hooke's_law). Good for making smooth and organic looking animations or modeling oscilating values (e.g. emotions). High physical accuracy is not a priority - performance and API is more important.
--}
-
-
-{-| A model of mass attached to a spring. The spring is anchored to a target. The mass is constant (1).
-
-Value represents the current position of the mass. It is re-calculated (together with velocity) by animate function.
-
-Strength regulates how strongly the spring pulls toward target. It is also called the stiffness but I find the former term more intuitive.
-
-Dampness is how resistant the spring is to change in it's stretch (both stretching out and contracting in). If dumpness is low relative to strength, then the animation will end in long period of vibration around the target value - in other words lowering dumpness will increase wobbliness. Setting dumpness to 0 will result in something like a sine wave oscilator (but it's not advise to depend on it's accuracy).
-
-Target is the value toward which the mass is pulled. Typically the spring will start in an equilibrium position (i.e. value == target) and later on (due to an event) the target will be changed and the value will follow according to the strength and dampness of the spring.
-
-Value is where the mass is. It can be extracted from the spring using `value` function and set (with `setValue` function - rarely useful).
-
-Velocity is an internal property that cannot be directly modified or read.
-
-Let's say we are creating a program that animates the position of an element toward last click position.
-
-    type alias Model =
-        { x : Spring
-        , y : Spring
-        }
-
--}
-type Spring
-    = Spring
-        { strength : Float
-        , dampness : Float
-        , target : Float
-        , value : Float
-        , velocity : Float
-        }
-
-
-{-| Create a spring in an equilibrium state.
-
-Let's say we are creating a program that animates the position of an element toward last click position.
-
-    type alias Model =
-        { x : Spring
-        , y : Spring
-        }
-
-    init : Flags -> ( Model, Cmd msg )
-    init flags =
-        ( { x = Spring.create 20 20
-          , y = Spring.create 20 20
-          }
-        , Cmd.none
-        )
-
--}
-create : Float -> Float -> Spring
-create strength dampness =
-    Spring
-        { strength = strength
-        , dampness = dampness
-        , target = 0
-        , value = 0
-        , velocity = 0
-        }
-
-
-{-| Set a new target (relaxed value) for the spring.
-
-The current value and it's velocity will remain the same. Typically you would set a target in response to an event, e.g.:
-
-    update : Msg -> Model -> ( Model, Cmd Msg )
-    update msg model =
-        case msg of
-            Click x y ->
-                ( { model
-                    | x = Spring.setTarget x model.x
-                    , y = Spring.setTarget y model.y
-                  }
-                , Cmd.none
-                )
-
--}
-setTarget : Float -> Spring -> Spring
-setTarget target_ (Spring spring) =
-    Spring
-        { spring
-            | target =
-                target_
-        }
-
-
-{-| Update the spring
-
-Typically you would do it in response to an animation frame message, like this:
-
-    subscriptions : Model -> Sub Msg
-    subscriptions model =
-        Browser.Events.onAnimationFrameDelta Animate
-
-    update : Msg -> Model -> ( Model, Cmd Msg )
-    update msg model =
-        case msg of
-            Animate delta ->
-                ( { model
-                    | x = Spring.animate delta model.x
-                    , y = Spring.animate delta model.y
-                  }
-                , Cmd.none
-                )
-
--}
-animate : Float -> Spring -> Spring
-animate delta ((Spring spring) as this) =
-    if atRest this then
-        {- If it's in equilibrium, then let's just skip the whole calculation. Be lazy. -}
-        Spring spring
-
-    else
-        let
-            time =
-                {- Low sampling rates often result in nasty errors.
-
-                   With this cap on delta, if the frame rate is lower than 30fps the animation will slow down and good sampling rate will be preserved.
-                -}
-                min delta 32 / 1000
-
-            stretch =
-                spring.target - spring.value
-
-            force =
-                stretch * spring.strength
-
-            dampening =
-                spring.velocity * spring.dampness
-
-            acceleration =
-                time * (force - dampening)
-        in
-        if
-            (abs (spring.value - spring.target) < 0.001)
-                && (abs spring.velocity < 0.001)
-        then
-            {- In reality the spring never stops vibrating, but at some point the vibration is lost in the background noise (uncertainity principle). In our case it's also a wasted computation. Let's just say that it is at rest already. -} {- Snap to ideal equilibrium -}
-            Spring
-                { spring
-                    | value = spring.target
-                    , velocity = 0
-                }
-
-        else
-            Spring
-                { spring
-                    | value =
-                        spring.value + (spring.velocity * time)
-                    , velocity =
-                        spring.velocity + acceleration
-                }
-
-
-{-| Measure the value of the spring.
-
-Typically you want to access it in the view function, like this:
-
-    Element.el
-        [ Element.width (Element.px 20)
-        , Element.height (Element.px 20)
-        , Font.size 30
-        , model.x
-            |> Spring.value
-            |> Element.moveRight
-        , model.y
-            |> Spring.value
-            |> Element.moveDown
-        ]
-        (Element.text "\u{1F991}")
-
-Above we use Elm UI Elements and Attributes, but it's not difficult to implement same behavior using CSS transformations. Spring value is just a `Float`.
-
--}
-value : Spring -> Float
-value (Spring spring) =
-    spring.value
-
-
-{-| Get current target of a spring
-
-Can be useful to see where the spring is going. Maybe you want to display something there?
-
--}
-target : Spring -> Float
-target (Spring spring) =
-    spring.target
-
-
-{-| Check if the spring is at rest
-
-It indicates that no animation is running. Maybe you want to unsubscribe from animation frames? Or remove an element?
-
-    subscriptions : Model -> Sub Msg
-    subscriptions model =
-        if Spring.atRest model.x && Spring.atRest model.y then
-            Sub.none
-
-        else
-            Browser.Events.onAnimationFrameDelta Animate
-
--}
-atRest : Spring -> Bool
-atRest (Spring spring) =
-    spring.value == spring.target && spring.velocity == 0.0
-
-
-{-| Forcefully set the value and interrupt the animation.
-
-It is useful when you set the spring for the first time (e.g. in init function) or you want to reset the animation.
-
-    init : Flags -> ( Model, Cmd msg )
-    init flags =
-        ( { x =
-                Spring.create 20 20
-                    |> Spring.setTarget 200
-                    |> Spring.jumpTo 200
-          , y =
-                Spring.create 20 20
-                    |> Spring.setTarget 200
-                    |> Spring.jumpTo 200
-          }
-        , Cmd.none
-        )
-
--}
-jumpTo : Float -> Spring -> Spring
-jumpTo value_ (Spring spring) =
-    Spring
-        { spring
-            | value = value_
-            , velocity = 0.0
-        }

Remove Examples/Spring

It lives at https://tad-lispy.gitlab.io/elm-springs/Squid.html now

deleted file mode 100644
index 690d5fb..0000000
--- a/src/Examples/Spring.elm
+++ /dev/null
@@ -1,139 +0,0 @@
-module Examples.Spring exposing
-    ( Model
-    , Msg
-    , init
-    , main
-    , subscriptions
-    , ui
-    , update
-    )
-
-import Browser
-import Browser.Events
-import Element exposing (Element)
-import Element.Background as Background
-import Element.Events as Events
-import Element.Font as Font
-import Element.Input as Input
-import Examples.Tree
-import FeatherIcons
-import Html exposing (Html)
-import Html.Events
-import Json.Decode as Decode exposing (Decoder)
-import Spring exposing (Spring)
-
-
-main : Program Flags Model Msg
-main =
-    Browser.element
-        { init = init
-        , view = view
-        , update = update
-        , subscriptions = subscriptions
-        }
-
-
-type alias Model =
-    { x : Spring
-    , y : Spring
-    }
-
-
-type alias Flags =
-    ()
-
-
-init : Flags -> ( Model, Cmd msg )
-init flags =
-    let
-        strength =
-            20
-
-        dampness =
-            20
-    in
-    ( { x =
-            Spring.create strength dampness
-                |> Spring.setTarget 200
-      , y =
-            Spring.create strength dampness
-                |> Spring.setTarget 200
-      }
-    , Cmd.none
-    )
-
-
-ui : Model -> Element Msg
-ui model =
-    Element.el
-        [ Element.width (Element.px 20)
-        , Element.height (Element.px 20)
-        , Font.size 30
-
-        -- , Background.color (Element.rgb 1 0 0)
-        , model.x
-            |> Spring.value
-            |> Element.moveRight
-        , model.y
-            |> Spring.value
-            |> Element.moveDown
-        ]
-        (Element.text "\u{1F991}")
-
-
-type Msg
-    = Animate Float
-    | Mouse Float Float
-
-
-view : Model -> Html Msg
-view model =
-    model
-        |> ui
-        |> Element.layout
-            [ Element.width Element.fill
-            , Element.height Element.fill
-            , mouseDecoder
-                |> Html.Events.on "click"
-                |> Element.htmlAttribute
-            ]
-
-
-update : Msg -> Model -> ( Model, Cmd Msg )
-update msg model =
-    case msg of
-        Animate delta ->
-            ( { model
-                | x = Spring.animate delta model.x
-                , y = Spring.animate delta model.y
-              }
-            , Cmd.none
-            )
-
-        Mouse x y ->
-            ( { model
-                | x = Spring.setTarget x model.x
-                , y = Spring.setTarget y model.y
-              }
-            , Cmd.none
-            )
-
-
-mouseDecoder : Decoder Msg
-mouseDecoder =
-    Decode.map2 Mouse
-        (Decode.field "clientX" Decode.float)
-        (Decode.field "clientY" Decode.float)
-        |> Decode.map (Debug.log "Msg")
-
-
-subscriptions : Model -> Sub Msg
-subscriptions model =
-    [ if Spring.atRest model.x && Spring.atRest model.y then
-        Sub.none
-
-      else
-        Browser.Events.onAnimationFrameDelta Animate
-    , Browser.Events.onMouseMove mouseDecoder
-    ]
-        |> Sub.batch

Add a text on test-run.

Informing students who can't register to reach out to us.

index 9a06486..39ca6b4 100644
--- a/content/test-run.txt
+++ b/content/test-run.txt
@@ -10,6 +10,8 @@ In collaboration with {Link|Career Services|url=https://students.uu.nl/en/career
=    07 March 2019: /Marinus Langeveld Room G230/  Time *16:00* - *19:00*
=    08 March 2019: /Marinus Ruppert Room 121/  Time *16:00* - *19:00*
=
+The workshop slots are almost filled. If you can't register and would like to attend in the future please, reach out to us. We will try to arrange another workshop with Utrecht University.
+
=| Emphasize
=    {Link|Sign up now|url=https://fd21.formdesk.com/universiteitutrecht/CS-20190304-08-SoftwareGarden}
=

Merge branch 'reg-wait-list' into 'master'

Add a text on test-run.

See merge request software-garden/software-garden.gitlab.io!36

Merge branch 'springs' into 'master'

Use tad-lispy/strings for better performance

See merge request software-garden/software-garden.gitlab.io!35

Create flash cards for day 1

For now we can use markdown-preview-enhanced plugin for Atom to view them. Install the plugin, open the preview with:

Cmd-Shift-P > Markdown Preview Enhanced: Toggle

Then right click on the preview and chose:

Open in Browser

In the future we may implement something to build them automatically (based on Mume: https://github.com/shd101wyy/mume).

new file mode 100644
index 0000000..78a2ed5
--- /dev/null
+++ b/flash-cards.md
@@ -0,0 +1,235 @@
+---
+presentation:
+  enableSpeakerNotes: true
+  theme: solarized.css
+  height: 150%
+---
+
+<!-- slide -->
+
+# After day 1
+
+<!-- slide vertical -->
+
+On day one we have created a program that ...
+
+
+1. ... calculates the phase of the moon
+1. ... displays a dot in the middle of the screen <!-- .element: class="fragment grow"  -->
+1. ... makes the screen pink
+
+
+<!-- slide vertical -->
+
+Consider the following code:
+
+```elm
+Svg.svg
+    [ Svg.Attributes.viewBox "-100 -100 200 200" ]
+    [ Svg.circle
+        [ Svg.Attributes.cx "300"
+        , Svg.Attributes.cy "100"
+        , Svg.Attributes.r "10"
+        ]
+        []
+    ]
+```
+
+Where will the dot be?
+
+
+1. Visible on the screen
+1. To the left of the screen (invisible)
+1. To the right of the screen (invisible) <!-- .element: class="fragment grow"  -->
+
+
+<!-- slide vertical -->
+
+What does it mean to format the code?
+
+
+1. To make it work when previously it was broken.
+1. To make it look good.  <!-- .element: class="fragment grow"  -->
+1. To write it from scratch.
+1. To take code created by somebody else and adapt it to our needs.
+
+
+<!-- slide vertical -->
+
+A way of describing a position of a point on flat a surface is called:
+
+1. the origin
+1. geography
+1. SVG
+1. cartesian coordinates system <!-- .element: class="fragment grow"  -->
+1. X - Y system
+
+
+
+
+
+<!-- slide vertical -->
+
+In SVG, the greater the value of the y coordinate ...
+
+1. ... the lower the point is on the screen. <!-- .element: class="fragment grow"  -->
+1. ... the higher the point is on the screen.
+1. ... the bigger the point is.
+
+
+<!-- slide vertical -->
+
+The value of `Svg.Attributes.r` affects:
+
+1. rotation of a circle
+1. roundness of a circle
+1. size of a circle  <!-- .element: class="fragment grow"  -->
+
+
+<!-- slide vertical -->
+
+The value of `Svg.Attributes.viewBox` controls:
+
+1. How big the screen is.
+1. At what fragment of a surface we are looking.  <!-- .element: class="fragment grow"  -->
+1. How big the SVG element is.
+1. How big the viewport is.
+
+
+<!-- slide vertical -->
+
+What is the origin?
+
+1. The first copy of a program.
+1. A number representing the size of a dot.
+1. A point in cartesian coordinates system.  <!-- .element: class="fragment grow"  -->
+
+
+<!-- slide vertical -->
+
+If the viewbox is
+
+```elm
+{ left = -200
+, top = -200
+, width = 300
+, height = 200
+}
+```
+
+then the point at the centre is:
+
+1. `{ x = 0, y = 0 }`
+1. `{ x = -50, y = -100 }` <!-- .element: class="fragment grow"  -->
+1. `{ x = 150, y = 100 }`
+
+
+<!-- slide vertical -->
+
+To make sure that a given point is in the middle of the screen, we can:
+
+1. Move the viewport
+1. Move the viewbox <!-- .element: class="fragment grow"  -->
+1. Move the screen
+1. Move the point
+
+
+<!-- slide vertical -->
+
+```elm
+main =
+    Svg.svg
+        [ Svg.Attributes.viewBox "-100 -100 200 200" ]
+        [ Svg.rect
+            [ Svg.Attributes.x "-10"
+            , Svg.Attributes.y "-10"
+            , Svg.Attributes.width "20"
+            , Svg.Attributes.height "20"
+            ]
+            []
+        ]
+```
+
+Which output will this program produce?
+
+<div style="display: flex">
+  <svg viewbox="-100 -100 200 200" style=" background: white; border: solid 1px black; border-radius: 10px; margin: 30px;" class="fragment grow">
+    <rect x="-10" y="-10" width="20"  height="20">
+  </svg>
+
+  <svg viewbox="-100 -100 200 200" style=" background: white; border: solid 1px black; border-radius: 10px; margin: 30px;">
+    <circle r="10">
+  </svg>
+
+  <svg viewbox="-100 -100 200 200" style=" background: white; border: solid 1px black; border-radius: 10px; margin: 30px;">
+    <rect x="-15" y="-10" width="30"  height="20">
+  </svg>
+</div>
+
+
+<!-- slide vertical -->
+
+What is this code missing?
+
+```elm
+main =
+    Svg.svg
+        [ Svg.Attributes.viewBox "-100 -100 200 200"
+        [ Svg.rect
+            [ x "-10"
+            , y "-10"
+            , width "20"
+            , height "20"
+            ]
+            []
+        ]
+```
+
+1. A closing quotation mark
+1. A closing square bracket <!-- .element: class="fragment grow"  -->
+1. An equal sign
+
+
+<!-- slide vertical -->
+
+This fragment of code is broken:
+
+```elm
+Svg.svg
+    [ Svg.Attributes.viewBox "-100 -100 200 200" ]
+    [ Svg.circle [ Svg.Attributes.r: "10" ] [] ]
+```
+
+Which one is the correct version?
+
+```elm
+Svg.svg
+    [ Svg.Attributes.viewBox = "-100 -100 200 200" ]
+    [ Svg.circle [ Svg.Attributes.r = "10" ] [] ]
+```
+
+```elm
+Svg.svg
+    [ Svg.Attributes.viewBox: "-100 -100 200 200" ]
+    [ Svg.circle [ Svg.Attributes.r: "10" ] [] ]
+```
+
+```elm { .fragment .grow}
+Svg.svg
+    [ Svg.Attributes.viewBox "-100 -100 200 200" ]
+    [ Svg.circle [ Svg.Attributes.r "10" ] [] ]
+```
+
+<!-- slide vertical -->
+
+## You are the best πŸ‘‘
+
+
+<!-- slide -->
+
+# After day 2
+
+
+<!-- slide vertical -->
+
+> TODO: Flashcards for day 2

Merge branch 'flash-cards' into 'master'

Create flash cards for day 1

See merge request software-garden/software-garden.gitlab.io!37

Schedule a timeline for day 1

new file mode 100644
index 0000000..a15227e
--- /dev/null
+++ b/TIMELINE.md
@@ -0,0 +1,120 @@
+# Timeline for the workshop
+
+
+## Day 1
+
+### 00:00
+
+  - πŸ‘‹ πŸ‘‹πŸΎ Introduce ourselves
+
+  - Ask to write names on badges
+
+  - πŸ™‹ Who read the material?
+
+  - Organizational stuff:
+
+    5 minute break after 1h
+
+    20 minutes after 2h
+
+  - πŸ’¬ Any questions?
+
+
+### 00:05
+
+  - Introduce the problem (Ellie)
+
+  - Are there any questions?
+
+### 00:10
+
+  - πŸ’» Introduce SVG
+
+    Installation
+
+    Import
+
+    Make a dot with radius only
+
+    πŸ™‹β€ Is everyone having it working ‍
+
+### 00:15
+
+  - πŸ’¬ Where is the dot?
+
+  - πŸ’» SVG Element - let's make it pink
+
+  - πŸ™‹β€ Do you have it? Is it more or less clear?
+
+### 00:20
+
+  - πŸ’» Fill the viewport
+
+    Install Elm UI
+
+    Import
+
+    `svg |> html |> layout`
+
+  - πŸ™‹ Do you have it working?
+
+    It's a technicality, so let's not focus too much on that right now.
+
+### 00:30
+
+  - Break (5 minutes)
+
+### 00:40
+
+  - Cartesian coordinates system
+
+    πŸ™‹ Who knows what it is?
+
+    πŸ‘¨β€πŸ« Explain on the whiteboard ( ⇄ πŸ“ 2d ☩ )
+
+  - Change the code to move the dot ( `cx` `cy` )
+
+    πŸ•ž Take 3 minutes to play with it
+
+  - πŸ’¬ Questions?
+
+
+### 00:50
+
+  - Screen size πŸ’₯
+
+  - πŸ‘¨β€πŸ« ‍The infinite canvas and the viewbox into it
+
+    We know the position of a point and we can set the viewbox any way we like. How can we make it in the middle?
+
+  - πŸ’» Code
+
+  - πŸ’¬ Questions?
+
+### 01:10
+
+  - Color
+
+    πŸ’¬ What else is there about our dot?
+
+    πŸ’» `fill "skyblue"`
+
+    πŸ™‹β€ Who is done?
+
+    πŸ’¬ Questions
+
+### 01:20
+
+  - Break 20 minutes
+
+### 01:40
+
+  - πŸ’¬ How did you like it?
+
+    Is there anything we could do better?
+
+    New questions, ideas?
+
+    Stashed questions
+
+    See you tomorrow πŸ‘‹πŸΎ πŸ‘‹

Merge branch 'timeline' into 'master'

Schedule a timeline for day 1

See merge request software-garden/software-garden.gitlab.io!38