Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Record match event and partnership #149

Merged
merged 6 commits into from
Dec 6, 2024
Merged

Conversation

cp-sidhdhi-p
Copy link
Collaborator

@cp-sidhdhi-p cp-sidhdhi-p commented Dec 5, 2024

Record Match Event and Partnership

Test steps:

Add Match and start scoring.
get Id from database and apply filter with match_id in database.
check entry as per type in database as you add or undo any major event.

  • four/six/single wicket: single entry in database
  • double wicket: added to previous wicket's event-entry with type wicket only.
  • triple or more wicket: added to previous wicket's event-entry with type hat-trick.
  • century/fifty: recorded at the ball when any batsman completes it's milestone, fifty and century of a batman recorded into single event.
  • partnership: combine run of both batsman should be 50 or more, at the wicket of any batsman, partnership will be recorded.

Note:

while this data isn't used in UI right now, we'll incorporate it into designs soon.

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced new data models for match events and partnerships, enhancing tracking capabilities.
    • Added comprehensive statistics for overs, including maiden overs and runs.
    • Integrated match events and partnerships into the score tracking system.
    • Added functionality for managing match events in Firestore.
    • Introduced a service for managing partnerships in Firestore.
  • Improvements

    • Streamlined methods for adding and managing ball scores.
    • Enhanced error handling across services for better reliability.
    • Improved clarity in match completion handling and error feedback in the UI.
    • Updated the scoreboard to handle match events and partnerships more effectively.
  • Bug Fixes

    • Resolved issues with document referencing in Firestore for ball scores.
  • Documentation

    • Updated documentation to reflect new models and services for better developer guidance.

Copy link

coderabbitai bot commented Dec 5, 2024

Walkthrough

This pull request introduces significant enhancements across multiple files related to sports data modeling and management. Key changes include the addition of new data models for match events and partnerships, improvements to existing ball score logic, and the introduction of services for managing these entities in Firestore. New computed properties and methods have been added to facilitate detailed statistics tracking, while existing methods have been refined for better clarity and efficiency. Overall, the changes aim to improve the functionality and integration of match scoring and event tracking within the application.

Changes

File Path Change Summary
data/lib/api/ball_score/ball_score_model.dart - Renamed extension BallScoreModelBoolean to BallScoreModelData.
- Added method formattedOver.
- Enhanced OverSummary with new computed properties: isMaiden, overCount, legalDeliveriesCount, runs, extras, wickets.
- Updated addBall and removeBall methods for better state management.
- Modified BowlerSummary and BatsmanSummary for ball management.
- Updated ExtraSummary for extras handling.
data/lib/api/match_event/match_event_model.dart - Added MatchEventModel, EventType, MatchEventWicket, and MatchEventMilestone classes with JSON serialization.
data/lib/api/match_event/match_event_model.freezed.dart - Generated code for MatchEventModel, MatchEventWicket, and MatchEventMilestone with serialization methods.
data/lib/api/match_event/match_event_model.g.dart - Added serialization and deserialization logic for match event entities.
data/lib/api/partnership/partnership_model.dart - Introduced PartnershipModel and PartnershipPlayer classes with JSON serialization.
data/lib/api/partnership/partnership_model.freezed.dart - Generated code for PartnershipModel and PartnershipPlayer with serialization capabilities.
data/lib/api/partnership/partnership_model.g.dart - Added serialization and deserialization logic for partnership models.
data/lib/service/ball_score/ball_score_service.dart - Updated addBallScoreAndUpdateTeamDetails to reference existing documents.
- Simplified overCount calculation.
- Streamlined document setting logic.
data/lib/service/match_event/match_event_service.dart - Introduced MatchEventService class for managing match events in Firestore with various CRUD operations.
data/lib/service/partnership/partnership_service.dart - Introduced PartnershipService class for managing partnerships in Firestore with CRUD operations.
data/lib/utils/constant/firestore_constant.dart - Added constants for matchEventsCollection and partnershipsCollection.
khelo/lib/ui/flow/score_board/score_board_view_model.dart - Enhanced ScoreBoardViewNotifier with new dependencies and methods for managing match events and partnerships.

Possibly related PRs

Suggested reviewers

  • cp-mayank

🐰 In the meadow, where scores do play,
A model blooms, brightening the day.
Events and partnerships dance in delight,
With each ball bowled, the stats take flight.
From Firestore's depths, we gather the cheer,
For cricket's grand tale, we hold so dear! 🎉


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@cp-sidhdhi-p cp-sidhdhi-p marked this pull request as ready for review December 5, 2024 05:24
# Conflicts:
#	khelo/lib/ui/flow/score_board/score_board_view_model.dart
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Outside diff range and nitpick comments (11)
data/lib/service/match_event/match_event_service.dart (2)

29-31: Simplify asyncMap to map in streamEventsByMatches

Since the asyncMap does not perform any asynchronous operations, you can simplify it by using map instead.

Apply this diff to simplify the code:

-    .snapshots()
-    .asyncMap((snapshot) async {
+    .snapshots()
+    .map((snapshot) {
       return snapshot.docs.map((mainDoc) => mainDoc.data()).toList();
     })

43-44: Consider logging errors for better debugging

Currently, errors are being converted to AppError without logging. Adding logging statements for errors and stack traces can facilitate debugging and improve maintainability.

You might add a logging statement like:

// Before throwing the error
print('Error updating match event: $error\nStack trace: $stack');
data/lib/service/partnership/partnership_service.dart (2)

43-45: Simplify asyncMap to map in streamPartnershipByMatches

The asyncMap does not perform any asynchronous operations. You can simplify it by using map instead.

Apply this diff to simplify the code:

-    .snapshots()
-    .asyncMap((snapshot) async {
+    .snapshots()
+    .map((snapshot) {
       return snapshot.docs.map((mainDoc) => mainDoc.data()).toList();
     })

51-52: Consider logging errors for better debugging

Errors are being converted to AppError without any logging. Adding logs for errors and stack traces can help with debugging issues in production.

You might add a logging statement like:

// Before throwing the error
print('Error deleting partnership: $error\nStack trace: $stack');
data/lib/api/match_event/match_event_model.dart (1)

42-53: Use lowerCamelCase for enum values

Enum values should be in lowerCamelCase to follow Dart naming conventions. For example, hatTrick instead of hatTrick.

Apply this diff to adjust the enum values:

 enum EventType {
-  hatTrick(1),
-  century(2),
-  fifty(3),
-  wicket(4),
-  six(5),
-  four(6);
+  hatTrick(1),
+  century(2),
+  fifty(3),
+  wicket(4),
+  six(5),
+  four(6);
data/lib/api/ball_score/ball_score_model.dart (3)

Line range hint 290-297: Avoid returning nullable boolean in isLegalDelivery

Returning null can lead to unnecessary null checks elsewhere. Consider returning false when this is null to simplify the method usage.

Apply this diff:

-  bool? isLegalDelivery() {
+  bool isLegalDelivery() {
     if (this == null) {
-      return null;
+      return false;
     }
     return this!.extras_type != ExtrasType.penaltyRun &&
         this!.extras_type != ExtrasType.noBall &&

Line range hint 305-309: Refine isMaiden logic to handle overs with extra deliveries

The current isMaiden logic assumes the last ball number is 6 and a legal delivery. This may not account for overs with extra deliveries due to wides or no-balls. Consider summing legal deliveries to determine the end of an over.

You might revise the condition to:

bool get isMaiden =>
    runs == 0 &&
    wickets == 0 &&
    extras == 0 &&
    legalDeliveriesCount == 6;

Line range hint 325-328: Ensure legalDeliveriesCount is not zero to avoid division by zero

In the overCount getter, dividing by zero can occur if legalDeliveriesCount is zero. Add a check to prevent runtime errors.

Consider adding:

if (legalDeliveriesCount == 0) {
  return 0.0;
}
data/lib/api/match_event/match_event_model.freezed.dart (1)

1-985: Consider excluding generated code from version control

Including generated files such as match_event_model.freezed.dart in version control can lead to merge conflicts and increase repository size. It's generally recommended to exclude generated files from version control and generate them during the build process.

khelo/lib/ui/flow/score_board/score_board_view_model.dart (1)

844-908: Consider recording all partnerships, not just those exceeding 50 runs

The current implementation only records partnerships when totalRuns > 50. In cricket, all partnerships are usually recorded regardless of the number of runs scored. This provides a complete statistical record of the match. Consider modifying the code to record all partnerships.

data/lib/api/partnership/partnership_model.dart (1)

1-1: Typo in comment syntax

There is an extra space in the comment on line 1. It should be corrected to // ignore_for_file: non_constant_identifier_names without a space between the slashes.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 1bf099e and 2fe641f.

📒 Files selected for processing (12)
  • data/lib/api/ball_score/ball_score_model.dart (1 hunks)
  • data/lib/api/match_event/match_event_model.dart (1 hunks)
  • data/lib/api/match_event/match_event_model.freezed.dart (1 hunks)
  • data/lib/api/match_event/match_event_model.g.dart (1 hunks)
  • data/lib/api/partnership/partnership_model.dart (1 hunks)
  • data/lib/api/partnership/partnership_model.freezed.dart (1 hunks)
  • data/lib/api/partnership/partnership_model.g.dart (1 hunks)
  • data/lib/service/ball_score/ball_score_service.dart (2 hunks)
  • data/lib/service/match_event/match_event_service.dart (1 hunks)
  • data/lib/service/partnership/partnership_service.dart (1 hunks)
  • data/lib/utils/constant/firestore_constant.dart (1 hunks)
  • khelo/lib/ui/flow/score_board/score_board_view_model.dart (8 hunks)
✅ Files skipped from review due to trivial changes (2)
  • data/lib/api/partnership/partnership_model.g.dart
  • data/lib/api/match_event/match_event_model.g.dart
🔇 Additional comments (8)
data/lib/service/partnership/partnership_service.dart (1)

30-31: Verify the use of partnershipRef.id when updating

In the updatePartnership method, you replace partnership.id with partnershipRef.id. Ensure this is intentional, as it might overwrite the original id of the partnership.

Confirm whether the id should remain the same or be updated to partnershipRef.id.

data/lib/api/match_event/match_event_model.dart (1)

25-27: Verify the data type of over field

The over field represents an over number and is currently a double. Ensure that this appropriately captures over fractions and consider using a more precise type if necessary.

Confirm that using double does not introduce precision issues in calculations.

data/lib/api/partnership/partnership_model.freezed.dart (1)

1-619: No issues found in the generated code

This is a generated file (.freezed.dart). No manual changes are required.

data/lib/api/ball_score/ball_score_model.dart (1)

289-289: Potential issue in formattedOver calculation

The formattedOver getter subtracts 1 from over_number. Verify if this accurately represents the over count, as over numbering generally starts from 0 or 1. Also, ensure that string interpolation handles null values correctly.

data/lib/utils/constant/firestore_constant.dart (1)

13-14: LGTM! Verify collection usage across the codebase.

The new collection constants follow the established naming convention and are properly placed with other collection constants.

Let's verify these collections are properly used across the codebase:

✅ Verification successful

Let me check the actual usage of these collections by examining the implementation details.


Let me check for any match events service implementation since we only see the constant definition but no usage.


LGTM! Both collections are properly implemented and used in the codebase.

The verification shows that:

  • The partnerships collection is properly used in PartnershipService for data access and ScoreBoardViewNotifier for managing partnerships data
  • The match_events collection is properly implemented in MatchEventService with proper model conversion and is used in ScoreBoardViewNotifier for tracking match events like wickets, milestones, etc.
  • Both collections follow Firestore best practices with proper type conversion and collection naming
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for proper usage of the new collections
# Expected: Find references in service classes and models

# Check for match_events collection usage
echo "Checking match_events collection usage:"
rg -l "match_events" --type dart

# Check for partnerships collection usage
echo "Checking partnerships collection usage:"
rg -l "partnerships" --type dart

Length of output: 451


Script:

#!/bin/bash
# Check the implementation details of match_events collection usage
echo "=== Checking match_events collection implementation ==="
rg "match_events" --type dart -C 3

# Check the implementation details of partnerships collection usage
echo "=== Checking partnerships collection implementation ==="
rg "partnerships" --type dart -C 3

Length of output: 4336


Script:

#!/bin/bash
# Search for match events related service files and implementations
echo "=== Searching for match events service files ==="
fd "match.*event.*service" --type f

echo "=== Searching for match event model usage ==="
rg "MatchEventModel" --type dart -C 3

Length of output: 25487

data/lib/service/ball_score/ball_score_service.dart (3)

Line range hint 61-96: LGTM! Transaction scope and error handling are well-implemented

The transaction appropriately handles atomic updates across multiple entities (match, innings, and ball score) with proper error handling using AppError.fromError.


63-63: Review transaction handling and over calculation

The changes improve the code by:

  1. Using formattedOver property for cleaner over calculation
  2. Using SetOptions(merge: true) for safer concurrent updates

However, we should verify the implementation of formattedOver to ensure it handles all edge cases.

Let's verify the formattedOver implementation:

Also applies to: 91-91


61-61: Verify unique ID generation for ball scores

The change from generating a new document ID to using score.id could lead to document overwrites if the IDs are not guaranteed to be unique.

Let's verify the ID generation logic:

khelo/lib/ui/flow/score_board/score_board_view_model.dart Outdated Show resolved Hide resolved
khelo/lib/ui/flow/score_board/score_board_view_model.dart Outdated Show resolved Hide resolved
@canopas canopas deleted a comment from coderabbitai bot Dec 5, 2024
@canopas canopas deleted a comment from coderabbitai bot Dec 5, 2024
@canopas canopas deleted a comment from coderabbitai bot Dec 5, 2024
@canopas canopas deleted a comment from coderabbitai bot Dec 5, 2024
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (8)
data/lib/api/ball_score/ball_score_model.dart (5)

226-228: Consider caching computed properties and adding documentation for cricket-specific logic.

The computed properties (isMaiden, overCount, legalDeliveriesCount, etc.) are recalculated on every access, which could impact performance when accessed frequently.

Consider:

  1. Caching the results using late variables that are invalidated when the ball list changes
  2. Adding documentation explaining cricket-specific rules and edge cases

Example implementation:

+ /// Cached values for frequently accessed properties
+ late final bool _isMaiden = _calculateIsMaiden();
+ late final int _legalDeliveriesCount = _calculateLegalDeliveriesCount();

- bool get isMaiden =>
-     runs == 0 &&
-     wickets == 0 &&
-     extras == 0 &&
-     balls.lastOrNull?.ball_number == 6 &&
-     (balls.lastOrNull?.isLegalDelivery() ?? false);
+ /// Returns true if the over is a maiden (no runs scored off the bat, no extras, and six legal deliveries)
+ bool get isMaiden => _isMaiden;

Also applies to: 246-248, 250-252, 254-256, 258-261, 263-266


Line range hint 446-448: Handle division by zero in economy calculation.

The economy calculation could throw an exception if overDelivered is 0.

Apply this fix:

-    return double.parse((runsConceded / overDelivered).toStringAsFixed(1));
+    return overDelivered > 0 
+        ? double.parse((runsConceded / overDelivered).toStringAsFixed(1))
+        : 0.0;

Line range hint 574-576: Handle division by zero in strike rate calculation.

The strike rate calculation could throw an exception if ballFaced is 0.

Apply this fix:

-    return double.parse(((runs / ballFaced) * 100).toStringAsFixed(1));
+    return ballFaced > 0 
+        ? double.parse(((runs / ballFaced) * 100).toStringAsFixed(1))
+        : 0.0;

Line range hint 669-694: Consider using a map lookup instead of switch statement.

The current implementation using switch statements is verbose and requires updating two places (add and remove) when adding new extra types.

Consider using a map-based approach:

+ static final _extraTypeToProperty = {
+   ExtrasType.wide: (ExtraSummary e) => e.wideBall,
+   ExtrasType.noBall: (ExtraSummary e) => e.noBall,
+   ExtrasType.bye: (ExtraSummary e) => e.bye,
+   ExtrasType.legBye: (ExtraSummary e) => e.legBye,
+   ExtrasType.penaltyRun: (ExtraSummary e) => e.penalty,
+ };

  ExtraSummary addExtra(BallScoreModel ball) {
    if (ball.extras_type == null) return this;
-   final ExtraSummary extra;
-   switch (ball.extras_type!) {
-     case ExtrasType.wide:
-       extra = copyWith(wideBall: wideBall + (ball.extras_awarded ?? 0));
-     // ... other cases
-   }
+   final getter = _extraTypeToProperty[ball.extras_type!]!;
+   return copyWith(
+     wideBall: getter(this) + (ball.extras_awarded ?? 0)
+   );
  }

Line range hint 751-898: Optimize statistics calculation to reduce iterations.

The statistics calculation methods make multiple passes over the same data. Consider combining calculations to reduce iterations.

For example, in calculateBattingStats, combine the calculations:

- for (final element in this) {
-   if (element.batsman_id == currentUserId) {
-     runScored += element.runs_scored;
-     // ... other calculations
-   }
-   if (element.player_out_id == currentUserId) {
-     dismissal++;
-   }
- }

+ for (final element in this) {
+   if (element.batsman_id == currentUserId || 
+       element.player_out_id == currentUserId) {
+     if (element.batsman_id == currentUserId) {
+       runScored += element.runs_scored;
+       // ... other calculations
+     }
+     if (element.player_out_id == currentUserId) {
+       dismissal++;
+     }
+   }
+ }
khelo/lib/ui/flow/score_board/score_board_view_model.dart (3)

846-905: Consider tracking all partnerships

The current implementation only records partnerships that exceed 50 runs. This could miss important partnerships that end just before 50 runs or partnerships that were crucial to the match outcome despite being lower scoring.

Consider:

  1. Tracking all partnerships
  2. Adding a partnership_milestone field to flag significant partnerships (e.g., 50+, 100+)
  3. Adding partnership rate (runs per ball) for better analysis
-    if (totalRuns > 50) {
+    // Record all partnerships with milestone flags
+    final partnership = PartnershipModel(
+      id: _partnershipService.generatePartnershipId,
+      match_id: ball.match_id,
+      inning_id: ball.inning_id,
+      player_ids: batsMen,
+      players: player,
+      runs: totalRuns,
+      extras: extras,
+      ball_faced: ballFaced,
+      start_over: scores.first.formattedOver,
+      end_over: scores.last.formattedOver,
+      run_rate: ballFaced > 0 ? (totalRuns * 6) / ballFaced : 0,
+      milestone: totalRuns >= 100 ? "century" : totalRuns >= 50 ? "fifty" : null
+    );

180-194: Consider centralizing error handling

Multiple methods have similar error handling patterns. Consider creating a centralized error handling mechanism to reduce code duplication and ensure consistent error handling across the codebase.

Example implementation:

Future<T> handleServiceError<T>(String operation, Future<T> Function() action) async {
  try {
    return await action();
  } catch (e) {
    debugPrint("ScoreBoardViewNotifier: error while $operation -> $e");
    state = state.copyWith(error: AppError.fromError(e));
    throw e;
  }
}

// Usage:
void _loadMatchEvent() async {
  await handleServiceError('loading match event', () async {
    if (matchId == null) return;
    _matchEventSubscription?.cancel();
    return _matchEventService
        .streamEventsByMatches(matchId!)
        .listen((events) => matchEvents = events);
  });
}

Also applies to: 196-211, 1317-1329


Line range hint 40-57: Consider breaking down the ScoreBoardViewNotifier

The class has grown to handle multiple responsibilities, making it harder to maintain and test. Consider splitting it into smaller, focused notifiers or services.

Suggested architecture:

  1. ScoringNotifier: Core scoring logic
  2. MatchEventNotifier: Event tracking
  3. PartnershipNotifier: Partnership tracking
  4. PlayerStatsNotifier: Player statistics

This would improve:

  • Code organization
  • Testability
  • Maintainability
  • State management
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 2fe641f and 62557d1.

📒 Files selected for processing (4)
  • data/lib/api/ball_score/ball_score_model.dart (1 hunks)
  • data/lib/utils/constant/firestore_constant.dart (1 hunks)
  • khelo/lib/ui/flow/score_board/score_board_screen.dart (2 hunks)
  • khelo/lib/ui/flow/score_board/score_board_view_model.dart (13 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • data/lib/utils/constant/firestore_constant.dart
🔇 Additional comments (7)
khelo/lib/ui/flow/score_board/score_board_screen.dart (2)

278-278: LGTM! More explicit match status handling

The change from endMatch() to endMatchWithStatus(MatchStatus.finish) improves code clarity by making the final match status explicit.


664-664: LGTM! Consistent match status handling

The change to use endMatchWithStatus(MatchStatus.abandoned) maintains consistency with the new explicit match status handling approach.

khelo/lib/ui/flow/score_board/score_board_view_model.dart (5)

51-52: LGTM! Proper stream management

The stream subscriptions for match events and partnerships are properly initialized and cleaned up in the dispose method.

Also applies to: 1911-1912


Line range hint 1501-1539: LGTM! Comprehensive match completion handling

The endMatchWithStatus method properly:

  1. Updates player statistics
  2. Finalizes partnerships
  3. Updates match status
  4. Cleans up state

1272-1276: ⚠️ Potential issue

Missing await before async call

The call to _matchEventService.updateMatchEvent is missing an await, which could lead to race conditions.


180-194: ⚠️ Potential issue

Improve error handling in _loadMatchEvent

The error handling only logs errors but doesn't update the state or notify the user. This could lead to silent failures.

Consider updating the state with the error:

 void _loadMatchEvent() {
   try {
     if (matchId == null) return;
     _matchEventSubscription?.cancel();
     _matchEventSubscription = _matchEventService
         .streamEventsByMatches(matchId!)
         .listen((events) => matchEvents = events, onError: (e) {
       debugPrint(
           "ScoreBoardViewNotifier: error while loading match event -> $e");
+      state = state.copyWith(error: AppError.fromError(e));
     });
   } catch (e) {
     debugPrint(
         "ScoreBoardViewNotifier: error while loading match event -> $e");
+    state = state.copyWith(error: AppError.fromError(e));
   }
 }

Likely invalid or redundant comment.


752-797: ⚠️ Potential issue

Fix incorrect hat-trick detection logic

The current implementation incorrectly marks multiple wickets as a hat-trick without verifying they occurred in consecutive deliveries.

Consider this fix:

 Future<void> handleWicketMatchEvent(BallScoreModel ball) async {
-  final lastBall = state.currentScoresList.lastWhereOrNull(
+  final lastThreeBalls = state.currentScoresList.where(
     (ball) =>
         ball.wicket_type != WicketType.retired &&
         ball.wicket_type != WicketType.retiredHurt &&
         ball.wicket_type != WicketType.timedOut,
-  );
+  ).toList().reversed.take(3).toList();
   
   MatchEventModel matchEvent;
-  if (lastBall?.wicket_type != null &&
-      lastBall?.bowler_id == ball.bowler_id) {
+  if (lastThreeBalls.length == 3 &&
+      lastThreeBalls.every((b) => b.bowler_id == ball.bowler_id) &&
+      _areConsecutiveDeliveries(lastThreeBalls)) {
     matchEvent = matchEvents
             .where((element) =>
                 (element.type == EventType.wicket ||
                     element.type == EventType.hatTrick) &&
                 element.bowler_id == ball.bowler_id &&
-                element.ball_ids.contains(lastBall?.id))
+                element.ball_ids.contains(lastThreeBalls.last.id))
             .firstOrNull ??
         MatchEventModel(
             id: _matchEventService.generateMatchEventId,
             match_id: ball.match_id,
             inning_id: ball.inning_id,
             type: EventType.wicket,
             bowler_id: ball.bowler_id,
             time: ball.score_time ?? DateTime.now());
   } else {
     // ... rest of the code
   }
 }

+bool _areConsecutiveDeliveries(List<BallScoreModel> balls) {
+  for (int i = 0; i < balls.length - 1; i++) {
+    if (!_isNextDelivery(balls[i], balls[i + 1])) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool _isNextDelivery(BallScoreModel current, BallScoreModel next) {
+  if (current.over_number == next.over_number) {
+    return current.ball_number == next.ball_number + 1;
+  } else if (current.over_number == next.over_number + 1) {
+    return current.ball_number == 1 && next.ball_number == 6;
+  }
+  return false;
+}

Likely invalid or redundant comment.

@canopas canopas deleted a comment from coderabbitai bot Dec 5, 2024
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (3)
khelo/lib/ui/flow/score_board/score_board_view_model.dart (3)

704-731: Add documentation for match event handling

The function handles different types of match events well, but would benefit from documentation explaining:

  • Purpose and responsibility of the function
  • Different event types handled
  • Parameters and their usage

Add documentation like:

+  /// Tracks match events like boundaries, wickets and milestones.
+  /// 
+  /// Takes a [BallScoreModel] and creates/updates corresponding match events:
+  /// - Boundaries (four/six)
+  /// - Wickets (single/hat-trick)
+  /// - Batting milestones (fifty/century)
   Future<void> addMatchEventIfNeeded(BallScoreModel ball) async {

733-778: Consider breaking down wicket event handling

The wicket event handling logic is complex and would benefit from being split into smaller, focused functions for better maintainability.

Consider refactoring into smaller functions:

  Future<void> handleWicketMatchEvent(BallScoreModel ball) async {
+   final lastWicketBall = _getLastWicketBall();
+   final existingEvent = _findExistingWicketEvent(ball, lastWicketBall);
+   final updatedEvent = _createOrUpdateWicketEvent(ball, existingEvent);
+   await _matchEventService.updateMatchEvent(updatedEvent);
  }

+ BallScoreModel? _getLastWicketBall() {
+   return state.currentScoresList.lastWhereOrNull(
+     (ball) =>
+       ball.wicket_type != WicketType.retired &&
+       ball.wicket_type != WicketType.retiredHurt &&
+       ball.wicket_type != WicketType.timedOut,
+   );
+ }

1239-1310: Enhance error handling in undo operations

While the undo operations are comprehensive, they could benefit from better error handling and recovery mechanisms.

Consider adding transaction-like behavior:

  Future<void> undoMatchEventIfNeeded(BallScoreModel ball) async {
+   try {
      final events =
          matchEvents.where((element) => element.ball_ids.contains(ball.id));
+     List<Future> operations = [];

      for (final event in events) {
        if (event.type == EventType.six || event.type == EventType.four) {
-         await _matchEventService.deleteMatchEvent(event.id);
+         operations.add(_matchEventService.deleteMatchEvent(event.id));
        } else if (event.type == EventType.hatTrick ||
            event.type == EventType.wicket) {
          // ... existing code ...
        }
      }
+     await Future.wait(operations);
+   } catch (e) {
+     debugPrint("Error during match event undo: $e");
+     // Consider adding recovery mechanism or state rollback
+     rethrow;
+   }
  }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 62557d1 and 5bf694c.

📒 Files selected for processing (1)
  • khelo/lib/ui/flow/score_board/score_board_view_model.dart (13 hunks)
🔇 Additional comments (1)
khelo/lib/ui/flow/score_board/score_board_view_model.dart (1)

676-679: LGTM! Verify event tracking integration

The match event and partnership tracking is properly integrated into the ball scoring flow, with good error isolation.

✅ Verification successful

Let me analyze the integration points further by checking the implementation details of these methods.


Let me try a different approach using ripgrep to see the full implementation of these methods.


Let me try one last approach with simpler ripgrep patterns to see the method implementations.


Integration of match events and partnerships is properly implemented

The code shows correct implementation with:

  • addMatchEventIfNeeded: Records special events (fours, sixes, wickets) with proper error isolation
  • addMatchPartnershipIfNeeded: Tracks partnership stats between batsmen when wickets fall
  • Both methods are called in the right order within the ball scoring flow
  • Error handling is in place with try-catch blocks

The integration points and implementation details confirm that the match event and partnership tracking is correctly integrated into the scoring system.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the integration points for match events
rg -A 5 "addMatchEventIfNeeded|addMatchPartnershipIfNeeded" --type dart

Length of output: 3239


Script:

#!/bin/bash
# Check the implementation of addMatchEventIfNeeded and addMatchPartnershipIfNeeded
ast-grep --pattern $'Future<void> addMatchEventIfNeeded(BallScoreModel ball) async {
  $$$
}'

ast-grep --pattern $'Future<void> addMatchPartnershipIfNeeded(BallScoreModel ball) async {
  $$$
}'

Length of output: 195


Script:

#!/bin/bash
# Get the full implementation of both methods with more context
rg -U "Future<void> addMatchEventIfNeeded.*?\n}" --multiline --type dart -A 20
rg -U "Future<void> addMatchPartnershipIfNeeded.*?\n}" --multiline --type dart -A 20

Length of output: 167


Script:

#!/bin/bash
# Get method implementations with surrounding context
rg -B 2 -A 15 "^  Future<void> addMatchEventIfNeeded" --type dart
rg -B 2 -A 15 "^  Future<void> addMatchPartnershipIfNeeded" --type dart

Length of output: 3441

@canopas canopas deleted a comment from coderabbitai bot Dec 5, 2024
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (6)
khelo/lib/ui/flow/score_board/score_board_view_model.dart (4)

724-727: Ensure consistent error handling in asynchronous methods

In methods like addMatchEventIfNeeded (lines 724-727) and undoPartnerShipIfNeeded (lines 1296-1307), exceptions are caught and only logged using debugPrint. To prevent silent failures and enhance reliability, consider updating the state with the error or implementing proper error handling mechanisms.

Also applies to: 1296-1307


704-883: Consider adding unit tests for event handling methods

The methods dealing with match events and partnerships, such as addMatchEventIfNeeded, handleWicketMatchEvent, handleMilestonesMatchEvent, and addMatchPartnershipIfNeeded, are critical for the application's functionality. Adding unit tests for these methods would help ensure their correctness and robustness, and can catch potential issues early in the development process.


Line range hint 12-38: Avoid redundant null checks for non-nullable fields

In the _loadMatchSetting method, the matchId variable is already checked for nullity at the beginning. However, in later lines, matchId! is used without additional benefits. Since matchId cannot be null beyond the initial check, consider removing the unnecessary null assertion operators to improve code clarity.


Line range hint 676-883: Optimize performance by reducing redundant calculations

In the addMatchPartnershipIfNeeded method, the statistics for batsmen are recalculated multiple times within loops. Consider refactoring the code to compute these statistics once and reuse them, which can improve performance, especially with larger data sets.

data/lib/api/match_event/match_event_model.dart (2)

27-28: Maintain consistency in naming plural list properties

The MatchEventModel class has a property named milestone of type List<MatchEventMilestone>. To maintain consistency with other list properties like ball_ids and wickets, consider renaming milestone to milestones.


80-87: Specify default values for all fields in MatchEventMilestone

In the MatchEventMilestone class, some fields like over, runs, ball_faced, fours, and sixes have default values, while others like time and ball_id do not. For consistency and to prevent potential null errors, ensure that default values are specified for all fields where appropriate.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 5bf694c and 7fcb328.

📒 Files selected for processing (4)
  • data/lib/api/match_event/match_event_model.dart (1 hunks)
  • data/lib/api/match_event/match_event_model.freezed.dart (1 hunks)
  • data/lib/api/match_event/match_event_model.g.dart (1 hunks)
  • khelo/lib/ui/flow/score_board/score_board_view_model.dart (13 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • data/lib/api/match_event/match_event_model.g.dart
🔇 Additional comments (3)
data/lib/api/match_event/match_event_model.freezed.dart (1)

1-984: Generated code appears correct

This is an auto-generated file by the Freezed package. The generated code aligns with the model definitions and shows no issues.

khelo/lib/ui/flow/score_board/score_board_view_model.dart (2)

179-192: Handle exceptions appropriately in _loadMatchEventAndPartnership

In the onError callback of _loadMatchEventAndPartnership, the exception is only logged using debugPrint, but the error is not propagated or the state updated. This could lead to silent failures without informing the user. Consider updating the state with the error or handling it appropriately.


1889-1891: ⚠️ Potential issue

Ensure all subscriptions are properly cancelled

In the _cancelStreamSubscription method, the _matchSettingSubscription is cancelled, but the _matchEventSubscription is also used in the class. Ensure that _matchEventSubscription is cancelled as well to prevent memory leaks.

Apply this diff to fix the issue:

   _cancelStreamSubscription() async {
     await _matchStreamSubscription?.cancel();
     await _ballScoreStreamSubscription?.cancel();
     await _matchSettingSubscription?.cancel();
+    await _matchEventSubscription?.cancel();
     await _matchStreamController.close();
   }

Likely invalid or redundant comment.

@cp-sidhdhi-p cp-sidhdhi-p merged commit a757f40 into main Dec 6, 2024
2 checks passed
@cp-sidhdhi-p cp-sidhdhi-p deleted the sidhdhi/record-match-event branch December 6, 2024 04:22
This was referenced Dec 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants