problemhardood

Object-Oriented Design for Cricinfo

Problem

Design an object-oriented system for Cricinfo: a cricket-focused sports news site that stores match archives, provides live ball-by-ball coverage, supports player and team data, and generates global statistics and queries about players and matches.

The system must support all major match formats (ODI, T20, Test), allow administrators to create and update matches/tournaments/teams, and support commentators and administrators recording ball-by-ball details and commentary.

Cricinfo

Solution

1. Requirements Analysis

Functional requirements (inferred from the existing content):

  • Maintain a registry of teams, players, tournaments, stadiums, umpires, and referees.
  • Create, modify, and schedule tournaments and matches (ODI, T20, Test).
  • Support team squad announcements for tournaments and playing-eleven selection for each match.
  • Record ball-by-ball events (balls, overs, innings) and associate commentary with those events.
  • Store and compute statistics for players, matches, and tournaments, and answer global stat queries.
  • Allow administrators to add/update data; allow commentators to add live commentary.

Non-functional requirements:

  • The system must handle high write throughput for live matches (low-latency updates).
  • Data integrity for match events (ordering of balls and overs) must be preserved.
  • Support efficient querying for historical and aggregate statistics.

2. Use Case Diagram

Actors:

  • Admin (adds/modifies teams, tournaments, matches, records ball details)
  • Commentator (adds live commentary)

Use cases (high level): Add/modify teams and players; Add tournaments and matches; Record a ball; Add stadium/umpire/referee; Add/update stats; Add commentary.

graph TD
    subgraph "Cricinfo System"
        UC1(Add/modify teams & players)
        UC2(Add tournaments & matches)
        UC3(Record a ball)
        UC4(Add stadium / umpire / referee)
        UC5(Add / update stats)
        UC6(Add commentary)
    end
    Admin --> UC1
    Admin --> UC2
    Admin --> UC3
    Admin --> UC4
    Admin --> UC5
    Commentator --> UC6
    Commentator --> UC3

Cricinfo Use Case Diagram

3. Class Diagram

Core classes and responsibilities (derived from original notes):

  • Player: stores player profile and contracts.
  • Team: manages players, squads, and team-level news.
  • Tournament: manages tournament details and points table.
  • TournamentSquad: players announced for a tournament.
  • Playing11: playing eleven chosen for a match.
  • Match (abstract): common match metadata and operations; specialized by ODI/Test/T20.
  • Inning: represents an innings and its overs.
  • Over: collection of Ball objects.
  • Ball: records ball-by-ball event, runs, wicket info and linked commentary.
  • Commentary / Commentator: textual commentary attached to balls; commentator actor.
  • Umpire / Referee: officials for a match.
  • Stat / StatQuery: compute and answer aggregate/statistical queries.
classDiagram
    class Player {
        -Person person
        -List contracts
        +add_contract(contract)
    }
    class Team {
        -String name
        -List<Player> players
        -List news
        -Person coach
        +add_player(player)
        +add_tournament_squad(squad)
    }
    class Tournament {
        -String name
        -List matches
        -PointsTable points
    }
    class TournamentSquad {
        -List<Player> players
        +add_player(player)
    }
    class Playing11 {
        -List<Player> players
        -Player twelfth_man
    }
    class Match {
        -int number
        -Date start_time
        -MatchResult result
        -List<Team> teams
        -List<Inning> innings
        -List<Umpire> umpires
        -Referee referee
        +assign_stadium(stadium)
        +assign_referee(referee)
    }
    class ODI {
    }
    class Test {
    }
    class T20 {
    }
    class Inning {
        -int number
        -Date start_time
        -List<Over> overs
        +add_over(over)
    }
    class Over {
        -int number
        -List<Ball> balls
        +add_ball(ball)
    }
    class Ball {
        -Player bowler
        -Player batsman
        -BallType type
        -Wicket wicket
        -Run runs
        -Commentary commentary
    }
    class Commentary {
        -String text
        -Date created_at
        -Commentator created_by
    }
    class Umpire {
        -Person person
    }
    class Referee {
        -Person person
    }
    class Stat {
        -Map metrics
    }
    class StatQuery {
        +execute()
    }

    Match <|-- ODI
    Match <|-- Test
    Match <|-- T20
    Inning "1" -- "*" Over : contains
    Over "1" -- "*" Ball : contains
    Team "1" -- "*" Player : has

Cricinfo Class Diagram

4. Activity Diagrams

Activity: Record a ball of an over (happy path):

graph TD
    A[Start: Ball to be recorded] --> B{Is match active?}
    B -- No --> Z[Reject / Queue update]
    B -- Yes --> C[Identify current Inning & Over]
    C --> D[Create Ball event]
    D --> E[Attach runs/wicket/commentary]
    E --> F[Persist Ball and update Over/Inning state]
    F --> G[Update live viewers / stats]
    G --> H[End]

Cricinfo Activity Diagram

5. High-Level Code Implementation

Below are concise skeletons for key enums and classes in Java and Python. These are skeletons (signatures only) suitable for further implementation.

Java

public enum MatchFormat {
    ODI, T20, TEST
}

public enum MatchResult {
    LIVE, FINISHED, DRAWN, CANCELLED
}

public class Player {
    private Person person;
    // constructors + getters
}

public class Team {
    private String name;
    private List<Player> players;
    private Person coach;

    public void addPlayer(Player p) {}
    public void addTournamentSquad(TournamentSquad s) {}
}

public abstract class Match {
    protected int number;
    protected Date startTime;
    protected MatchResult result;

    public void assignStadium(Stadium s) {}
    public void assignReferee(Referee r) {}
}

public class Over {
    private int number;
    private List<Ball> balls;

    public void addBall(Ball b) {}
}

public class Ball {
    private Player bowler;
    private Player batsman;
    private BallType type;
}

Python (type-hinted, Google style skeletons)

from __future__ import annotations
from dataclasses import dataclass
from enum import Enum
from typing import List, Optional
from datetime import datetime


class MatchFormat(Enum):
    ODI = "ODI"
    T20 = "T20"
    TEST = "TEST"


class MatchResult(Enum):
    LIVE = "LIVE"
    FINISHED = "FINISHED"


@dataclass
class Person:
    name: str
    email: Optional[str] = None


class Player:
    def __init__(self, person: Person) -> None:
        self._person = person
        self._contracts: List[str] = []

    def add_contract(self, contract: str) -> None:
        """Add a contract for the player."""
        raise NotImplementedError


class Team:
    def __init__(self, name: str, coach: Person) -> None:
        self._name = name
        self._players: List[Player] = []
        self._news: List[str] = []
        self._coach = coach

    def add_player(self, player: Player) -> None:
        raise NotImplementedError


class Match:
    def __init__(self, number: int, start_time: datetime) -> None:
        self._number = number
        self._start_time = start_time
        self._result = MatchResult.LIVE

    def assign_stadium(self, stadium: str) -> None:
        raise NotImplementedError


class Over:
    def __init__(self, number: int) -> None:
        self._number = number
        self._balls: List["Ball"] = []

    def add_ball(self, ball: "Ball") -> None:
        raise NotImplementedError


class Ball:
    def __init__(
        self,
        bowler: Player,
        batsman: Player,
        ball_type: str,
        wicket: Optional["Wicket"],
        runs: int,
        commentary: Optional[str],
    ) -> None:
        self._bowler = bowler
        self._batsman = batsman
        self._type = ball_type
        self._wicket = wicket
        self._runs = runs
        self._commentary = commentary

Appendix: Original reference Python code

The original, more detailed Python definitions from the source are preserved here for reference.

from enum import Enum


class Address:
    def __init__(self, street, city, state, zip_code, country):
        self.__street_address = street
        self.__city = city
        self.__state = state
        self.__zip_code = zip_code
        self.__country = country


class Person():
    def __init__(self, name, address, email, phone):
        self.__name = name
        self.__address = address
        self.__email = email
        self.__phone = phone


class MatchFormat(Enum):
    ODI, T20, TEST = 1, 2, 3


class MatchResult(Enum):
    LIVE, FINISHED, DRAWN, CANCELLED = 1, 2, 3, 4


class UmpireType(Enum):
    FIELD, RESERVED, TV = 1, 2, 3


class WicketType(Enum):
    BOLD, CAUGHT, STUMPED, RUN_OUT, LBW, RETIRED_HURT, HIT_WICKET, OBSTRUCTING = 1, 2, 3, 4, 5, 6, 7, 8


class BallType(Enum):
    NORMAL, WIDE, WICKET, NO_BALL = 1, 2, 3, 4


class RunType(Enum):
    NORMAL, FOUR, SIX, LEG_BYE, BYE, NO_BALL, OVERTHROW = 1, 2, 3, 4, 5, 6, 7


class Player:
    def __init__(self, person):
        self.__person = person
        self.__contracts = []

    def add_contract(self, contract):
        None


class Admin:
    def __init__(self, person):
        self.__person = person

    def add_match(self, match):
        None

    def add_team(self, team):
        None

    def add_tournament(self, tournament):
        None


class Umpire:
    def __init__(self, person):
        self.__person = person

    def assign_match(self, match):
        None


class Referee:
    def __init__(self, person):
        self.__person = person

    def assign_match(self, match):
        None


class Commentator:
    def __init__(self, person):
        self.__person = person

    def assign_match(self, match):
        None


class Team:
    def __init__(self, name, coach):
        self.__name = name
        self.__players = []
        self.__news = []
        self.__coach = coach

    def add_tournament_squad(self, tournament_squad):
        None

    def add_player(self, player):
        None

    def add_news(self, news):
        None


class TournamentSquad:
    def __init__(self):
        self.__players = []
        self.__tournament_stats = []

    def add_player(self, player):
        None


class Playing11:
    def __init__(self):
        self.__players = []
        self.__twelfth_man = None

    def add_player(self, player):
        None


from datetime import datetime
from abc import ABC
from .constants import MatchResult


class Over:
    def __init__(self, number):
        self.__number = number
        self.__balls = []

    def add_ball(self, ball):
        None


class Ball:
    def __init__(self, balled_by, played_by, ball_type, wicket, runs, commentary):
        self.__balled_by = balled_by
        self.__played_by = played_by
        self.__type = ball_type

        self.__wicket = wicket
        self.__runs = runs
        self.__commentary = commentary


class Wicket:
    def __init__(self, wicket_type, player_out, caught_by, runout_by, stumped_by):
        self.__wicket_type = wicket_type
        self.__player_out = player_out
        self.__caught_by = caught_by
        self.__runout_by = runout_by
        self.__stumped_by = stumped_by


class Commentary:
    def __init__(self, text, commentator):
        self.__text = text
        self.__created_at = datetime.date.today()
        self.__created_by = commentator


class Inning:
    def __init__(self, number, start_time):
        self.__number = number
        self.__start_time = start_time
        self.__overs = []

    def add_over(self, over):
        None


class Match(ABC):
    def __init__(self, number, start_time, referee):
        self.__number = number
        self.__start_time = start_time
        self.__result = MatchResult.LIVE

        self.__teams = []
        self.__innings = []
        self.__umpires = []
        self.__referee = referee
        self.__commentators = []
        self.__match_stats = []

    def assign_stadium(self, stadium):
        None

    def assign_referee(self, referee):
        None


class ODI(Match):
    # ...
    pass


class Test(Match):
    # ...
    pass

Comments