overtime-live-trading-utils 2.1.29 → 2.1.31

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "overtime-live-trading-utils",
3
- "version": "2.1.29",
3
+ "version": "2.1.31",
4
4
  "description": "",
5
5
  "main": "main.js",
6
6
  "scripts": {
@@ -14,7 +14,7 @@
14
14
  "dependencies": {
15
15
  "@types/node": "^20.8.10",
16
16
  "oddslib": "^2.1.1",
17
- "overtime-utils": "^0.1.37",
17
+ "overtime-utils": "^0.1.41",
18
18
  "react": "^17.0.1"
19
19
  },
20
20
  "devDependencies": {
@@ -568,6 +568,64 @@ describe('Resolution Utils', () => {
568
568
 
569
569
  expect(result).toBeNull();
570
570
  });
571
+
572
+ it('Bug Fix: Should NOT mark current period as complete when future periods have data (live in period 3)', () => {
573
+ // This tests the bug where OpticOdds API includes future period data with scores (including zeros)
574
+ // Period 3 is currently being played, period 4 has 0-0 scores but hasn't started
575
+ const event = {
576
+ status: 'live',
577
+ is_live: true,
578
+ in_play: { period: '3' },
579
+ scores: {
580
+ home: { periods: { period_1: 33, period_2: 32, period_3: 12, period_4: 0 } },
581
+ away: { periods: { period_1: 23, period_2: 27, period_3: 18, period_4: 0 } },
582
+ },
583
+ };
584
+
585
+ const result = detectCompletedPeriods(event);
586
+
587
+ expect(result).not.toBeNull();
588
+ expect(result?.completedPeriods).toEqual([1, 2]); // Only periods 1 and 2 are complete
589
+ expect(result?.currentPeriod).toBe(3);
590
+ // Period 3 is currently being played, so NOT complete
591
+ // Period 4 has data (0-0) but hasn't started, so NOT complete
592
+ });
593
+
594
+ it('Bug Fix: Should mark all periods as complete for completed game', () => {
595
+ const event = {
596
+ status: 'completed',
597
+ is_live: false,
598
+ scores: {
599
+ home: { periods: { period_1: 33, period_2: 32, period_3: 25, period_4: 20 } },
600
+ away: { periods: { period_1: 23, period_2: 27, period_3: 18, period_4: 22 } },
601
+ },
602
+ };
603
+
604
+ const result = detectCompletedPeriods(event);
605
+
606
+ expect(result).not.toBeNull();
607
+ expect(result?.completedPeriods).toEqual([1, 2, 3, 4]);
608
+ // All periods complete because game status is 'completed'
609
+ });
610
+
611
+ it('Bug Fix: Should NOT mark current period as complete during transition to period 4', () => {
612
+ const event = {
613
+ status: 'live',
614
+ is_live: true,
615
+ in_play: { period: '4' },
616
+ scores: {
617
+ home: { periods: { period_1: 33, period_2: 32, period_3: 25, period_4: 5 } },
618
+ away: { periods: { period_1: 23, period_2: 27, period_3: 18, period_4: 3 } },
619
+ },
620
+ };
621
+
622
+ const result = detectCompletedPeriods(event);
623
+
624
+ expect(result).not.toBeNull();
625
+ expect(result?.completedPeriods).toEqual([1, 2, 3]); // Periods 1, 2, 3 are complete
626
+ expect(result?.currentPeriod).toBe(4);
627
+ // Period 4 is currently in_play, so NOT complete yet
628
+ });
571
629
  });
572
630
 
573
631
 
package/src/utils/odds.ts CHANGED
@@ -523,6 +523,29 @@ export const groupAndFormatGGOdds = (oddsArray: any[]) => {
523
523
  return formattedOdds;
524
524
  };
525
525
 
526
+ /**
527
+ * Normalize a score line like "A:B" to a map-friendly key "A_B" with
528
+ * numeric normalization (removing any leading zeros).
529
+ *
530
+ * Behavior:
531
+ * - Accepts optional whitespace around the colon (e.g., "03 : 10").
532
+ * - Parses both sides as numbers to strip leading zeros:
533
+ * "13:09" → "13_9", "13:00" → "13_0", "03:10" → "3_10".
534
+ * - If the input does NOT match "<digits> : <digits>", falls back to a simple
535
+ * string replace of ":" with "_" without numeric parsing.
536
+ *
537
+ * @param {string|number} line
538
+ * A score string (e.g., "13:09") or any value coercible to string.
539
+ *
540
+ * @returns {string}
541
+ * The normalized key (e.g., "13_9"). If not a digit:digit pattern, returns
542
+ * the string with ":" replaced by "_".
543
+ */
544
+ function normalizeScoreLine(line: any) {
545
+ const m = String(line).match(/(\d+)\s*:\s*(\d+)/);
546
+ return m ? `${Number(m[1])}_${Number(m[2])}` : String(line).replace(':', '_');
547
+ }
548
+
526
549
  /**
527
550
  * Groups correct score odds by their lines and formats the result.
528
551
  *
@@ -534,65 +557,280 @@ export const groupAndFormatCorrectScoreOdds = (oddsArray: any[], commonData: Hom
534
557
  const homeTeamKey = commonData.homeTeam.toLowerCase().replace(/\s+/g, '_');
535
558
  const awayTeamKey = commonData.awayTeam.toLowerCase().replace(/\s+/g, '_');
536
559
 
537
- const oddsMap = {
538
- draw_0_0: 0,
539
- draw_1_1: 0,
540
- draw_2_2: 0,
541
- draw_3_3: 0,
542
- draw_4_4: 0,
543
- [`${homeTeamKey}_1_0`]: 0,
544
- [`${homeTeamKey}_2_0`]: 0,
545
- [`${homeTeamKey}_2_1`]: 0,
546
- [`${homeTeamKey}_3_0`]: 0,
547
- [`${homeTeamKey}_3_1`]: 0,
548
- [`${homeTeamKey}_3_2`]: 0,
549
- [`${homeTeamKey}_4_0`]: 0,
550
- [`${homeTeamKey}_4_1`]: 0,
551
- [`${homeTeamKey}_4_2`]: 0,
552
- [`${homeTeamKey}_4_3`]: 0,
553
- [`${awayTeamKey}_1_0`]: 0,
554
- [`${awayTeamKey}_2_0`]: 0,
555
- [`${awayTeamKey}_2_1`]: 0,
556
- [`${awayTeamKey}_3_0`]: 0,
557
- [`${awayTeamKey}_3_1`]: 0,
558
- [`${awayTeamKey}_3_2`]: 0,
559
- [`${awayTeamKey}_4_0`]: 0,
560
- [`${awayTeamKey}_4_1`]: 0,
561
- [`${awayTeamKey}_4_2`]: 0,
562
- [`${awayTeamKey}_4_3`]: 0,
563
- other: 0,
564
- };
565
-
566
- // Populate the oddsMap with the odds from the provided array
567
- oddsArray.forEach((odd) => {
568
- const normalizedSelection = `${odd.selection.toLowerCase().replace(/\s+/g, '_')}_${odd.selectionLine.replace(
569
- ':',
570
- '_'
571
- )}`;
572
- if (oddsMap.hasOwnProperty(normalizedSelection)) {
573
- oddsMap[normalizedSelection] = odd.price;
560
+ // Group odds by typeId first
561
+ const oddsByTypeId = oddsArray.reduce((acc: any, odd: any) => {
562
+ const typeId = odd.typeId || 10100;
563
+ if (!acc[typeId]) {
564
+ acc[typeId] = [];
574
565
  }
575
- });
566
+ acc[typeId].push(odd);
567
+ return acc;
568
+ }, {});
576
569
 
577
- const allOddsAreZero = Object.values(oddsMap).every((odd) => odd === ZERO);
570
+ // Create market objects for each unique typeId
571
+ const marketObjects: any[] = [];
572
+
573
+ Object.entries(oddsByTypeId).forEach(([typeId, odds]: [string, any]) => {
574
+ const oddsMap = {
575
+ draw_0_0: 0,
576
+ draw_1_1: 0,
577
+ draw_2_2: 0,
578
+ draw_3_3: 0,
579
+ draw_4_4: 0,
580
+ [`${homeTeamKey}_1_0`]: 0,
581
+ [`${homeTeamKey}_2_0`]: 0,
582
+ [`${homeTeamKey}_2_1`]: 0,
583
+ [`${homeTeamKey}_3_0`]: 0,
584
+ [`${homeTeamKey}_3_1`]: 0,
585
+ [`${homeTeamKey}_3_2`]: 0,
586
+ [`${homeTeamKey}_4_0`]: 0,
587
+ [`${homeTeamKey}_4_1`]: 0,
588
+ [`${homeTeamKey}_4_2`]: 0,
589
+ [`${homeTeamKey}_4_3`]: 0,
590
+ [`${awayTeamKey}_1_0`]: 0,
591
+ [`${awayTeamKey}_2_0`]: 0,
592
+ [`${awayTeamKey}_2_1`]: 0,
593
+ [`${awayTeamKey}_3_0`]: 0,
594
+ [`${awayTeamKey}_3_1`]: 0,
595
+ [`${awayTeamKey}_3_2`]: 0,
596
+ [`${awayTeamKey}_4_0`]: 0,
597
+ [`${awayTeamKey}_4_1`]: 0,
598
+ [`${awayTeamKey}_4_2`]: 0,
599
+ [`${awayTeamKey}_4_3`]: 0,
600
+ draw_5_5: 0,
601
+ draw_6_6: 0,
602
+ draw_7_7: 0,
603
+ draw_8_8: 0,
604
+ draw_9_9: 0,
605
+ draw_10_10: 0,
606
+ draw_11_11: 0,
607
+ draw_12_12: 0,
608
+ draw_13_13: 0,
609
+ draw_14_14: 0,
610
+ [`${homeTeamKey}_5_0`]: 0,
611
+ [`${homeTeamKey}_5_1`]: 0,
612
+ [`${homeTeamKey}_5_2`]: 0,
613
+ [`${homeTeamKey}_5_3`]: 0,
614
+ [`${homeTeamKey}_5_4`]: 0,
615
+ [`${homeTeamKey}_6_0`]: 0,
616
+ [`${homeTeamKey}_6_1`]: 0,
617
+ [`${homeTeamKey}_6_2`]: 0,
618
+ [`${homeTeamKey}_6_3`]: 0,
619
+ [`${homeTeamKey}_6_4`]: 0,
620
+ [`${homeTeamKey}_6_5`]: 0,
621
+ [`${homeTeamKey}_7_0`]: 0,
622
+ [`${homeTeamKey}_7_1`]: 0,
623
+ [`${homeTeamKey}_7_2`]: 0,
624
+ [`${homeTeamKey}_7_3`]: 0,
625
+ [`${homeTeamKey}_7_4`]: 0,
626
+ [`${homeTeamKey}_7_5`]: 0,
627
+ [`${homeTeamKey}_7_6`]: 0,
628
+ [`${homeTeamKey}_8_0`]: 0,
629
+ [`${homeTeamKey}_8_1`]: 0,
630
+ [`${homeTeamKey}_8_2`]: 0,
631
+ [`${homeTeamKey}_8_3`]: 0,
632
+ [`${homeTeamKey}_8_4`]: 0,
633
+ [`${homeTeamKey}_8_5`]: 0,
634
+ [`${homeTeamKey}_8_6`]: 0,
635
+ [`${homeTeamKey}_8_7`]: 0,
636
+ [`${homeTeamKey}_9_0`]: 0,
637
+ [`${homeTeamKey}_9_1`]: 0,
638
+ [`${homeTeamKey}_9_2`]: 0,
639
+ [`${homeTeamKey}_9_3`]: 0,
640
+ [`${homeTeamKey}_9_4`]: 0,
641
+ [`${homeTeamKey}_9_5`]: 0,
642
+ [`${homeTeamKey}_9_6`]: 0,
643
+ [`${homeTeamKey}_9_7`]: 0,
644
+ [`${homeTeamKey}_9_8`]: 0,
645
+ [`${homeTeamKey}_10_0`]: 0,
646
+ [`${homeTeamKey}_10_1`]: 0,
647
+ [`${homeTeamKey}_10_2`]: 0,
648
+ [`${homeTeamKey}_10_3`]: 0,
649
+ [`${homeTeamKey}_10_4`]: 0,
650
+ [`${homeTeamKey}_10_5`]: 0,
651
+ [`${homeTeamKey}_10_6`]: 0,
652
+ [`${homeTeamKey}_10_7`]: 0,
653
+ [`${homeTeamKey}_10_8`]: 0,
654
+ [`${homeTeamKey}_10_9`]: 0,
655
+ [`${homeTeamKey}_11_0`]: 0,
656
+ [`${homeTeamKey}_11_1`]: 0,
657
+ [`${homeTeamKey}_11_2`]: 0,
658
+ [`${homeTeamKey}_11_3`]: 0,
659
+ [`${homeTeamKey}_11_4`]: 0,
660
+ [`${homeTeamKey}_11_5`]: 0,
661
+ [`${homeTeamKey}_11_6`]: 0,
662
+ [`${homeTeamKey}_11_7`]: 0,
663
+ [`${homeTeamKey}_11_8`]: 0,
664
+ [`${homeTeamKey}_11_9`]: 0,
665
+ [`${homeTeamKey}_11_10`]: 0,
666
+ [`${homeTeamKey}_12_0`]: 0,
667
+ [`${homeTeamKey}_12_1`]: 0,
668
+ [`${homeTeamKey}_12_2`]: 0,
669
+ [`${homeTeamKey}_12_3`]: 0,
670
+ [`${homeTeamKey}_12_4`]: 0,
671
+ [`${homeTeamKey}_12_5`]: 0,
672
+ [`${homeTeamKey}_12_6`]: 0,
673
+ [`${homeTeamKey}_12_7`]: 0,
674
+ [`${homeTeamKey}_12_8`]: 0,
675
+ [`${homeTeamKey}_12_9`]: 0,
676
+ [`${homeTeamKey}_12_10`]: 0,
677
+ [`${homeTeamKey}_12_11`]: 0,
678
+ [`${homeTeamKey}_13_0`]: 0,
679
+ [`${homeTeamKey}_13_1`]: 0,
680
+ [`${homeTeamKey}_13_2`]: 0,
681
+ [`${homeTeamKey}_13_3`]: 0,
682
+ [`${homeTeamKey}_13_4`]: 0,
683
+ [`${homeTeamKey}_13_5`]: 0,
684
+ [`${homeTeamKey}_13_6`]: 0,
685
+ [`${homeTeamKey}_13_7`]: 0,
686
+ [`${homeTeamKey}_13_8`]: 0,
687
+ [`${homeTeamKey}_13_9`]: 0,
688
+ [`${homeTeamKey}_13_10`]: 0,
689
+ [`${homeTeamKey}_13_11`]: 0,
690
+ [`${homeTeamKey}_13_12`]: 0,
691
+ [`${homeTeamKey}_14_0`]: 0,
692
+ [`${homeTeamKey}_14_1`]: 0,
693
+ [`${homeTeamKey}_14_2`]: 0,
694
+ [`${homeTeamKey}_14_3`]: 0,
695
+ [`${homeTeamKey}_14_4`]: 0,
696
+ [`${homeTeamKey}_14_5`]: 0,
697
+ [`${homeTeamKey}_14_6`]: 0,
698
+ [`${homeTeamKey}_14_7`]: 0,
699
+ [`${homeTeamKey}_14_8`]: 0,
700
+ [`${homeTeamKey}_14_9`]: 0,
701
+ [`${homeTeamKey}_14_10`]: 0,
702
+ [`${homeTeamKey}_14_11`]: 0,
703
+ [`${homeTeamKey}_14_12`]: 0,
704
+ [`${homeTeamKey}_14_13`]: 0,
705
+ [`${awayTeamKey}_5_0`]: 0,
706
+ [`${awayTeamKey}_5_1`]: 0,
707
+ [`${awayTeamKey}_5_2`]: 0,
708
+ [`${awayTeamKey}_5_3`]: 0,
709
+ [`${awayTeamKey}_5_4`]: 0,
710
+ [`${awayTeamKey}_6_0`]: 0,
711
+ [`${awayTeamKey}_6_1`]: 0,
712
+ [`${awayTeamKey}_6_2`]: 0,
713
+ [`${awayTeamKey}_6_3`]: 0,
714
+ [`${awayTeamKey}_6_4`]: 0,
715
+ [`${awayTeamKey}_6_5`]: 0,
716
+ [`${awayTeamKey}_7_0`]: 0,
717
+ [`${awayTeamKey}_7_1`]: 0,
718
+ [`${awayTeamKey}_7_2`]: 0,
719
+ [`${awayTeamKey}_7_3`]: 0,
720
+ [`${awayTeamKey}_7_4`]: 0,
721
+ [`${awayTeamKey}_7_5`]: 0,
722
+ [`${awayTeamKey}_7_6`]: 0,
723
+ [`${awayTeamKey}_8_0`]: 0,
724
+ [`${awayTeamKey}_8_1`]: 0,
725
+ [`${awayTeamKey}_8_2`]: 0,
726
+ [`${awayTeamKey}_8_3`]: 0,
727
+ [`${awayTeamKey}_8_4`]: 0,
728
+ [`${awayTeamKey}_8_5`]: 0,
729
+ [`${awayTeamKey}_8_6`]: 0,
730
+ [`${awayTeamKey}_8_7`]: 0,
731
+ [`${awayTeamKey}_9_0`]: 0,
732
+ [`${awayTeamKey}_9_1`]: 0,
733
+ [`${awayTeamKey}_9_2`]: 0,
734
+ [`${awayTeamKey}_9_3`]: 0,
735
+ [`${awayTeamKey}_9_4`]: 0,
736
+ [`${awayTeamKey}_9_5`]: 0,
737
+ [`${awayTeamKey}_9_6`]: 0,
738
+ [`${awayTeamKey}_9_7`]: 0,
739
+ [`${awayTeamKey}_9_8`]: 0,
740
+ [`${awayTeamKey}_10_0`]: 0,
741
+ [`${awayTeamKey}_10_1`]: 0,
742
+ [`${awayTeamKey}_10_2`]: 0,
743
+ [`${awayTeamKey}_10_3`]: 0,
744
+ [`${awayTeamKey}_10_4`]: 0,
745
+ [`${awayTeamKey}_10_5`]: 0,
746
+ [`${awayTeamKey}_10_6`]: 0,
747
+ [`${awayTeamKey}_10_7`]: 0,
748
+ [`${awayTeamKey}_10_8`]: 0,
749
+ [`${awayTeamKey}_10_9`]: 0,
750
+ [`${awayTeamKey}_11_0`]: 0,
751
+ [`${awayTeamKey}_11_1`]: 0,
752
+ [`${awayTeamKey}_11_2`]: 0,
753
+ [`${awayTeamKey}_11_3`]: 0,
754
+ [`${awayTeamKey}_11_4`]: 0,
755
+ [`${awayTeamKey}_11_5`]: 0,
756
+ [`${awayTeamKey}_11_6`]: 0,
757
+ [`${awayTeamKey}_11_7`]: 0,
758
+ [`${awayTeamKey}_11_8`]: 0,
759
+ [`${awayTeamKey}_11_9`]: 0,
760
+ [`${awayTeamKey}_11_10`]: 0,
761
+ [`${awayTeamKey}_12_0`]: 0,
762
+ [`${awayTeamKey}_12_1`]: 0,
763
+ [`${awayTeamKey}_12_2`]: 0,
764
+ [`${awayTeamKey}_12_3`]: 0,
765
+ [`${awayTeamKey}_12_4`]: 0,
766
+ [`${awayTeamKey}_12_5`]: 0,
767
+ [`${awayTeamKey}_12_6`]: 0,
768
+ [`${awayTeamKey}_12_7`]: 0,
769
+ [`${awayTeamKey}_12_8`]: 0,
770
+ [`${awayTeamKey}_12_9`]: 0,
771
+ [`${awayTeamKey}_12_10`]: 0,
772
+ [`${awayTeamKey}_12_11`]: 0,
773
+ [`${awayTeamKey}_13_0`]: 0,
774
+ [`${awayTeamKey}_13_1`]: 0,
775
+ [`${awayTeamKey}_13_2`]: 0,
776
+ [`${awayTeamKey}_13_3`]: 0,
777
+ [`${awayTeamKey}_13_4`]: 0,
778
+ [`${awayTeamKey}_13_5`]: 0,
779
+ [`${awayTeamKey}_13_6`]: 0,
780
+ [`${awayTeamKey}_13_7`]: 0,
781
+ [`${awayTeamKey}_13_8`]: 0,
782
+ [`${awayTeamKey}_13_9`]: 0,
783
+ [`${awayTeamKey}_13_10`]: 0,
784
+ [`${awayTeamKey}_13_11`]: 0,
785
+ [`${awayTeamKey}_13_12`]: 0,
786
+ [`${awayTeamKey}_14_0`]: 0,
787
+ [`${awayTeamKey}_14_1`]: 0,
788
+ [`${awayTeamKey}_14_2`]: 0,
789
+ [`${awayTeamKey}_14_3`]: 0,
790
+ [`${awayTeamKey}_14_4`]: 0,
791
+ [`${awayTeamKey}_14_5`]: 0,
792
+ [`${awayTeamKey}_14_6`]: 0,
793
+ [`${awayTeamKey}_14_7`]: 0,
794
+ [`${awayTeamKey}_14_8`]: 0,
795
+ [`${awayTeamKey}_14_9`]: 0,
796
+ [`${awayTeamKey}_14_10`]: 0,
797
+ [`${awayTeamKey}_14_11`]: 0,
798
+ [`${awayTeamKey}_14_12`]: 0,
799
+ [`${awayTeamKey}_14_13`]: 0,
800
+ other: 0,
801
+ };
578
802
 
579
- if (allOddsAreZero) {
580
- return [];
581
- }
803
+ // Populate the oddsMap with the odds from this typeId's odds
804
+ odds.forEach((odd: any) => {
805
+ const normalizedSelection = `${odd.selection.toLowerCase().replace(/\s+/g, '_')}_${normalizeScoreLine(
806
+ odd.selectionLine
807
+ )}`;
808
+ if (oddsMap.hasOwnProperty(normalizedSelection)) {
809
+ oddsMap[normalizedSelection] = odd.price;
810
+ }
811
+ });
582
812
 
583
- const positionNames = Object.keys(oddsMap);
813
+ const allOddsAreZero = Object.values(oddsMap).every((odd) => odd === ZERO);
814
+
815
+ if (!allOddsAreZero) {
816
+ const positionNames = Object.keys(oddsMap);
817
+
818
+ // Create a market object for this typeId
819
+ const marketObject = {
820
+ homeTeam: commonData.homeTeam,
821
+ awayTeam: commonData.awayTeam,
822
+ line: 0,
823
+ positionNames: positionNames,
824
+ odds: Object.values(oddsMap),
825
+ type: odds?.[0]?.type ? odds[0].type : 'Correct Score',
826
+ typeId: Number(typeId),
827
+ sportId: odds?.[0]?.sportId ? odds[0].sportId : undefined,
828
+ };
829
+ marketObjects.push(marketObject);
830
+ }
831
+ });
584
832
 
585
- // Create the market object
586
- const marketObject = {
587
- homeTeam: commonData.homeTeam,
588
- awayTeam: commonData.awayTeam,
589
- line: 0,
590
- positionNames: positionNames,
591
- odds: Object.values(oddsMap),
592
- type: 'Correct Score',
593
- typeId: 10100,
594
- };
595
- return [marketObject];
833
+ return marketObjects;
596
834
  };
597
835
 
598
836
  /**
@@ -60,26 +60,27 @@ export const detectCompletedPeriods = (
60
60
  periodScores[`period${periodNum}`] = { home: homeScore, away: awayScore };
61
61
 
62
62
  // Period is complete if:
63
- // 1. Next period exists in periods data, OR
64
- // 2. Game is completed, OR
65
- // 3. Game is live with numeric period AND current live period is greater than this period, OR
66
- // 4. Game is in overtime (all regulation periods are complete)
67
- const nextPeriodKey = `period_${periodNum + 1}`;
63
+ // 1. Game is completed (status = completed/finished), OR
64
+ // 2. Game is live AND in_play.period is GREATER than this period, OR
65
+ // 3. Game is in overtime (all regulation periods are complete)
66
+ //
67
+ // Note: We do NOT check if next period exists in data, as OpticOdds may include
68
+ // future periods with scores (including zeros). Only in_play.period is
69
+ // the source of truth for live games.
68
70
  const isCompleted = status === 'completed' || status === 'complete' || status === 'finished';
69
- const hasNextPeriod = homePeriods[nextPeriodKey] !== undefined && awayPeriods[nextPeriodKey] !== undefined;
70
71
  const isCompletedInLiveGame = isLive && currentLivePeriod !== null && currentLivePeriod > periodNum;
71
72
 
72
- if (hasNextPeriod || isCompleted || isCompletedInLiveGame || isInOvertime) {
73
+ if (isCompleted || isCompletedInLiveGame || isInOvertime) {
73
74
  completedPeriods.push(periodNum);
74
75
  }
75
76
  }
76
77
  }
77
78
 
78
79
  // Determine current period
79
- // If we have a numeric in_play period and it's greater than highest period in data, use it
80
+ // For live games with numeric in_play period, use that as the authoritative current period
80
81
  // Otherwise use highest period number from the data
81
82
  const highestPeriodInData = periodKeys.length > 0 ? Math.max(...periodKeys) : undefined;
82
- const currentPeriod = currentLivePeriod && currentLivePeriod > (highestPeriodInData || 0)
83
+ const currentPeriod = isLive && currentLivePeriod !== null
83
84
  ? currentLivePeriod
84
85
  : highestPeriodInData;
85
86
 
package/webpack.config.js CHANGED
@@ -17,8 +17,14 @@ module.exports = {
17
17
  output: {
18
18
  filename: 'main.js',
19
19
  path: path.resolve(__dirname),
20
- library: 'thalesUtils',
21
- libraryTarget: 'umd',
20
+ library: {
21
+ name: 'thalesUtils',
22
+ type: 'umd',
23
+ },
22
24
  globalObject: 'this',
23
25
  },
26
+ optimization: {
27
+ usedExports: false,
28
+ sideEffects: false,
29
+ },
24
30
  };