’m taking a first year computer science course (CompSci 1JC3) as one of my electives for my final year. We had to read a book selected from a list provided by the professor and do a book report presentation on it. It had to include an Elm animation. My group made our entire presentation in Elm using code provided by our professor. Each slide represents one chapter from the book we read, The Naked Future by Patrick Tucker.

You can see our Elm-made presentation here: http://www.taylorsilva.com/thenakedfuture.html

Elm code for the presentation is below, it’s pretty straightforward. Feel free to use it to make your own Elm presentations!

import Color exposing (..)
import Graphics.Collage exposing (..)
import Graphics.Element exposing (..)
import Time exposing (..)
import Keyboard
import Signal
import Text exposing (..)
import List exposing (map)
import Array exposing (Array)

-- a somewhat different pattern for putting signals together
-- this time we want to have either a time signal, or arrows
-- so we need to make a type to handle this, which can be either 
-- of these (and we could add more types of Signals

type Events = Arrows {x : Int, y:Int} 
           | TimeIncrease Float

events : Signal Events
events =
   -- Signal.merge takes two signals OF THE SAME TYPE and interleaves them
   -- mergeMany can merge a whole list of different signals
   Signal.merge
       -- wait!  how can we merge signals of different types, there is
       --        no point in merging signals of the same tyep
       -- That is why we may a type Events with two constructors!
       -- By mapping a constructor over the underlying signals
       -- we change the type of the signal to Signal.Events,
       -- and we can separate the two types of underlying events
       -- using a case expression.
       (Signal.map Arrows       Keyboard.arrows)
       (Signal.map TimeIncrease (fps 40))

main =
 Signal.map view <| Signal.foldp update (1,0) events -- was initially (0,1) but then it would show slide2 first instead of slide1...

-- the update has to handle both types of signals
update event (t,idx)
 = case event of
     -- if an arrow is pressed, move to another slide, and reset time
     Arrows arrows   -> (0     , moveIdx arrows idx)
     -- if time goes by, update the time in the state (for animations)
     TimeIncrease dt -> (t + 0.001 * dt, idx)

-- to avoid going past the first/last slides, check before changing 
-- the slide index
moveIdx arrows oldIdx = case arrows.x of
                        1  -> if oldIdx + 1 < Array.length slides 
                              then oldIdx + 1
                              else oldIdx
                        (-1) -> if oldIdx > 0
                              then oldIdx - 1
                              else oldIdx
                        otherwise -> oldIdx

-- even though we cannot go past the last slide,
-- we need to check that the slide lookup in the array of slides works
-- and display a blank collage if we are out of range
view (t,idx) = case Array.get idx slides of
                Just slide -> slide t
                Nothing    -> collage 700 700 []

-- the list of slides is stored in an array (because this is O(1) lookup)
slides = Array.fromList [slide1,slide2,slide3,slide4,slide5,slide6,slide7,slide8,slide9,slide10,slide11,slide12]

-- Chapter 1: 
slide1 t = slide12 t

-- Chapter 2: Human Optimization
slide2 t = collage 700 700 [group 
                  [(filled yellow (circle 20))
                   , text (Text.height 25 (Text.color black (Text.fromString "Calories consumed: 523cl"))) |> move(175+5*sin(t*3), 75+10*cos(t))
                   , text (Text.height 25 (Text.color black (Text.fromString "Steps taken: 908"))) |> move(175+5*sin(t*2), 175+10*cos(t))
                   , text (Text.height 25 (Text.color black (Text.fromString "Calories burned: 114cl"))) |> move(175+8*sin(t*3), 275+10*cos(t))
                   , text (Text.height 25 (Text.color black (Text.fromString "Tweets sent: 4"))) |> move(-175+10*sin(t*2), 75+8*cos(t))
                   , text (Text.height 25 (Text.color black (Text.fromString "Money spent: $17.34"))) |> move(-175+10*sin(t*2), 175+10*cos(t*2))
                   , text (Text.height 25 (Text.color black (Text.fromString "Location: McMaster University"))) |> move(-175+10*sin(t*2), 275+8*cos(t*2))
                   , move (0,-20) (filled yellow (rect 10 20))
                   , move (0,-60) (filled red (rect 40 60))
                   , move (-14,-38) (filled red (circle 10))
                   , move (14,-38) (filled red (circle 10))
                   , move (-20, -90) (filled blue <| polygon [(0,0), (0,-60), (15,-60), (15,-20), (25,-20), (25,-60), (40,-60), (40,0),(0,0)])
                   , move (-17,-150) (filled orange (oval 24 8))
                   , move (17,-150) (filled orange (oval 24 8))
                   , move (30, -50) (filled red (rect 10 40)) |> rotate (degrees 45)
                   , move (-30, -50) (filled red (rect 10 40)) |> rotate (degrees -45)
                   , move (-45, -65) (filled yellow (circle 8))
                   , move (45, -65) (filled yellow (circle 8))
                   , move (-10,0) (filled black (circle 1)) 
                   , move (10,0) (filled black (circle 1))
                   , move (0,-10) (filled black (oval 10 5))
                   , move (45,-65) (filled black (rect 10 20) |> rotate (degrees -45))
                   , move (45,-65) (filled blue (rect 5 15) |> rotate (degrees -45))
                    ]]

-- Chapter 3: Healthcare again... tracking diseases
slide3 t = collage 700 700 [
                             text (Text.height 45 (Text.color blue (Text.fromString "tweets: "))) |> move (-80,0)
                           , text (Text.height 30 (Text.color black (Text.fromString "Feeling sick :(("))) |> move (120, 30*sin(t))
                           , text (Text.height 20 (Text.color blue (Text.fromString "#sick"))) |> move (100,-30) |> move (0, 30*sin(t))
                           , text (Text.height 20 (Text.color black (Text.fromString "2 min ago"))) |> move (190,-50) |> move (0, 30*sin(t))
                           , text (Text.height 30 (Text.color black (Text.fromString "Have the flu"))) |> move (100, 100) |> move (0, 30*sin(t))
                           , text (Text.height 20 (Text.color blue (Text.fromString "#feelingbad"))) |> move (100,70) |> move (0, 30*sin(t))
                           , text (Text.height 20 (Text.color black (Text.fromString "10 min ago"))) |> move (190,50) |> move (0, 30*sin(t))
                           , text (Text.height 30 (Text.color black (Text.fromString "I'm sick guys"))) |> move (100, 200) |> move (0, 30*sin(t))
                           , text (Text.height 20 (Text.color blue (Text.fromString "#flu"))) |> move (100,170) |> move (0, 30*sin(t))
                           , text (Text.height 20 (Text.color black (Text.fromString "4 min ago"))) |> move (190,150) |> move (0, 30*sin(t))                           
                           , text (Text.height 30 (Text.color black (Text.fromString "Need more Advil"))) |> move (120, 300) |> move (0, 30*sin(t))
                           , text (Text.height 20 (Text.color blue (Text.fromString "#advilpls"))) |> move (100,270) |> move (0, 30*sin(t))
                           , text (Text.height 20 (Text.color black (Text.fromString "0 min ago"))) |> move (190,250) |> move (0, 30*sin(t))    
                           , text (Text.height 30 (Text.color black (Text.fromString "Guess who's sick"))) |> move (140, -100) |> move (0, 30*sin(t))
                           , text (Text.height 20 (Text.color blue (Text.fromString "#me"))) |> move (130,-130) |> move (0, 30*sin(t))
                           , text (Text.height 20 (Text.color black (Text.fromString "23 min ago"))) |> move (190,-150) |> move (0, 30*sin(t))                           
                           , text (Text.height 30 (Text.color black (Text.fromString "Really sick D:"))) |> move (120, -200) |> move (0, 30*sin(t))
                           , text (Text.height 20 (Text.color blue (Text.fromString "#sickk"))) |> move (130,-230) |> move (0, 30*sin(t))
                           , text (Text.height 20 (Text.color black (Text.fromString "3 min ago"))) |> move (190,-250) |> move (0, 30*sin(t))                            
                           ]

-- Chapter 4: Weather Forecast
slide4 t = collage 700 700 [sunAndClouds t]
sun = group [filled yellow (circle 100)
           , filled yellow (ngon 3 30) |> move(130, 0)
           , filled yellow (ngon 3 30) |> move(0, -130) |> rotate (degrees 30)
           , filled yellow (ngon 3 30) |> move(0, 130) |> rotate (degrees -30)
           , filled yellow (ngon 3 30) |> move(-130, 0) |> rotate (degrees 60)
           , filled yellow (ngon 3 30) |> move(100, -100) |> rotate (degrees 75)
           , filled yellow (ngon 3 30) |> move(100, 100) |> rotate (degrees 45)
           , filled yellow (ngon 3 30) |> move(-100, 100) |> rotate (degrees 15)
           , filled yellow (ngon 3 30) |> move(-100, -100) |> rotate (degrees -15)]
lBCloud = group [filled lightBlue (rect 300 120)
             , filled lightBlue (circle 50) |> move (150, -20)
             , filled lightBlue (circle 70) |> move (-130, -20)
             , filled lightBlue (circle 60) |> move (100, 25)
             , filled lightBlue (circle 80) |> move (0, 50)
             , filled lightBlue (circle 60) |> move (-100, 30)]
lightBlue = (hsl (degrees 190) 0.89 0.86)
bCloud = group [filled ablue (rect 300 120)
             , filled ablue (circle 50) |> move (150, -20)
             , filled ablue (circle 70) |> move (-130, -20)
             , filled ablue (circle 60) |> move (100, 25)
             , filled ablue (circle 80) |> move (0, 50)
             , filled ablue (circle 60) |> move (-100, 30)]
ablue = (hsl (degrees 197) 1 0.5)
greyCloud = group [filled grey (rect 300 120)
             , filled grey (circle 50) |> move (150, -20)
             , filled grey (circle 70) |> move (-130, -20)
             , filled grey (circle 60) |> move (100, 25)
             , filled grey (circle 80) |> move (0, 50)
             , filled grey (circle 60) |> move (-100, 30)]
grey = (hsl (degrees 205) 0.21 0.51)
noCloud = group [filled transparent (rect 300 120)
             , filled transparent (circle 50) |> move (150, -20)
             , filled transparent (circle 70) |> move (-130, -20)
             , filled transparent (circle 60) |> move (100, 25)
             , filled transparent (circle 80) |> move (0, 50)
             , filled transparent (circle 60) |> move (-100, 30)]
transparent = (hsla (degrees 111) 0.0 0.0 0.0)
predict1 = text (Text.height 30 (Text.fromString "0% possible precipitation"))
predict2 = text (Text.height 30 (Text.fromString "30% possible precipitation"))
predict3 = text (Text.height 30 (Text.fromString "60% possible precipitation"))
predict4 = text (Text.height 30 (Text.fromString "90% possible precipitation"))

predict t = if t >= 10 && t < 20
        then predict2
        else if t >= 20 && t < 30
        then predict3
        else if t >= 30
        then predict4
        else predict1

sunAndClouds t = group [sun |> rotate (degrees t*3), (clouds t) |> scale 0.9 |> move (0 + 10*sin t, -110), (predict t) |> move (0, 200)]
clouds t = if t >= 10 && t < 20
         then lBCloud
         else if t >= 20 && t < 30
         then bCloud
         else if t >= 30
         then greyCloud
         else noCloud

-- Chapter 5: Preference Suggestions
slide5 t = collage 700 700 [video, suggestion |> move ((-30*t), 0), rectangles]
video = group [filled red (rect 300 175)
             , filled white (ngon 3 40)]
rectangles = group [filled white (rect 200 600) |> move (-250, 0)
                  , filled white (rect 200 600) |> move (250, 0)]
suggestion = group [text (Text.height 10 (Text.fromString "Videos You Might Like: Suggestion A , Suggestion B, Suggestion C, Suggestion D, Suggestion E, Suggestion F, Suggestion G, Suggestion H, Suggestion I, Suggestion J, Suggestion K, Suggestion L, Suggestion N.")) |> move(310, -100)]

-- Chapter 6: Promotions
slide6 t = collage 700 700 [icon t]
icon t = group [filled blue (square 300)
            , mail, notification |> move (150, 150) |> scale (abs(sin(t/10)))
            , coupon |> scale (abs(sin(t/10)))]
mail = group [filled white (rect 250 145)
            , outlined (solid blue) (rect 250 145)
            , outlined (solid blue) (ngon 3 83) |> move (-83, 0)
            , outlined (solid blue) (ngon 3 83) |> move (83, 0) |> rotate (degrees 180)]
notification = group [filled red (circle 40)
                    , text (Text.color white (Text.height 50 (Text.bold (Text.fromString "1")))) |> move (0, 5)]
coupon = group [text (Text.height 50 (Text.color red (Text.bold (Text.fromString "25% "))))
               , text (Text.height 25 (Text.bold (Text.fromString "off"))) |> move (60, 0)
               , text (Text.height 35 (Text.bold (Text.fromString "just for you!"))) |> move (185, 0)] |> move (-120, -175)

-- Chapter 7: Education
slide7 t = collage 700 700 [-- Quiz part
                            outlined (solid black) (rect 400 600) -- the paper
                            ,text (Text.height 30 (Text.fromString "Question: 1 + 1 = ?")) |> move(-10, 260)
                            ,text (Text.height 30 (Text.fromString "A) 4")) |> move(-110, 220)
                            ,text (Text.height 30 (Text.fromString "B) 2")) |> move(-110, 170)
                            ,text (Text.height 30 (Text.fromString "C) 6")) |> move(-110, 120)
                            ,text (Text.height 30 (Text.fromString "D) 0")) |> move(-110, 70)
                            -- pencil
                            ,filled (rgb 255 204 0) (rect 600 80) |> rotate (degrees -40) |> move(-400, 350 + 100*sin t) -- body
                            ,filled black (ngon 3 45) |> rotate (degrees -40) |> move(-152, 350 + -207 + 100*sin t) -- lead tip
                            ]

-- Chapter 8: Finding love/dating
-- TODO: have a male and female stick figure coming together in the middle
lsSolidBlack = LineStyle black 2.0 (Round) (Smooth) [1,0] 0 -- creates solid black outline with width 2
leftPosition t = -315 * abs(sin (t*0.2)) - 50
rightPosition t = 315 * abs(sin (t*0.2)) + 50
slide8 t = collage 700 700 [-- a heart
                             scale 4 <| move (0,0) (filled red (ngon 4 (50*cos (t*0.2))))
                            , scale 4 <| move (68*abs(cos (t*0.2)),70*abs(cos (t*0.2))) (filled red (circle (37*cos (t*0.2))))
                            , scale 4 <| move (-68*abs(cos (t*0.2)),70*abs(cos (t*0.2))) (filled red (circle (37*cos (t*0.2))))
                            -- male stick figure
                            ,filled black (rect 2 75) |> move(rightPosition t,0) -- body
                            ,outlined (lsSolidBlack) (circle 20) |> move(rightPosition t, 58) -- head
                            ,filled black (rect 2 40) |> rotate(degrees -60) |> move(17+rightPosition t,20) -- right arm
                            ,filled black (rect 2 40) |> rotate(degrees 60) |> move(-17+rightPosition t,20) -- left arm
                            ,filled black (rect 2 50) |> rotate(degrees -160) |> move(9+rightPosition t,-59) -- right leg
                            ,filled black (rect 2 50) |> rotate(degrees 160) |> move(-9+rightPosition t,-59) -- left leg
                            -- female stick figure
                            ,outlined (lsSolidBlack) (polygon [(0,38), (-20,-36), (20,-36)]) |> move(leftPosition t,0) -- body
                            ,outlined (lsSolidBlack) (circle 20) |> move(leftPosition t, 58) -- head
                            ,filled black (rect 2 35) |> rotate(degrees -60) |> move(22+leftPosition t,20) -- right arm
                            ,filled black (rect 2 35) |> rotate(degrees 60) |> move(-22+leftPosition t,20) -- left arm
                            ,filled black (rect 2 50) |> rotate(degrees -160) |> move(9+leftPosition t,-59) -- right leg
                            ,filled black (rect 2 50) |> rotate(degrees 160) |> move(-9+leftPosition t,-59) -- left leg
                            ]

-- Chapter 9: Crime predication and how it helps cops, NGO's with relief work, businesses pull out of risky areas
lsSolidBlackCh9 = LineStyle black 2.0 (Round) (Smooth) [1,0] 0 -- creates solid black outline with width 2
lsSolidBlack2Ch9 = LineStyle black 3.0 (Round) (Smooth) [1,0] 0 -- creates solid black outline with width 3
rightPositionCh9 t = 315 * abs(sin (t*1.0)) + 40 -- move right 
slide9 t = collage 1000 600 [
                            outlined (lsSolidBlackCh9) (oval 55 60)  |> scale 2 -- |> move (0, 20) -- face
                            , outlined (lsSolidBlackCh9) (oval 49 15) |> scale 2 |> move (0,28) -- small oval
                            , filled black (rect 102 15) |> move (0, 34) -- black top
                            , filled white (rect 101 21) |> move (0, 51.9) -- white
                            , filled black (rect 35 3) |> rotate (degrees 69) |> move (55, 55) -- small one(top right)
                            , filled black (rect 35 3) |> rotate (degrees -69) |> move (-55, 55) -- small one (top left)
                            , outlined (lsSolidBlackCh9) (oval 120 20) |> move (0,69)
                            , filled black (circle 5) |> move (0,50)
                            , filled black (oval 5 10) |> move (-20,0) -- left eye
                            , filled black (oval 5 10) |> move (20,0) -- right eye
                            , filled black (rect 15 2) |> rotate (degrees 58) |> move (0,-13) -- nose
                            , filled black (rect 10 2) |> rotate (degrees 180) |> move (0, -20) -- nose 2
                            , filled black (rect 30 2) |> rotate (degrees 180) |> move (0, -33) -- mouth
                            , filled black (rect 10 2) |> rotate (degrees 180) |> move (0, -38) -- mouth 2 
                            , outlined (lsSolidBlack2Ch9) (oval 25 8) |> rotate (degrees 66) |> move(60,0) -- ear(right)
                            , outlined (lsSolidBlack2Ch9) (oval 25 8) |> rotate (degrees -66) |> move(-60,0)
                            , filled red (oval 25 60) |> move (rightPositionCh9 t +20  ,10)
                            , filled red (circle 10) |> move (rightPositionCh9 t +20, -32)
                            , outlined (lsSolidBlackCh9) (rect 90 90) |> move (370,0)
                            , move (370,-5) <| scale 2 <| text <| fromString <| "MAP" 
                            , move (0, -90) <| scale 2 <| text <| fromString <| "911"
                            ]

-- chapter 10 Crime prediction continued
rightPosition2 t =  315 * abs(sin (t*0.4))
leftPositionCh10 t = -315 * abs(sin (t*0.4)) 
downUp t = -65 + 100*sin t*1.3
upDown t = -65 + -100*sin t*1.3
clearGrey = rgba 111 111 111 0.6
slide10 t = collage 500 500 [ 

                                 (filled yellow (circle 20))
                                 , move (0,-20) (filled yellow (rect 10 20))
                                 , move (0,-60) (filled red (rect 40 60))
                                 , move (-14,-38) (filled red (circle 10))
                                 , move (14,-38) (filled red (circle 10))
                                 , move (-20, -90) (filled blue <| polygon [(0,0), (0,-60), (15,-60), (15,-20), (25,-20), (25,-60), (40,-60), (40,0),(0,0)])
                                 , move (-17,-150) (filled green (oval 24 8))
                                 , move (17,-150) (filled green (oval 24 8))
                                 , move (30, -50) (filled red (rect 10 40)) |> rotate (degrees 45)
                                 , move (-30, -50) (filled red (rect 10 40)) |> rotate (degrees -45)
                                 , move (-45, -65) (filled yellow (circle 8))
                                 , move (45, -65) (filled yellow (circle 8))
                                 , move (-10,0) (filled purple (circle 2)) 
                                 , move (10,0) (filled purple (circle 2))
                                 , move (0,-10) (filled white (oval 10 5))
                                 , filled (clearGrey) (rect 2 280) |> move (rightPosition2 t - 160,-70)
                                 , filled (clearGrey) (rect 2 280 ) |> move (leftPositionCh10 t + 160, -70)
                                 , filled (clearGrey) (rect 160 2) |> move (0, downUp t)
                                 , filled (clearGrey) (rect 160 2) |> move (0, upDown t)
                                 , filled grey (rect 70 280) |> move ( -150,-70)
                                 , filled grey (rect 70 280) |> move ( 150,-70)
                                 , filled grey ( rect 240 40) |> move (0,50)
                                 , filled grey ( rect 240 40) |> move (0,-190)
                                 , scale 2 <| move (0,50) <| text <| fromString <| "Security" 
                                 , scale 2 <| move (0,-190) <| text <| fromString <| "Detector" 
                                 --, move (0,-60) <| toForm (image 35 35 "/imgs/mario/jump/right.gif")

                                   ]                               

-- George Orwell eye ball
slide11 t = collage 700 700 [filled red (square 700)
                            ,filled white (oval 400 180) |> move(50*sin t, 100*cos t) -- white of eye
                            ,outlined lsSolidBlackCh9 (oval 400 180) |> move(50*sin t, 100*cos t) -- white of eye
                            -- eye lashes
                            ,filled black (rect 3 30) |> move(50*sin t, 105+100*cos t)
                            -- right top of eye
                            ,filled black (rect 3 30) |> move(40+50*sin t, 102+100*cos t) |> rotate(degrees -5)
                            ,filled black (rect 3 30) |> move(80+50*sin t, 97+100*cos t) |> rotate(degrees -9)
                            ,filled black (rect 3 30) |> move(120+50*sin t, 88+100*cos t) |> rotate(degrees -15)
                            ,filled black (rect 3 30) |> move(160+50*sin t, 70+100*cos t) |> rotate(degrees -24) 
                            -- left top of eye
                            ,filled black (rect 3 30) |> move(-40+50*sin t, 102+100*cos t) |> rotate(degrees 5)
                            ,filled black (rect 3 30) |> move(-80+50*sin t, 97+100*cos t) |> rotate(degrees 9)
                            ,filled black (rect 3 30) |> move(-120+50*sin t, 88+100*cos t) |> rotate(degrees 15)
                            ,filled black (rect 3 30) |> move(-160+50*sin t, 70+100*cos t) |> rotate(degrees 24) 
                            -- pupil
                            ,filled black (circle 40) |> move(120*sin t, 100*cos t)]

-- Ch. 11: Summary/outro. Can also be the intro slide
-- create the cover of the naked future, have the lines in the bg move around a bit
lsDashOutlineBlack = LineStyle black 2.0 (Round) (Smooth) [3,3] 0 -- creates dashed black outline with width 2
lsRed = LineStyle red 1 Round Smooth [1,0] 0
lsBlue = LineStyle blue 1 Round Smooth [1,0] 0
lsYellow = LineStyle yellow 1 Round Smooth [1,0] 0
lsGreen = LineStyle green 1 Round Smooth [1,0] 0
slide12 t = collage 700 700 [filled (rgb 244 244 244) (square 700) -- background colour
                            ,text (Text.typeface ["helvetica"] (Text.height 25 (Text.fromString "WHAT HAPPENS IN A WORLD THAT"))) |> move(0, -200) -- bottom text
                            ,text (Text.typeface ["helvetica"] (Text.height 25 (Text.fromString "ANTICIPATES YOUR EVERY MOVE"))) |> move(0, -250) -- bottom text
                            -- the web of lines!
                            ,traced lsRed (path [(175+10*sin(t*2), 275+10*cos(t)), (250,200), (170,130), (277,170), (164,-32), (-280+10*cos(t*2), 0+sin(t)), (76,121), (2,148), (-26,16), (80,-39), (-125,134), (-37,-22), (159,169), (250+10*cos(t*2), 80+10*sin(t)), (91,186), (31,142), (-44,170), (-137,136), (-188,2), (-79,-33), (-210,127), (116,-4), (-43,114), (173,32), (240+10*sin(t), -80+10*cos(2*t)), (-97,-57), (-258,153), (-280+10*cos(t*2), 0+sin(t)), (175+10*sin(t*2), 275+10*cos(t)), (-212,145), (250+10*cos(t*2), 80+10*sin(t))])
                            ,traced lsYellow (path [(175+10*sin(t*2), 275+10*cos(t)), (91,186), (76,121), (277,170), (250+10*cos(t*2), 80+10*sin(t)), (-137,136), (91,186), (116,-4), (250+10*cos(t*2), 80+10*sin(t)), (-210,127), (-79,-33), (240+10*sin(t), -80+10*cos(2*t)), (31,142), (-188,2), (240+10*sin(t), -80+10*cos(2*t)), (184,129), (76,22), (267,140), (175+10*sin(t*2), 275+10*cos(t)), (-84,12), (-252,96), (-280+10*cos(t*2), 0+sin(t)), (-187,-30), (-258,153), (-140,159), (175+10*sin(t*2), 275+10*cos(t)), (173,32), (250+10*cos(t*2), 80+10*sin(t))])
                            ,traced lsBlue (path [(175+10*sin(t*2), 275+10*cos(t)), (250+10*cos(t*2), 80+10*sin(t)), (76,121), (-137,136), (250+10*cos(t*2), 80+10*sin(t)), (164,-32), (159,169), (-79,-33), (-280+10*cos(t*2), 0+sin(t)), (-188,2), (31,142), (184,129), (-252,153), (240+10*sin(t), -80+10*cos(2*t)), (-280+10*cos(t*2), 0+sin(t)), (132,190), (175+10*sin(t*2), 275+10*cos(t)), (-45, 170), (240+10*sin(t), -80+10*cos(2*t)), (-187,-30), (173,32), (-79,-33), (267,140), (175+10*sin(t*2), 275+10*cos(t))])
                            ,traced lsGreen (path [(175+10*sin(t*2), 275+10*cos(t)), (170,130), (-137,136), (159,169), (116,-4), (250+10*cos(t*2), 80+10*sin(t)), (-79,-33), (159,169), (-79,-33), (91,186), (-280+10*cos(t*2), 0+sin(t)), (-252,153), (267,140), (-280+10*cos(t*2), 0+sin(t)), (-84,12), (76,22), (-187,-30), (175+10*sin(t*2), 275+10*cos(t)), (-187,-30), (173,32), (-188,2), (175+10*sin(t*2), 275+10*cos(t)), (267,140), (250+10*cos(t*2), 80+10*sin(t))])
                            -- Title, solid white to fill text
                            ,text (Text.height 100 (Text.color white (Text.fromString "THE NAKED"))) |> rotate(degrees 5) |> move(0, 160) 
                            ,text (Text.height 100 (Text.color white (Text.fromString "FUTURE"))) |> rotate(degrees 5) |> move(0, 0)
                            -- Title, outlined with black dashes
                            ,outlinedText lsDashOutlineBlack (Text.typeface ["helvetica"] (Text.height 100 (Text.fromString "THE NAKED"))) |> rotate(degrees 5) |> move(0, 160) 
                            ,outlinedText lsDashOutlineBlack (Text.typeface ["helvetica"] (Text.height 100 (Text.fromString "FUTURE"))) |> rotate(degrees 5) |> move(0, 0) 
                            -- black circle that lines will connect to
                            ,filled black (circle 5) |> move(175+10*sin(t*2), 275+10*cos(t)) --move(175, 275) -- top right
                            ,filled black (circle 5) |> move(250+10*cos(t*2), 80+10*sin(t)) --move(250, 80) -- right side, between the title texts
                            ,filled black (circle 5) |> move(240+10*sin(t), -80+10*cos(2*t)) --move(240, -80) -- right side, below both title texts
                            ,filled black (circle 5) |> move(-280+10*cos(t*2), 0+sin(t)) --move(-280, 0) -- left side, inline with top of bottom text   
                            -- our names
                            ,text (Text.typeface ["helvetica"] (Text.height 15 (Text.fromString "Suri Jia, Zhe Lin, Taylor Silva, Hamid Yuksel"))) |> move(0, -300)
                            ]

-- from original animation / Stephen Wolfram
stephenWolfram = group 
                  [(filled black (circle 20))
                   , move (0,-20) (filled black (rect 10 20))
                   , move (0,-60) (filled red (rect 40 60))
                   , move (-14,-38) (filled red (circle 10))
                   , move (14,-38) (filled red (circle 10))
                   , move (-20, -90) (filled blue <| polygon [(0,0), (0,-60), (15,-60), (15,-20), (25,-20), (25,-60), (40,-60), (40,0),(0,0)])
                   , move (-17,-150) (filled orange (oval 24 8))
                   , move (17,-150) (filled orange (oval 24 8))
                   , move (30, -50) (filled red (rect 10 40)) |> rotate (degrees 45)
                   , move (-30, -50) (filled red (rect 10 40)) |> rotate (degrees -45)
                   , move (-45, -65) (filled yellow (circle 8))
                   , move (45, -65) (filled yellow (circle 8))
                   , move (-10,0) (filled white (circle 1)) 
                   , move (10,0) (filled white (circle 1))
                   , move (0,-10) (filled white (oval 10 5))
                    ]