desck 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,415 @@
1
+ module DeckView exposing (backface, cardSize, cornerRadius, frontface, includes)
2
+
3
+ import Deck exposing (..)
4
+ import Svg exposing (Svg)
5
+ import Svg.Attributes as A
6
+ import Util exposing (num, rotate, scale, scaleXY, translate, url)
7
+ import Vec exposing (Vec2)
8
+
9
+
10
+ cardSize : Vec2
11
+ cardSize =
12
+ Vec2 250 350
13
+
14
+
15
+ var : String -> String
16
+ var name =
17
+ "var(--" ++ name ++ ")"
18
+
19
+
20
+ black : String
21
+ black =
22
+ var "black"
23
+
24
+
25
+ white : String
26
+ white =
27
+ var "white"
28
+
29
+
30
+ stripes : Float -> String -> String -> Float -> Svg msg
31
+ stripes width a b deg =
32
+ Svg.pattern
33
+ [ A.id "stripes"
34
+ , A.patternUnits "userSpaceOnUse"
35
+ , num A.width 10
36
+ , num A.height (width * 2)
37
+ , A.patternTransform <| rotate deg
38
+ ]
39
+ [ Svg.rect
40
+ [ num A.width 10
41
+ , num A.height width
42
+ , A.fill a
43
+ ]
44
+ []
45
+ , Svg.rect
46
+ [ num A.width 10
47
+ , num A.height width
48
+ , num A.y width
49
+ , A.fill b
50
+ ]
51
+ []
52
+ ]
53
+
54
+
55
+ includes : List (Svg msg)
56
+ includes =
57
+ [ Svg.defs [ A.id "defs" ]
58
+ [ stripes 15 "#444" "#666" 45.0
59
+ , Svg.symbol [ A.id "backface" ]
60
+ [ Svg.rect
61
+ [ num A.x 0
62
+ , num A.y 0
63
+ , num A.width <| 250
64
+ , num A.height <| 350
65
+ , A.class "card-back-pattern"
66
+ , A.rx cornerRadius
67
+ , A.fill (url "stripes")
68
+ , A.strokeWidth borderWidth
69
+ ]
70
+ []
71
+ ]
72
+ ]
73
+ ]
74
+
75
+
76
+ cornerRadius : String
77
+ cornerRadius =
78
+ "8"
79
+
80
+
81
+ borderWidth : String
82
+ borderWidth =
83
+ "2"
84
+
85
+
86
+ backface : Float -> Float -> CardModel -> List (Svg msg)
87
+ backface w h _ =
88
+ let
89
+ p =
90
+ 8
91
+ in
92
+ [ Svg.rect
93
+ [ num A.width <| w
94
+ , num A.height <| h
95
+ , A.rx cornerRadius
96
+ , A.class "card-back-rect"
97
+ , A.fill white
98
+ , A.stroke black
99
+ , A.strokeWidth borderWidth
100
+ ]
101
+ []
102
+
103
+ -- , Svg.rect
104
+ -- [ num A.width <| w
105
+ -- , num A.height <| h
106
+ -- , A.transform <| translate p p ++ scaleXY (1.0 - (2 * p / 250)) (1.0 - (2 * p / 350))
107
+ -- , A.rx cornerRadius
108
+ -- , A.class "card-back-rect"
109
+ -- , A.fill "var(--red)"
110
+ -- , A.stroke black
111
+ -- , A.strokeWidth borderWidth
112
+ -- ]
113
+ -- []
114
+ , Svg.use
115
+ [ A.xlinkHref "#backface"
116
+ , A.transform <| translate p p ++ scaleXY (1.0 - (2 * p / 250)) (1.0 - (2 * p / 350))
117
+ ]
118
+ []
119
+ ]
120
+
121
+
122
+ type alias Pip =
123
+ ( Float, Float )
124
+
125
+
126
+ pips : Rank -> List Pip
127
+ pips r =
128
+ let
129
+ top =
130
+ 0.32
131
+
132
+ htop =
133
+ top / 2.0
134
+
135
+ stop =
136
+ top / 3.0
137
+
138
+ mtop =
139
+ ((top - stop) / 2.0) + stop
140
+
141
+ side =
142
+ 0.2
143
+
144
+ center4 =
145
+ [ ( -side, stop ), ( side, stop ), ( -side, -stop ), ( side, -stop ) ]
146
+
147
+ courtSide =
148
+ side * 1.2
149
+
150
+ courtTop =
151
+ top * 0.95
152
+
153
+ court =
154
+ [ ( courtSide, courtTop ), ( -courtSide, -courtTop ) ]
155
+
156
+ shiftx : Float -> List Pip -> List Pip
157
+ shiftx v ls =
158
+ List.map (\p -> ( v + Tuple.first p, Tuple.second p )) ls
159
+ in
160
+ case r of
161
+ Ace ->
162
+ [ ( 0.0, 0.0 ) ]
163
+
164
+ Two ->
165
+ [ ( 0.0, top ), ( 0.0, -top ) ]
166
+
167
+ Three ->
168
+ pips Ace ++ pips Two
169
+
170
+ Four ->
171
+ (pips Two |> shiftx -side) ++ (pips Two |> shiftx side)
172
+
173
+ Five ->
174
+ pips Ace ++ pips Four
175
+
176
+ Six ->
177
+ (pips Three |> shiftx -side) ++ (pips Three |> shiftx side)
178
+
179
+ Seven ->
180
+ ( 0.0, -htop ) :: pips Six
181
+
182
+ Eight ->
183
+ ( 0.0, htop ) :: pips Seven
184
+
185
+ Nine ->
186
+ center4 ++ pips Five
187
+
188
+ Ten ->
189
+ center4 ++ [ ( 0.0, mtop ), ( 0.0, -mtop ) ] ++ pips Four
190
+
191
+ Jack ->
192
+ court
193
+
194
+ Queen ->
195
+ court
196
+
197
+ King ->
198
+ court
199
+
200
+
201
+ suitIcon : CardModel -> Svg msg
202
+ suitIcon model =
203
+ case maybeSuit model of
204
+ Just suit ->
205
+ let
206
+ href =
207
+ "#"
208
+ ++ suitAsString suit
209
+ in
210
+ Svg.use
211
+ [ A.xlinkHref href
212
+ , transform
213
+ [ translate -50.0 -50.0
214
+ ]
215
+ , A.class "card-suit-icon"
216
+ , A.class <| suitAsString suit
217
+ , A.fill <| var <| suitAsColor suit
218
+ ]
219
+ []
220
+
221
+ Nothing ->
222
+ Svg.text ""
223
+
224
+
225
+
226
+ -- Svg.image
227
+ -- [ imageUrl <| suitString suit
228
+ -- , A.transform <| translate (-size / 2.0) (-size / 2.0)
229
+ -- , A.filter <| url <| suitAsColor suit
230
+ -- ]
231
+ -- []
232
+
233
+
234
+ cornerPip : CardModel -> Svg msg
235
+ cornerPip model =
236
+ let
237
+ textScale =
238
+ scale 3.7
239
+
240
+ textPos =
241
+ translate 0 7
242
+
243
+ rankChar =
244
+ case model of
245
+ Ranked rank _ ->
246
+ rankAsChar rank
247
+
248
+ Joker _ ->
249
+ "x"
250
+ in
251
+ Svg.g
252
+ []
253
+ [ Svg.g
254
+ [ transform [ textPos, textScale ] ]
255
+ [ Svg.use
256
+ [ A.xlinkHref <| "#" ++ rankChar
257
+ , A.fill <| var <| modelAsColor model
258
+ ]
259
+ []
260
+ ]
261
+ , Svg.g
262
+ [ transform
263
+ [ translate 12.0 60.0
264
+ , scale 0.26
265
+ ]
266
+ ]
267
+ [ suitIcon model ]
268
+ ]
269
+
270
+
271
+ transform : List String -> Svg.Attribute msg
272
+ transform ls =
273
+ A.transform <| String.join " " ls
274
+
275
+
276
+ frontface : Float -> Float -> CardModel -> List (Svg msg)
277
+ frontface w h model =
278
+ let
279
+ p =
280
+ 5
281
+
282
+ -- TODO Cards - Jumbo index setting
283
+ cp =
284
+ 34.0
285
+
286
+ pipx pos =
287
+ (w / 2.0) + w * Tuple.first pos
288
+
289
+ pipy pos =
290
+ (h / 2.0) + h * Tuple.second pos
291
+
292
+ size =
293
+ 0.65
294
+
295
+ courtSymbol m =
296
+ "#"
297
+ ++ modelAsShort m
298
+
299
+ isPicture m =
300
+ case m of
301
+ Ranked rank _ ->
302
+ List.member rank [ Jack, Queen, King ]
303
+
304
+ Joker _ ->
305
+ True
306
+
307
+ courtCard =
308
+ if isPicture model then
309
+ Svg.g
310
+ []
311
+ [ Svg.use
312
+ [ A.xlinkHref <| courtSymbol model
313
+ , A.transform <| translate cp cp ++ scaleXY (1.0 - (cp / 250.0) * 2.0) (1.0 - (cp / 350.0) * 2.0)
314
+ ]
315
+ []
316
+
317
+ -- , Svg.rect
318
+ -- [ case model of
319
+ -- Ranked _ _ ->
320
+ -- A.stroke "#ffffff"
321
+ -- Joker _ ->
322
+ -- A.stroke "transparent"
323
+ -- , A.fill "transparent"
324
+ -- , A.strokeWidth "5px"
325
+ -- , A.class "card-court-border"
326
+ -- , A.rx cornerRadius
327
+ -- -- , A.filter <| url "blue"
328
+ -- , A.transform <| translate cp cp ++ scaleXY (1.0 - (cp / 250.0) * 2.0) (1.0 - (cp / 350.0) * 2.0)
329
+ -- , num A.width 250
330
+ -- , num A.height 350
331
+ -- ]
332
+ -- []
333
+ ]
334
+
335
+ else
336
+ Svg.text ""
337
+
338
+ courtPipSize =
339
+ size * 0.8
340
+
341
+ suitIconFromPos pos =
342
+ Svg.g
343
+ [ transform
344
+ [ translate (pipx pos) (pipy pos)
345
+ , rotate
346
+ (if Tuple.second pos <= 0.0 then
347
+ 0.0
348
+
349
+ else
350
+ 180.0
351
+ )
352
+ , scale
353
+ (case maybeRank model of
354
+ Just rank ->
355
+ case rank of
356
+ Ace ->
357
+ size * 2
358
+
359
+ Jack ->
360
+ courtPipSize
361
+
362
+ Queen ->
363
+ courtPipSize
364
+
365
+ King ->
366
+ courtPipSize
367
+
368
+ _ ->
369
+ size
370
+
371
+ Nothing ->
372
+ size
373
+ )
374
+ ]
375
+ ]
376
+ [ suitIcon model
377
+ ]
378
+
379
+ pipIcons =
380
+ case maybeRank model of
381
+ Just rank ->
382
+ pips rank
383
+ |> List.map suitIconFromPos
384
+ |> Svg.g []
385
+
386
+ Nothing ->
387
+ Svg.text ""
388
+
389
+ cornerLabels =
390
+ Svg.g []
391
+ [ Svg.g
392
+ [ A.transform <| translate p p
393
+ ]
394
+ [ cornerPip model ]
395
+ , Svg.g
396
+ [ A.transform <| translate (w - p) (h - p) ++ rotate 180
397
+ ]
398
+ [ cornerPip model ]
399
+ ]
400
+ in
401
+ [ Svg.rect
402
+ [ num A.width <| w
403
+ , num A.height <| h
404
+ , A.rx cornerRadius
405
+ , A.class "card-front-rect"
406
+ , A.ry cornerRadius
407
+ , A.fill white
408
+ , A.stroke black
409
+ , A.strokeWidth borderWidth
410
+ ]
411
+ []
412
+ , courtCard
413
+ , pipIcons
414
+ , cornerLabels
415
+ ]
package/src/Layout.elm ADDED
@@ -0,0 +1,224 @@
1
+ module Layout exposing (..)
2
+
3
+ import List exposing (indexedMap, length, map, reverse)
4
+ import Vec exposing (Vec2)
5
+
6
+
7
+ type Spread
8
+ = Horizontal
9
+ | Vertical
10
+ | Diagonal
11
+ | Rows
12
+ | Columns
13
+ | Stack
14
+ | Fan
15
+
16
+
17
+ defaultSpread : Spread -> Int
18
+ defaultSpread s =
19
+ let
20
+ dist =
21
+ 35
22
+ in
23
+ case s of
24
+ Horizontal ->
25
+ dist
26
+
27
+ Vertical ->
28
+ 85
29
+
30
+ Diagonal ->
31
+ dist
32
+
33
+ Rows ->
34
+ 4
35
+
36
+ Columns ->
37
+ 4
38
+
39
+ Stack ->
40
+ 0
41
+
42
+ Fan ->
43
+ 15
44
+
45
+
46
+ updateSpreadValue : Spread -> Spread -> Int -> Int
47
+ updateSpreadValue prev next value =
48
+ if defaultSpread prev == defaultSpread next then
49
+ value
50
+
51
+ else
52
+ defaultSpread next
53
+
54
+
55
+ validateSpreadValue : Spread -> Int -> Int
56
+ validateSpreadValue spreadType value =
57
+ case spreadType of
58
+ Rows ->
59
+ max 1 value
60
+
61
+ Columns ->
62
+ max 1 value
63
+
64
+ _ ->
65
+ value
66
+
67
+
68
+ spreadAsString : Spread -> String
69
+ spreadAsString st =
70
+ case st of
71
+ Horizontal ->
72
+ "Horizontal"
73
+
74
+ Vertical ->
75
+ "Vertical"
76
+
77
+ Diagonal ->
78
+ "Diagonal"
79
+
80
+ Rows ->
81
+ "Rows"
82
+
83
+ Columns ->
84
+ "Columns"
85
+
86
+ Stack ->
87
+ "Stack"
88
+
89
+ Fan ->
90
+ "Fan"
91
+
92
+
93
+ spreadTransforms : Int -> Vec2 -> Int -> Spread -> List ( Vec2, Vec2, Float )
94
+ spreadTransforms n cardSize spreadValue s =
95
+ let
96
+ noRotation =
97
+ List.map (\v -> ( v, Vec.half Vec.one, 0.0 ))
98
+
99
+ vec2i : Int -> Int -> Vec2
100
+ vec2i x y =
101
+ Vec2 (toFloat x) (toFloat y)
102
+
103
+ targets =
104
+ List.range 0 (n - 1)
105
+ in
106
+ case s of
107
+ Stack ->
108
+ targets
109
+ |> map (\_ -> Vec.zero)
110
+ |> noRotation
111
+ |> indexedMap (\i ( p, pv, _ ) -> ( p, pv, toFloat <| spreadValue * i ))
112
+
113
+ Horizontal ->
114
+ targets
115
+ |> map
116
+ (\i -> vec2i (i * spreadValue) 0)
117
+ |> reverse
118
+ |> noRotation
119
+
120
+ Vertical ->
121
+ targets
122
+ |> map
123
+ (\i -> vec2i 0 (i * spreadValue))
124
+ |> reverse
125
+ |> noRotation
126
+
127
+ -- FIX 4 cards to 3 rows etc, same for columns
128
+ Rows ->
129
+ let
130
+ columns =
131
+ max 1 (length targets // spreadValue)
132
+ in
133
+ targets
134
+ |> map
135
+ (\i ->
136
+ Vec2
137
+ (toFloat (modBy columns i) * cardSize.x)
138
+ (toFloat (i // columns) * cardSize.y)
139
+ )
140
+ |> reverse
141
+ |> noRotation
142
+
143
+ Columns ->
144
+ let
145
+ rows =
146
+ max 1 (length targets // spreadValue)
147
+ in
148
+ targets
149
+ |> map
150
+ (\i ->
151
+ Vec2
152
+ (toFloat (i // rows) * cardSize.x)
153
+ (toFloat (modBy rows i) * cardSize.y)
154
+ )
155
+ |> reverse
156
+ |> noRotation
157
+
158
+ Diagonal ->
159
+ targets
160
+ |> map
161
+ (\i ->
162
+ Vec2
163
+ (toFloat <| i * spreadValue)
164
+ (toFloat <| i * spreadValue)
165
+ )
166
+ |> reverse
167
+ |> noRotation
168
+
169
+ Fan ->
170
+ targets
171
+ |> map
172
+ (\i ->
173
+ let
174
+ t =
175
+ toFloat i / toFloat (n - 1)
176
+
177
+ -- angle =
178
+ -- 0.2
179
+ -- p =
180
+ -- t * pi * 2.0 * 0.1 - pi * 0.5 - pi * angle
181
+ -- x =
182
+ -- cos p
183
+ -- y =
184
+ -- sin p
185
+ -- radius =
186
+ -- (toFloat <| length targets) * 80.0
187
+ deg =
188
+ toFloat spreadValue * 0.5 * (toFloat <| List.length targets)
189
+
190
+ pos =
191
+ -- sub (scale radius (Vec2 x y)) (Vec2 (-radius * 0.105) (-radius * 0.995))
192
+ Vec.zero
193
+
194
+ pivot =
195
+ Vec2 0.5 1.0
196
+
197
+ rot =
198
+ -0.5 * deg + deg * t
199
+ in
200
+ ( pos, pivot, rot )
201
+ )
202
+ |> reverse
203
+
204
+
205
+
206
+ -- _ ->
207
+ -- targets
208
+ -- |> map (\_ -> zero)
209
+ -- |> noRotation
210
+
211
+
212
+ hsep : Int -> Float -> Vec2 -> Int -> Vec2
213
+ hsep rows separation size index =
214
+ let
215
+ column =
216
+ index // rows
217
+
218
+ row =
219
+ modBy rows index
220
+
221
+ ( w, h ) =
222
+ Vec.tuple size
223
+ in
224
+ Vec2 (separation + toFloat column * w) (separation + toFloat row * h)