|
| 1 | +module Main exposing (main) |
| 2 | + |
| 3 | +import Html exposing (Html, Attribute, table, tbody, tr, td, text) |
| 4 | +import Html.Attributes exposing (style) |
| 5 | +import Matrix exposing (Matrix) |
| 6 | +import Matrix.Extra |
| 7 | +import Array |
| 8 | +import Random |
| 9 | +import AnimationFrame |
| 10 | + |
| 11 | + |
| 12 | +main : Program Never Grid Msg |
| 13 | +main = |
| 14 | + Html.program |
| 15 | + { init = init |
| 16 | + , update = update |
| 17 | + , view = view |
| 18 | + , subscriptions = subscriptions |
| 19 | + } |
| 20 | + |
| 21 | + |
| 22 | +type alias Grid = |
| 23 | + Matrix Bool |
| 24 | + |
| 25 | + |
| 26 | +type Msg |
| 27 | + = SetGrid Grid |
| 28 | + | Step |
| 29 | + |
| 30 | + |
| 31 | +gridGenerator : Random.Generator Grid |
| 32 | +gridGenerator = |
| 33 | + Random.list 50 (Random.list 50 Random.bool) |
| 34 | + |> Random.map (Matrix.fromList >> Maybe.withDefault (Matrix.repeat 50 50 False)) |
| 35 | + |
| 36 | + |
| 37 | +init : ( Grid, Cmd Msg ) |
| 38 | +init = |
| 39 | + ( Matrix.repeat 50 50 False, Random.generate SetGrid gridGenerator ) |
| 40 | + |
| 41 | + |
| 42 | +update : Msg -> Grid -> ( Grid, Cmd Msg ) |
| 43 | +update msg grid = |
| 44 | + case msg of |
| 45 | + SetGrid grid_ -> |
| 46 | + ( grid_, Cmd.none ) |
| 47 | + |
| 48 | + Step -> |
| 49 | + let |
| 50 | + step x y isAlive = |
| 51 | + let |
| 52 | + neighborCount = |
| 53 | + Matrix.Extra.neighbours x y grid |
| 54 | + |> List.filter identity |
| 55 | + |> List.length |
| 56 | + in |
| 57 | + if (not isAlive) && neighborCount == 3 then |
| 58 | + True |
| 59 | + else if isAlive && (neighborCount == 2 || neighborCount == 3) then |
| 60 | + True |
| 61 | + else |
| 62 | + False |
| 63 | + in |
| 64 | + ( Matrix.indexedMap step grid, Cmd.none ) |
| 65 | + |
| 66 | + |
| 67 | +subscriptions : Grid -> Sub Msg |
| 68 | +subscriptions _ = |
| 69 | + AnimationFrame.diffs (always Step) |
| 70 | + |
| 71 | + |
| 72 | +view : Grid -> Html Msg |
| 73 | +view grid = |
| 74 | + table [] |
| 75 | + [ tbody [] (List.map row (matrixToList grid)) |
| 76 | + ] |
| 77 | + |
| 78 | + |
| 79 | +matrixToList : Matrix a -> List (List a) |
| 80 | +matrixToList matrix = |
| 81 | + List.range 0 (Matrix.height matrix) |
| 82 | + |> List.map (flip Matrix.getRow matrix >> Maybe.withDefault Array.empty >> Array.toList) |
| 83 | + |
| 84 | + |
| 85 | +row : List Bool -> Html Msg |
| 86 | +row = |
| 87 | + List.map cell >> (tr []) |
| 88 | + |
| 89 | + |
| 90 | +cell : Bool -> Html Msg |
| 91 | +cell isAlive = |
| 92 | + td [ cellStyle isAlive ] [] |
| 93 | + |
| 94 | + |
| 95 | +cellStyle : Bool -> Attribute Msg |
| 96 | +cellStyle isAlive = |
| 97 | + let |
| 98 | + backgroundColor = |
| 99 | + if isAlive then |
| 100 | + "black" |
| 101 | + else |
| 102 | + "white" |
| 103 | + in |
| 104 | + style |
| 105 | + [ ( "background-color", backgroundColor ) |
| 106 | + , ( "width", "5px" ) |
| 107 | + , ( "height", "5px" ) |
| 108 | + ] |
0 commit comments