Skip to content

Commit 1900b2f

Browse files
committed
Reintroduce circle progress
1 parent 437beba commit 1900b2f

File tree

4 files changed

+167
-9
lines changed

4 files changed

+167
-9
lines changed

src/elm/Circle.elm

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
module Circle exposing (Circle, Coordinates, Stroke, draw, drawWithoutInsideBorder, inside)
2+
3+
import Html.Attributes as Html
4+
import Lib.Ratio as Ratio exposing (Ratio)
5+
import Svg exposing (Svg)
6+
import Svg.Attributes as Svg
7+
8+
9+
borderStroke : Stroke
10+
borderStroke =
11+
Stroke 1 "#ddd"
12+
13+
14+
type alias Coordinates =
15+
{ x : Int
16+
, y : Int
17+
}
18+
19+
20+
type alias Circle =
21+
{ radiant : Int
22+
, center : Coordinates
23+
, stroke : Stroke
24+
}
25+
26+
27+
type alias Stroke =
28+
{ width : Int
29+
, color : String
30+
}
31+
32+
33+
inside : Circle -> Stroke -> Circle
34+
inside outer stroke =
35+
{ radiant = outer.radiant - ceiling (toFloat outer.stroke.width / 2 + toFloat stroke.width / 2)
36+
, center = outer.center
37+
, stroke = stroke
38+
}
39+
40+
41+
draw : Circle -> Ratio -> List (Svg msg)
42+
draw circle ratio =
43+
circles circle ratio 2
44+
|> List.map (\( c, r ) -> draw_ c r)
45+
46+
47+
drawWithoutInsideBorder : Circle -> Ratio -> List (Svg msg)
48+
drawWithoutInsideBorder circle ratio =
49+
circles circle ratio 1
50+
|> List.take 3
51+
|> List.map (\( c, r ) -> draw_ c r)
52+
53+
54+
circles : Circle -> Ratio -> Int -> List ( Circle, Ratio )
55+
circles circle ratio nBorders =
56+
let
57+
outerBorder =
58+
{ radiant = circle.radiant + circle.stroke.width // 2
59+
, center = circle.center
60+
, stroke = borderStroke
61+
}
62+
63+
principalWidth =
64+
circle.stroke.width - nBorders * borderStroke.width
65+
66+
principal =
67+
inside outerBorder <| Stroke principalWidth circle.stroke.color
68+
69+
background =
70+
inside outerBorder (Stroke circle.stroke.width "#ccc")
71+
72+
innerBorder =
73+
inside principal borderStroke
74+
in
75+
[ ( background, Ratio.full )
76+
, ( principal, ratio )
77+
, ( outerBorder, Ratio.full )
78+
, ( innerBorder, Ratio.full )
79+
]
80+
81+
82+
83+
--
84+
-- DRAW
85+
--
86+
87+
88+
draw_ : Circle -> Ratio -> Svg msg
89+
draw_ circle ratio =
90+
let
91+
perimeter =
92+
2 * pi * toFloat circle.radiant
93+
in
94+
Svg.circle
95+
[ Svg.cx <| String.fromInt circle.center.x
96+
, Svg.cy <| String.fromInt circle.center.y
97+
, Svg.r <| String.fromInt circle.radiant
98+
, Svg.stroke circle.stroke.color
99+
, Svg.strokeWidth <| String.fromInt circle.stroke.width
100+
, Svg.fillOpacity "0"
101+
, Svg.strokeDasharray <| String.fromFloat perimeter
102+
, Html.style "stroke-dashoffset" <| String.fromFloat <| Ratio.apply ratio perimeter
103+
]
104+
[]

src/elm/Lib/Duration.elm

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
module Lib.Duration exposing (..)
22

3+
import Json.Decode
4+
import Json.Encode
35
import Time
46

57

68
type Duration
79
= Duration Int
810

11+
toJson : Duration -> Json.Encode.Value
12+
toJson duration =
13+
Json.Encode.int <| toMillis duration
14+
15+
jsonDecoder : Json.Decode.Decoder Duration
16+
jsonDecoder =
17+
Json.Decode.int
18+
|> Json.Decode.map ofMillis
19+
920
secondsBetween : Time.Posix -> Time.Posix -> Int
1021
secondsBetween a b =
1122
toSeconds <| between a b

src/elm/Main.elm

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,25 @@ port module Main exposing (..)
22

33
import Browser
44
import Browser.Navigation as Nav
5+
import Circle
56
import Html exposing (..)
6-
import Html.Attributes exposing (class, disabled, hidden, id, type_, value)
7+
import Html.Attributes exposing (class, disabled, id, type_, value)
78
import Html.Events exposing (onClick, onInput, onSubmit)
89
import Js.Commands
910
import Js.Events
1011
import Json.Decode
1112
import Json.Encode
12-
import Lib.Duration as Duration
13+
import Lib.Duration as Duration exposing (Duration)
1314
import Lib.Icons as Icons
1415
import Lib.ListExtras exposing (assign, rotate, uncons)
16+
import Lib.Ratio
1517
import Mobbers exposing (Mobber, Mobbers)
1618
import Random
1719
import Random.List
1820
import SharedEvents
1921
import Sound.Library
2022
import Svg exposing (Svg, svg)
23+
import Svg.Attributes as Svg
2124
import Task
2225
import Time
2326
import Url
@@ -54,7 +57,7 @@ main =
5457

5558
type ClockState
5659
= Off
57-
| On { end : Time.Posix, ended : Bool }
60+
| On { end : Time.Posix, length : Duration, ended : Bool }
5861

5962

6063
type AlarmState
@@ -149,7 +152,9 @@ update msg model =
149152

150153
StartWithAlarm sound ->
151154
( model
152-
, sendEvent <| SharedEvents.toJson <| SharedEvents.Started { time = model.now, alarm = sound }
155+
, sendEvent <|
156+
SharedEvents.toJson <|
157+
SharedEvents.Started { time = model.now, alarm = sound, length = Duration.ofSeconds 10 }
153158
)
154159

155160
StopSound ->
@@ -223,6 +228,7 @@ applyTo state event =
223228
| clock =
224229
On
225230
{ end = Time.posixToMillis started.time + (10 * 1000) |> Time.millisToPosix
231+
, length = started.length
226232
, ended = False
227233
}
228234
}
@@ -247,7 +253,7 @@ applyTo state event =
247253
( { state | mobbers = rotate state.mobbers }, Cmd.none )
248254

249255
( SharedEvents.ShuffledMobbers mobbers, _ ) ->
250-
( { state | mobbers = mobbers ++ (List.filter (\el -> not <| List.member el mobbers) state.mobbers) }, Cmd.none )
256+
( { state | mobbers = mobbers ++ List.filter (\el -> not <| List.member el mobbers) state.mobbers }, Cmd.none )
251257

252258
_ ->
253259
( state, Cmd.none )
@@ -286,13 +292,35 @@ view model =
286292
let
287293
action =
288294
detectAction model
295+
296+
totalWidth =
297+
220
298+
299+
outerRadiant =
300+
104
301+
302+
pomodoroCircle =
303+
Circle.Circle
304+
outerRadiant
305+
(Circle.Coordinates (outerRadiant + 6) (outerRadiant + 6))
306+
(Circle.Stroke 10 "#999")
307+
308+
mobCircle =
309+
Circle.inside pomodoroCircle <| Circle.Stroke 18 "#666"
289310
in
290311
{ title = "Mob Time"
291312
, body =
292313
[ div [ class "container" ]
293314
[ header []
294315
[ section []
295-
[ svg [ id "circles" ] []
316+
[ svg
317+
[ id "circles"
318+
, Svg.width <| String.fromInt totalWidth
319+
, Svg.height <| String.fromInt totalWidth
320+
]
321+
<|
322+
Circle.draw pomodoroCircle Lib.Ratio.full
323+
++ Circle.draw mobCircle (clockRatio model)
296324
, button
297325
[ id "action"
298326
, class action.class
@@ -344,6 +372,18 @@ view model =
344372
}
345373

346374

375+
clockRatio : Model -> Lib.Ratio.Ratio
376+
clockRatio model =
377+
case model.clock of
378+
Off ->
379+
Lib.Ratio.full
380+
381+
On on ->
382+
Duration.div (Duration.between model.now on.end) on.length
383+
|> ((-) 1)
384+
|> Lib.Ratio.from
385+
386+
347387
mobberView : ( Maybe String, Maybe Mobber ) -> Maybe (Html Msg)
348388
mobberView ( role, maybeMobber ) =
349389
maybeMobber

src/elm/SharedEvents.elm

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ module SharedEvents exposing (..)
22

33
import Json.Decode
44
import Json.Encode
5+
import Lib.Duration exposing (Duration)
56
import Mobbers exposing (Mobber, Mobbers)
67
import Sound.Library
78
import Time
89

910

1011
type Event
11-
= Started { time : Time.Posix, alarm : Sound.Library.Sound }
12+
= Started { time : Time.Posix, alarm : Sound.Library.Sound, length : Duration }
1213
| Stopped
1314
| AddedMobber Mobber
1415
| DeletedMobber Mobber
@@ -58,10 +59,11 @@ decoderFromName eventName =
5859

5960
startedDecoder : Json.Decode.Decoder Event
6061
startedDecoder =
61-
Json.Decode.map2
62-
(\start alarm -> Started { time = start, alarm = alarm })
62+
Json.Decode.map3
63+
(\start alarm length -> Started { time = start, alarm = alarm, length = length })
6364
(Json.Decode.field "time" timeDecoder)
6465
(Json.Decode.field "alarm" Json.Decode.string)
66+
(Json.Decode.field "length" Lib.Duration.jsonDecoder)
6567

6668

6769
timeDecoder : Json.Decode.Decoder Time.Posix
@@ -81,6 +83,7 @@ toJson event =
8183
[ ( "name", Json.Encode.string "Started" )
8284
, ( "time", Json.Encode.int <| Time.posixToMillis started.time )
8385
, ( "alarm", Json.Encode.string started.alarm )
86+
, ( "length", Lib.Duration.toJson started.length )
8487
]
8588

8689
Stopped ->

0 commit comments

Comments
 (0)