spells-mtg 0.0.1__py3-none-any.whl

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.

Potentially problematic release.


This version of spells-mtg might be problematic. Click here for more details.

spells/columns.py ADDED
@@ -0,0 +1,771 @@
1
+ from dataclasses import dataclass
2
+ from collections.abc import Callable
3
+
4
+ import polars as pl
5
+
6
+ from spells.enums import View, ColName, ColType
7
+
8
+
9
+ @dataclass(frozen=True)
10
+ class ColumnSpec:
11
+ name: str
12
+ col_type: ColType
13
+ expr: pl.Expr | None = None
14
+ exprMap: Callable[[str], pl.Expr] | None = None
15
+ views: tuple[View, ...] = ()
16
+ dependencies: list[str] | None = None
17
+ version: str | None = (
18
+ None # only needed for user-defined functions with python functions in expr
19
+ )
20
+
21
+
22
+ @dataclass(frozen=True)
23
+ class ColumnDefinition:
24
+ name: str
25
+ col_type: ColType
26
+ expr: pl.Expr | tuple[pl.Expr, ...]
27
+ views: tuple[View, ...]
28
+ dependencies: tuple[str, ...]
29
+ signature: str
30
+
31
+
32
+ default_columns = [
33
+ ColName.COLOR,
34
+ ColName.RARITY,
35
+ ColName.NUM_SEEN,
36
+ ColName.ALSA,
37
+ ColName.NUM_TAKEN,
38
+ ColName.ATA,
39
+ ColName.NUM_GP,
40
+ ColName.PCT_GP,
41
+ ColName.GP_WR,
42
+ ColName.NUM_OH,
43
+ ColName.OH_WR,
44
+ ColName.NUM_GIH,
45
+ ColName.GIH_WR,
46
+ ]
47
+
48
+ _column_specs = [
49
+ ColumnSpec(
50
+ name=ColName.NAME,
51
+ col_type=ColType.GROUP_BY,
52
+ views=(),
53
+ # handled by internals, derived from both 'pick' and "name mapped" columns
54
+ ),
55
+ ColumnSpec(
56
+ name=ColName.EXPANSION,
57
+ col_type=ColType.GROUP_BY,
58
+ views=(View.GAME, View.DRAFT),
59
+ ),
60
+ ColumnSpec(
61
+ name=ColName.EVENT_TYPE,
62
+ col_type=ColType.GROUP_BY,
63
+ views=(View.GAME, View.DRAFT),
64
+ ),
65
+ ColumnSpec(
66
+ name=ColName.DRAFT_ID,
67
+ views=(View.GAME, View.DRAFT),
68
+ col_type=ColType.FILTER_ONLY,
69
+ ),
70
+ ColumnSpec(
71
+ name=ColName.DRAFT_TIME,
72
+ col_type=ColType.FILTER_ONLY,
73
+ views=(View.GAME, View.DRAFT),
74
+ ),
75
+ ColumnSpec(
76
+ name=ColName.DRAFT_DATE,
77
+ col_type=ColType.GROUP_BY,
78
+ views=(View.GAME, View.DRAFT),
79
+ expr=pl.col("draft_time").str.to_datetime("%Y-%m-%d %H:%M:%S").dt.date(),
80
+ dependencies=[ColName.DRAFT_TIME],
81
+ ),
82
+ ColumnSpec(
83
+ name=ColName.DRAFT_DAY_OF_WEEK,
84
+ col_type=ColType.GROUP_BY,
85
+ views=(View.GAME, View.DRAFT),
86
+ expr=pl.col("draft_time").str.to_datetime("%Y-%m-%d %H:%M:%S").dt.weekday(),
87
+ dependencies=[ColName.DRAFT_TIME],
88
+ ),
89
+ ColumnSpec(
90
+ name=ColName.DRAFT_HOUR,
91
+ col_type=ColType.GROUP_BY,
92
+ views=(View.GAME, View.DRAFT),
93
+ expr=pl.col("draft_time").str.to_datetime("%Y-%m-%d %H:%M:%S").dt.hour(),
94
+ dependencies=[ColName.DRAFT_TIME],
95
+ ),
96
+ ColumnSpec(
97
+ name=ColName.DRAFT_WEEK,
98
+ col_type=ColType.GROUP_BY,
99
+ views=(View.GAME, View.DRAFT),
100
+ expr=pl.col("draft_time").str.to_datetime("%Y-%m-%d %H:%M:%S").dt.week(),
101
+ dependencies=[ColName.DRAFT_TIME],
102
+ ),
103
+ ColumnSpec(
104
+ name=ColName.RANK,
105
+ col_type=ColType.GROUP_BY,
106
+ views=(View.GAME, View.DRAFT),
107
+ ),
108
+ ColumnSpec(
109
+ name=ColName.USER_N_GAMES_BUCKET,
110
+ col_type=ColType.GROUP_BY,
111
+ views=(View.DRAFT, View.GAME),
112
+ ),
113
+ ColumnSpec(
114
+ name=ColName.USER_GAME_WIN_RATE_BUCKET,
115
+ col_type=ColType.GROUP_BY,
116
+ views=(View.DRAFT, View.GAME),
117
+ ),
118
+ ColumnSpec(
119
+ name=ColName.PLAYER_COHORT,
120
+ col_type=ColType.GROUP_BY,
121
+ views=(View.DRAFT, View.GAME),
122
+ expr=pl.when(pl.col("user_n_games_bucket") < 100)
123
+ .then(pl.lit("Other"))
124
+ .otherwise(
125
+ pl.when(pl.col("user_game_win_rate_bucket") > 0.57)
126
+ .then(pl.lit("Top"))
127
+ .otherwise(
128
+ pl.when(pl.col("user_game_win_rate_bucket") < 0.49)
129
+ .then(pl.lit("Bottom"))
130
+ .otherwise(pl.lit("Middle"))
131
+ )
132
+ ),
133
+ dependencies=[ColName.USER_N_GAMES_BUCKET, ColName.USER_GAME_WIN_RATE_BUCKET],
134
+ ),
135
+ ColumnSpec(
136
+ name=ColName.EVENT_MATCH_WINS,
137
+ col_type=ColType.GROUP_BY,
138
+ views=(View.DRAFT,),
139
+ ),
140
+ ColumnSpec(
141
+ name=ColName.EVENT_MATCH_WINS_SUM,
142
+ col_type=ColType.PICK_SUM,
143
+ views=(View.DRAFT,),
144
+ expr=pl.col(ColName.EVENT_MATCH_WINS),
145
+ dependencies=[ColName.EVENT_MATCH_WINS],
146
+ ),
147
+ ColumnSpec(
148
+ name=ColName.EVENT_MATCH_LOSSES,
149
+ col_type=ColType.GROUP_BY,
150
+ views=(View.DRAFT,),
151
+ ),
152
+ ColumnSpec(
153
+ name=ColName.EVENT_MATCH_LOSSES_SUM,
154
+ col_type=ColType.PICK_SUM,
155
+ views=(View.DRAFT,),
156
+ expr=pl.col(ColName.EVENT_MATCH_LOSSES),
157
+ dependencies=[ColName.EVENT_MATCH_LOSSES],
158
+ ),
159
+ ColumnSpec(
160
+ name=ColName.EVENT_MATCHES,
161
+ col_type=ColType.GROUP_BY,
162
+ views=(View.DRAFT,),
163
+ expr=pl.col("event_match_wins") + pl.col("event_match_losses"),
164
+ dependencies=[ColName.EVENT_MATCH_WINS, ColName.EVENT_MATCH_LOSSES],
165
+ ),
166
+ ColumnSpec(
167
+ name=ColName.EVENT_MATCHES_SUM,
168
+ col_type=ColType.PICK_SUM,
169
+ views=(View.DRAFT,),
170
+ expr=pl.col(ColName.EVENT_MATCHES),
171
+ dependencies=[ColName.EVENT_MATCHES],
172
+ ),
173
+ ColumnSpec(
174
+ name=ColName.IS_TROPHY,
175
+ col_type=ColType.GROUP_BY,
176
+ views=(View.DRAFT,),
177
+ expr=pl.when(pl.col("event_type") == "Traditional")
178
+ .then(pl.col("event_match_wins") == 3)
179
+ .otherwise(pl.col("event_match_wins") == 7),
180
+ dependencies=[ColName.EVENT_TYPE, ColName.EVENT_MATCH_WINS],
181
+ ),
182
+ ColumnSpec(
183
+ name=ColName.IS_TROPHY_SUM,
184
+ col_type=ColType.PICK_SUM,
185
+ views=(View.DRAFT,),
186
+ expr=pl.col(ColName.IS_TROPHY),
187
+ dependencies=[ColName.IS_TROPHY],
188
+ ),
189
+ ColumnSpec(
190
+ name=ColName.PACK_NUMBER,
191
+ col_type=ColType.FILTER_ONLY, # use pack_num
192
+ views=(View.DRAFT,),
193
+ ),
194
+ ColumnSpec(
195
+ name=ColName.PACK_NUM,
196
+ col_type=ColType.GROUP_BY,
197
+ views=(View.DRAFT,),
198
+ expr=pl.col("pack_number") + 1,
199
+ dependencies=[ColName.PACK_NUMBER],
200
+ ),
201
+ ColumnSpec(
202
+ name=ColName.PICK_NUMBER,
203
+ col_type=ColType.FILTER_ONLY, # use pick_num
204
+ views=(View.DRAFT,),
205
+ ),
206
+ ColumnSpec(
207
+ name=ColName.PICK_NUM,
208
+ col_type=ColType.GROUP_BY,
209
+ views=(View.DRAFT,),
210
+ expr=pl.col("pick_number") + 1,
211
+ dependencies=[ColName.PICK_NUMBER],
212
+ ),
213
+ ColumnSpec(
214
+ name=ColName.TAKEN_AT,
215
+ col_type=ColType.PICK_SUM,
216
+ views=(View.DRAFT,),
217
+ expr=pl.col(ColName.PICK_NUM),
218
+ dependencies=[ColName.PICK_NUM],
219
+ ),
220
+ ColumnSpec(
221
+ name=ColName.NUM_TAKEN,
222
+ col_type=ColType.PICK_SUM,
223
+ views=(View.DRAFT,),
224
+ expr=pl.when(pl.col(ColName.PICK).is_not_null())
225
+ .then(1)
226
+ .otherwise(0), # a literal returns one row under select alone
227
+ dependencies=[ColName.PICK],
228
+ ),
229
+ ColumnSpec(
230
+ name=ColName.PICK,
231
+ col_type=ColType.FILTER_ONLY, # aggregated as "name"
232
+ views=(View.DRAFT,),
233
+ ),
234
+ ColumnSpec(
235
+ name=ColName.PICK_MAINDECK_RATE,
236
+ col_type=ColType.PICK_SUM,
237
+ views=(View.DRAFT,),
238
+ ),
239
+ ColumnSpec(
240
+ name=ColName.PICK_SIDEBOARD_IN_RATE,
241
+ col_type=ColType.PICK_SUM,
242
+ views=(View.DRAFT,),
243
+ ),
244
+ ColumnSpec(
245
+ name=ColName.PACK_CARD,
246
+ col_type=ColType.NAME_SUM,
247
+ views=(View.DRAFT,),
248
+ ),
249
+ ColumnSpec(
250
+ name=ColName.LAST_SEEN,
251
+ col_type=ColType.NAME_SUM,
252
+ views=(View.DRAFT,),
253
+ exprMap=lambda name: pl.col(f"pack_card_{name}")
254
+ * pl.min_horizontal("pick_num", 8),
255
+ dependencies=[ColName.PACK_CARD, ColName.PICK_NUM],
256
+ ),
257
+ ColumnSpec(
258
+ name=ColName.NUM_SEEN,
259
+ col_type=ColType.NAME_SUM,
260
+ views=(View.DRAFT,),
261
+ exprMap=lambda name: pl.col(f"pack_card_{name}") * (pl.col("pick_num") <= 8),
262
+ dependencies=[ColName.PACK_CARD, ColName.PICK_NUM],
263
+ ),
264
+ ColumnSpec(
265
+ name=ColName.POOL,
266
+ col_type=ColType.NAME_SUM,
267
+ views=(View.DRAFT,),
268
+ ),
269
+ ColumnSpec(
270
+ name=ColName.GAME_TIME,
271
+ col_type=ColType.FILTER_ONLY,
272
+ views=(View.GAME,),
273
+ ),
274
+ ColumnSpec(
275
+ name=ColName.GAME_DATE,
276
+ col_type=ColType.GROUP_BY,
277
+ views=(View.GAME,),
278
+ expr=pl.col("game_time").str.to_datetime("%Y-%m-%d %H-%M-%S").dt.date(),
279
+ dependencies=[ColName.GAME_TIME],
280
+ ),
281
+ ColumnSpec(
282
+ name=ColName.GAME_DAY_OF_WEEK,
283
+ col_type=ColType.GROUP_BY,
284
+ views=(View.GAME,),
285
+ expr=pl.col("game_time").str.to_datetime("%Y-%m-%d %H-%M-%S").dt.weekday(),
286
+ dependencies=[ColName.GAME_TIME],
287
+ ),
288
+ ColumnSpec(
289
+ name=ColName.GAME_HOUR,
290
+ col_type=ColType.GROUP_BY,
291
+ views=(View.GAME,),
292
+ expr=pl.col("game_time").str.to_datetime("%Y-%m-%d %H-%M-%S").dt.hour(),
293
+ dependencies=[ColName.GAME_TIME],
294
+ ),
295
+ ColumnSpec(
296
+ name=ColName.GAME_WEEK,
297
+ col_type=ColType.GROUP_BY,
298
+ views=(View.GAME,),
299
+ expr=pl.col("game_time").str.to_datetime("%Y-%m-%d %H-%M-%S").dt.week(),
300
+ dependencies=[ColName.GAME_TIME],
301
+ ),
302
+ ColumnSpec(
303
+ name=ColName.BUILD_INDEX,
304
+ col_type=ColType.GROUP_BY,
305
+ views=(View.GAME,),
306
+ ),
307
+ ColumnSpec(
308
+ name=ColName.MATCH_NUMBER,
309
+ col_type=ColType.GROUP_BY,
310
+ views=(View.GAME,),
311
+ ),
312
+ ColumnSpec(
313
+ name=ColName.GAME_NUMBER,
314
+ col_type=ColType.GROUP_BY,
315
+ views=(View.GAME,),
316
+ ),
317
+ ColumnSpec(
318
+ name=ColName.NUM_GAMES,
319
+ col_type=ColType.GAME_SUM,
320
+ views=(View.GAME,),
321
+ expr=pl.col(ColName.GAME_NUMBER).is_not_null(),
322
+ dependencies=[ColName.GAME_NUMBER],
323
+ ),
324
+ ColumnSpec(
325
+ name=ColName.NUM_MATCHES,
326
+ col_type=ColType.GAME_SUM,
327
+ views=(View.GAME,),
328
+ expr=pl.col(ColName.GAME_NUMBER) == 1,
329
+ dependencies=[ColName.GAME_NUMBER],
330
+ ),
331
+ ColumnSpec(
332
+ name=ColName.NUM_EVENTS,
333
+ col_type=ColType.GAME_SUM,
334
+ views=(View.GAME,),
335
+ expr=(pl.col(ColName.GAME_NUMBER) == 1) & (pl.col(ColName.MATCH_NUMBER) == 1),
336
+ dependencies=[ColName.GAME_NUMBER, ColName.MATCH_NUMBER],
337
+ ),
338
+ ColumnSpec(
339
+ name=ColName.OPP_RANK,
340
+ col_type=ColType.GROUP_BY,
341
+ views=(View.GAME,),
342
+ ),
343
+ ColumnSpec(
344
+ name=ColName.MAIN_COLORS,
345
+ col_type=ColType.GROUP_BY,
346
+ views=(View.GAME,),
347
+ ),
348
+ ColumnSpec(
349
+ name=ColName.NUM_COLORS,
350
+ col_type=ColType.GROUP_BY,
351
+ views=(View.GAME,),
352
+ expr=pl.col(ColName.MAIN_COLORS).str.len_chars(),
353
+ dependencies=[ColName.MAIN_COLORS],
354
+ ),
355
+ ColumnSpec(
356
+ name=ColName.SPLASH_COLORS,
357
+ col_type=ColType.GROUP_BY,
358
+ views=(View.GAME,),
359
+ ),
360
+ ColumnSpec(
361
+ name=ColName.HAS_SPLASH,
362
+ col_type=ColType.GROUP_BY,
363
+ views=(View.GAME,),
364
+ expr=pl.col(ColName.SPLASH_COLORS).str.len_chars() > 0,
365
+ dependencies=[ColName.SPLASH_COLORS],
366
+ ),
367
+ ColumnSpec(
368
+ name=ColName.ON_PLAY,
369
+ col_type=ColType.GROUP_BY,
370
+ views=(View.GAME,),
371
+ ),
372
+ ColumnSpec(
373
+ name=ColName.NUM_ON_PLAY,
374
+ col_type=ColType.GAME_SUM,
375
+ expr=pl.col(ColName.ON_PLAY),
376
+ dependencies=[ColName.ON_PLAY],
377
+ ),
378
+ ColumnSpec(
379
+ name=ColName.NUM_MULLIGANS,
380
+ col_type=ColType.GROUP_BY,
381
+ views=(View.GAME,),
382
+ ),
383
+ ColumnSpec(
384
+ name=ColName.NUM_MULLIGANS_SUM,
385
+ col_type=ColType.GAME_SUM,
386
+ views=(View.GAME,),
387
+ expr=pl.col(ColName.NUM_MULLIGANS),
388
+ dependencies=[ColName.NUM_MULLIGANS],
389
+ ),
390
+ ColumnSpec(
391
+ name=ColName.OPP_NUM_MULLIGANS,
392
+ col_type=ColType.GAME_SUM,
393
+ views=(View.GAME,),
394
+ ),
395
+ ColumnSpec(
396
+ name=ColName.OPP_NUM_MULLIGANS_SUM,
397
+ col_type=ColType.GAME_SUM,
398
+ views=(View.GAME,),
399
+ expr=pl.col(ColName.OPP_NUM_MULLIGANS),
400
+ dependencies=[ColName.OPP_NUM_MULLIGANS],
401
+ ),
402
+ ColumnSpec(
403
+ name=ColName.OPP_COLORS,
404
+ col_type=ColType.GROUP_BY,
405
+ views=(View.GAME,),
406
+ ),
407
+ ColumnSpec(
408
+ name=ColName.NUM_TURNS,
409
+ col_type=ColType.GROUP_BY,
410
+ views=(View.GAME,),
411
+ ),
412
+ ColumnSpec(
413
+ name=ColName.NUM_TURNS_SUM,
414
+ col_type=ColType.GAME_SUM,
415
+ views=(View.GAME,),
416
+ expr=pl.col(ColName.NUM_TURNS),
417
+ dependencies=[ColName.NUM_TURNS],
418
+ ),
419
+ ColumnSpec(
420
+ name=ColName.WON,
421
+ col_type=ColType.GROUP_BY,
422
+ views=(View.GAME,),
423
+ ),
424
+ ColumnSpec(
425
+ name=ColName.NUM_WON,
426
+ col_type=ColType.GAME_SUM,
427
+ views=(View.GAME,),
428
+ expr=pl.col(ColName.WON),
429
+ dependencies=[ColName.WON],
430
+ ),
431
+ ColumnSpec(
432
+ name=ColName.OPENING_HAND,
433
+ col_type=ColType.NAME_SUM,
434
+ views=(View.GAME,),
435
+ ),
436
+ ColumnSpec(
437
+ name=ColName.WON_OPENING_HAND,
438
+ col_type=ColType.NAME_SUM,
439
+ views=(View.GAME,),
440
+ exprMap=lambda name: pl.col(f"opening_hand_{name}") * pl.col(ColName.WON),
441
+ dependencies=[ColName.OPENING_HAND, ColName.WON],
442
+ ),
443
+ ColumnSpec(
444
+ name=ColName.DRAWN,
445
+ col_type=ColType.NAME_SUM,
446
+ views=(View.GAME,),
447
+ ),
448
+ ColumnSpec(
449
+ name=ColName.WON_DRAWN,
450
+ col_type=ColType.NAME_SUM,
451
+ views=(View.GAME,),
452
+ exprMap=lambda name: pl.col(f"drawn_{name}") * pl.col(ColName.WON),
453
+ dependencies=[ColName.DRAWN, ColName.WON],
454
+ ),
455
+ ColumnSpec(
456
+ name=ColName.TUTORED,
457
+ col_type=ColType.NAME_SUM,
458
+ views=(View.GAME,),
459
+ ),
460
+ ColumnSpec(
461
+ name=ColName.WON_TUTORED,
462
+ col_type=ColType.NAME_SUM,
463
+ views=(View.GAME,),
464
+ exprMap=lambda name: pl.col(f"tutored_{name}") * pl.col(ColName.WON),
465
+ dependencies=[ColName.TUTORED, ColName.WON],
466
+ ),
467
+ ColumnSpec(
468
+ name=ColName.DECK,
469
+ col_type=ColType.NAME_SUM,
470
+ views=(View.GAME,),
471
+ ),
472
+ ColumnSpec(
473
+ name=ColName.WON_DECK,
474
+ col_type=ColType.NAME_SUM,
475
+ views=(View.GAME,),
476
+ exprMap=lambda name: pl.col(f"deck_{name}") * pl.col(ColName.WON),
477
+ dependencies=[ColName.DECK, ColName.WON],
478
+ ),
479
+ ColumnSpec(
480
+ name=ColName.SIDEBOARD,
481
+ col_type=ColType.NAME_SUM,
482
+ views=(View.GAME,),
483
+ ),
484
+ ColumnSpec(
485
+ name=ColName.WON_SIDEBOARD,
486
+ col_type=ColType.NAME_SUM,
487
+ views=(View.GAME,),
488
+ exprMap=lambda name: pl.col(f"sideboard_{name}") * pl.col(ColName.WON),
489
+ dependencies=[ColName.SIDEBOARD, ColName.WON],
490
+ ),
491
+ ColumnSpec(
492
+ name=ColName.NUM_GNS,
493
+ col_type=ColType.NAME_SUM,
494
+ views=(View.GAME,),
495
+ exprMap=lambda name: pl.max_horizontal(
496
+ 0,
497
+ pl.col(f"deck_{name}")
498
+ - pl.col(f"drawn_{name}")
499
+ - pl.col(f"tutored_{name}")
500
+ - pl.col(f"opening_hand_{name}"),
501
+ ),
502
+ dependencies=[
503
+ ColName.DECK,
504
+ ColName.DRAWN,
505
+ ColName.TUTORED,
506
+ ColName.OPENING_HAND,
507
+ ],
508
+ ),
509
+ ColumnSpec(
510
+ name=ColName.WON_NUM_GNS,
511
+ col_type=ColType.NAME_SUM,
512
+ views=(View.GAME,),
513
+ exprMap=lambda name: pl.col(ColName.WON) * pl.col(f"num_gns_{name}"),
514
+ dependencies=[ColName.NUM_GNS, ColName.WON],
515
+ ),
516
+ ColumnSpec(
517
+ name=ColName.SET_CODE,
518
+ col_type=ColType.CARD_ATTR,
519
+ views=(View.CARD,),
520
+ ),
521
+ ColumnSpec(
522
+ name=ColName.COLOR,
523
+ col_type=ColType.CARD_ATTR,
524
+ views=(View.CARD,),
525
+ ),
526
+ ColumnSpec(
527
+ name=ColName.RARITY,
528
+ col_type=ColType.CARD_ATTR,
529
+ views=(View.CARD,),
530
+ ),
531
+ ColumnSpec(
532
+ name=ColName.COLOR_IDENTITY,
533
+ col_type=ColType.CARD_ATTR,
534
+ views=(View.CARD,),
535
+ ),
536
+ ColumnSpec(
537
+ name=ColName.CARD_TYPE,
538
+ col_type=ColType.CARD_ATTR,
539
+ views=(View.CARD,),
540
+ ),
541
+ ColumnSpec(
542
+ name=ColName.SUBTYPE,
543
+ col_type=ColType.CARD_ATTR,
544
+ views=(View.CARD,),
545
+ ),
546
+ ColumnSpec(
547
+ name=ColName.MANA_VALUE,
548
+ col_type=ColType.CARD_ATTR,
549
+ views=(View.CARD,),
550
+ ),
551
+ ColumnSpec(
552
+ name=ColName.MANA_COST,
553
+ col_type=ColType.CARD_ATTR,
554
+ views=(View.CARD,),
555
+ ),
556
+ ColumnSpec(
557
+ name=ColName.POWER,
558
+ col_type=ColType.CARD_ATTR,
559
+ views=(View.CARD,),
560
+ ),
561
+ ColumnSpec(
562
+ name=ColName.TOUGHNESS,
563
+ col_type=ColType.CARD_ATTR,
564
+ views=(View.CARD,),
565
+ ),
566
+ ColumnSpec(
567
+ name=ColName.IS_BONUS_SHEET,
568
+ col_type=ColType.CARD_ATTR,
569
+ views=(View.CARD,),
570
+ ),
571
+ ColumnSpec(
572
+ name=ColName.IS_DFC,
573
+ col_type=ColType.CARD_ATTR,
574
+ views=(View.CARD,),
575
+ ),
576
+ ColumnSpec(
577
+ name=ColName.PICKED_MATCH_WR,
578
+ col_type=ColType.AGG,
579
+ expr=pl.col(ColName.EVENT_MATCH_WINS_SUM) / pl.col(ColName.EVENT_MATCHES),
580
+ dependencies=[ColName.EVENT_MATCH_WINS_SUM, ColName.EVENT_MATCHES],
581
+ ),
582
+ ColumnSpec(
583
+ name=ColName.TROPHY_RATE,
584
+ col_type=ColType.AGG,
585
+ expr=pl.col(ColName.IS_TROPHY_SUM) / pl.col(ColName.NUM_TAKEN),
586
+ dependencies=[ColName.IS_TROPHY_SUM, ColName.NUM_TAKEN],
587
+ ),
588
+ ColumnSpec(
589
+ name=ColName.GAME_WR,
590
+ col_type=ColType.AGG,
591
+ expr=pl.col(ColName.NUM_WON) / pl.col(ColName.NUM_GAMES),
592
+ dependencies=[ColName.NUM_WON, ColName.NUM_GAMES],
593
+ ),
594
+ ColumnSpec(
595
+ name=ColName.ALSA,
596
+ col_type=ColType.AGG,
597
+ views=(),
598
+ expr=pl.col(ColName.LAST_SEEN) / pl.col(ColName.NUM_SEEN),
599
+ dependencies=[ColName.LAST_SEEN, ColName.NUM_SEEN],
600
+ ),
601
+ ColumnSpec(
602
+ name=ColName.ATA,
603
+ col_type=ColType.AGG,
604
+ expr=pl.col(ColName.TAKEN_AT) / pl.col(ColName.NUM_TAKEN),
605
+ dependencies=[ColName.TAKEN_AT, ColName.NUM_TAKEN],
606
+ ),
607
+ ColumnSpec(
608
+ name=ColName.NUM_GP,
609
+ col_type=ColType.AGG,
610
+ expr=pl.col(ColName.DECK),
611
+ dependencies=[ColName.DECK],
612
+ ),
613
+ ColumnSpec(
614
+ name=ColName.PCT_GP,
615
+ col_type=ColType.AGG,
616
+ expr=pl.col(ColName.DECK) / (pl.col(ColName.DECK) + pl.col(ColName.SIDEBOARD)),
617
+ dependencies=[ColName.DECK, ColName.SIDEBOARD],
618
+ ),
619
+ ColumnSpec(
620
+ name=ColName.GP_WR,
621
+ col_type=ColType.AGG,
622
+ expr=pl.col(ColName.WON_DECK) / pl.col(ColName.DECK),
623
+ dependencies=[ColName.WON_DECK, ColName.DECK],
624
+ ),
625
+ ColumnSpec(
626
+ name=ColName.NUM_OH,
627
+ col_type=ColType.AGG,
628
+ expr=pl.col(ColName.OPENING_HAND),
629
+ dependencies=[ColName.OPENING_HAND],
630
+ ),
631
+ ColumnSpec(
632
+ name=ColName.OH_WR,
633
+ col_type=ColType.AGG,
634
+ expr=pl.col(ColName.WON_OPENING_HAND) / pl.col(ColName.OPENING_HAND),
635
+ dependencies=[ColName.WON_OPENING_HAND, ColName.OPENING_HAND],
636
+ ),
637
+ ColumnSpec(
638
+ name=ColName.NUM_GIH,
639
+ col_type=ColType.AGG,
640
+ expr=pl.col(ColName.OPENING_HAND) + pl.col(ColName.DRAWN),
641
+ dependencies=[ColName.OPENING_HAND, ColName.DRAWN],
642
+ ),
643
+ ColumnSpec(
644
+ name=ColName.NUM_GIH_WON,
645
+ col_type=ColType.AGG,
646
+ expr=pl.col(ColName.WON_OPENING_HAND) + pl.col(ColName.WON_DRAWN),
647
+ dependencies=[ColName.WON_OPENING_HAND, ColName.WON_DRAWN],
648
+ ),
649
+ ColumnSpec(
650
+ name=ColName.GIH_WR,
651
+ col_type=ColType.AGG,
652
+ expr=pl.col(ColName.NUM_GIH_WON) / pl.col(ColName.NUM_GIH),
653
+ dependencies=[ColName.NUM_GIH_WON, ColName.NUM_GIH],
654
+ ),
655
+ ColumnSpec(
656
+ name=ColName.GNS_WR,
657
+ col_type=ColType.AGG,
658
+ expr=pl.col(ColName.WON_NUM_GNS) / pl.col(ColName.NUM_GNS),
659
+ dependencies=[ColName.WON_NUM_GNS, ColName.NUM_GNS],
660
+ ),
661
+ ColumnSpec(
662
+ name=ColName.IWD,
663
+ col_type=ColType.AGG,
664
+ expr=pl.col(ColName.GIH_WR) - pl.col(ColName.GNS_WR),
665
+ dependencies=[ColName.GIH_WR, ColName.GNS_WR],
666
+ ),
667
+ ColumnSpec(
668
+ name=ColName.NUM_IN_POOL,
669
+ col_type=ColType.AGG,
670
+ expr=pl.col(ColName.DECK) + pl.col(ColName.SIDEBOARD),
671
+ dependencies=[ColName.DECK, ColName.SIDEBOARD],
672
+ ),
673
+ ColumnSpec(
674
+ name=ColName.IN_POOL_WR,
675
+ col_type=ColType.AGG,
676
+ expr=(pl.col(ColName.WON_DECK) + pl.col(ColName.WON_SIDEBOARD))
677
+ / pl.col(ColName.NUM_IN_POOL),
678
+ dependencies=[ColName.WON_DECK, ColName.WON_SIDEBOARD, ColName.NUM_IN_POOL],
679
+ ),
680
+ ColumnSpec(
681
+ name=ColName.DECK_TOTAL,
682
+ col_type=ColType.AGG,
683
+ expr=pl.col(ColName.DECK).sum(),
684
+ dependencies=[ColName.DECK],
685
+ ),
686
+ ColumnSpec(
687
+ name=ColName.WON_DECK_TOTAL,
688
+ col_type=ColType.AGG,
689
+ expr=pl.col(ColName.WON_DECK).sum(),
690
+ dependencies=[ColName.WON_DECK],
691
+ ),
692
+ ColumnSpec(
693
+ name=ColName.GP_WR_MEAN,
694
+ col_type=ColType.AGG,
695
+ expr=pl.col(ColName.WON_DECK_TOTAL) / pl.col(ColName.DECK_TOTAL),
696
+ dependencies=[ColName.WON_DECK_TOTAL, ColName.DECK_TOTAL],
697
+ ),
698
+ ColumnSpec(
699
+ name=ColName.GP_WR_EXCESS,
700
+ col_type=ColType.AGG,
701
+ expr=pl.col(ColName.GP_WR) - pl.col(ColName.GP_WR_MEAN),
702
+ dependencies=[ColName.GP_WR, ColName.GP_WR_MEAN],
703
+ ),
704
+ ColumnSpec(
705
+ name=ColName.GP_WR_VAR,
706
+ col_type=ColType.AGG,
707
+ expr=(pl.col(ColName.GP_WR_EXCESS).pow(2) * pl.col(ColName.NUM_GP)).sum()
708
+ / pl.col(ColName.DECK_TOTAL),
709
+ dependencies=[ColName.GP_WR_EXCESS, ColName.NUM_GP, ColName.DECK_TOTAL],
710
+ ),
711
+ ColumnSpec(
712
+ name=ColName.GP_WR_STDEV,
713
+ col_type=ColType.AGG,
714
+ expr=pl.col(ColName.GP_WR_VAR).sqrt(),
715
+ dependencies=[ColName.GP_WR_VAR],
716
+ ),
717
+ ColumnSpec(
718
+ name=ColName.GP_WR_Z,
719
+ col_type=ColType.AGG,
720
+ expr=pl.col(ColName.GP_WR_EXCESS) / pl.col(ColName.GP_WR_STDEV),
721
+ dependencies=[ColName.GP_WR_EXCESS, ColName.GP_WR_STDEV],
722
+ ),
723
+ ColumnSpec(
724
+ name=ColName.GIH_TOTAL,
725
+ col_type=ColType.AGG,
726
+ expr=pl.col(ColName.NUM_GIH).sum(),
727
+ dependencies=[ColName.NUM_GIH],
728
+ ),
729
+ ColumnSpec(
730
+ name=ColName.WON_GIH_TOTAL,
731
+ col_type=ColType.AGG,
732
+ expr=pl.col(ColName.NUM_GIH_WON).sum(),
733
+ dependencies=[ColName.NUM_GIH_WON],
734
+ ),
735
+ ColumnSpec(
736
+ name=ColName.GIH_WR_MEAN,
737
+ col_type=ColType.AGG,
738
+ expr=pl.col(ColName.WON_GIH_TOTAL) / pl.col(ColName.GIH_TOTAL),
739
+ dependencies=[ColName.WON_GIH_TOTAL, ColName.GIH_TOTAL],
740
+ ),
741
+ ColumnSpec(
742
+ name=ColName.GIH_WR_EXCESS,
743
+ col_type=ColType.AGG,
744
+ expr=pl.col(ColName.GIH_WR) - pl.col(ColName.GIH_WR_MEAN),
745
+ dependencies=[ColName.GIH_WR, ColName.GIH_WR_MEAN],
746
+ ),
747
+ ColumnSpec(
748
+ name=ColName.GIH_WR_VAR,
749
+ col_type=ColType.AGG,
750
+ expr=(pl.col(ColName.GIH_WR_EXCESS).pow(2) * pl.col(ColName.NUM_GIH)).sum()
751
+ / pl.col(ColName.GIH_TOTAL),
752
+ dependencies=[ColName.GIH_WR_EXCESS, ColName.NUM_GIH, ColName.GIH_TOTAL],
753
+ ),
754
+ ColumnSpec(
755
+ name=ColName.GIH_WR_STDEV,
756
+ col_type=ColType.AGG,
757
+ expr=pl.col(ColName.GIH_WR_VAR).sqrt(),
758
+ dependencies=[ColName.GIH_WR_VAR],
759
+ ),
760
+ ColumnSpec(
761
+ name=ColName.GIH_WR_Z,
762
+ col_type=ColType.AGG,
763
+ expr=pl.col(ColName.GIH_WR_EXCESS) / pl.col(ColName.GIH_WR_STDEV),
764
+ dependencies=[ColName.GIH_WR_EXCESS, ColName.GIH_WR_STDEV],
765
+ ),
766
+ ]
767
+
768
+ col_spec_map = {col.name: col for col in _column_specs}
769
+
770
+ for item in ColName:
771
+ assert item in col_spec_map, f"column {item} enumerated but not specified"