# Input service to return array of array [ ["Team A", "Team B", "win"] ] class DummyData def initialize @data = <<~INPUT Team B;Team C;win Team A;Team D;draw Team A;Team B;win Team D;Team C;loss Team C;Team A;loss Team B;Team D;win INPUT end def call @data.split("\n").map { |line| line.split(";") } end end class Team POINTS_TABLE = { win: 3, draw: 1, loss: 0 } attr_accessor :name, :points, :win_count, :draw_count, :loss_count, :match_played def initialize(name) @name = name @points = 0 @win_count = 0 @loss_count = 0 @draw_count = 0 @match_played = 0 end def win! @win_count += 1 @match_played += 1 @points += POINTS_TABLE[:win] end def loss! @loss_count += 1 @match_played += 1 @points += POINTS_TABLE[:loss] end def draw! @draw_count += 1 @match_played += 1 @points += POINTS_TABLE[:draw] end end class Match attr_accessor :home_team, :visiting_team, :outcome OUTCOME = { win: 'win', loss: 'loss', draw: 'draw' }.freeze def initialize(home_team, visiting_team, outcome) @outcome = outcome @home_team = home_team @visiting_team = visiting_team end def call case outcome when OUTCOME[:win] @home_team.win! @visiting_team.loss! when OUTCOME[:loss] @home_team.loss! @visiting_team.win! when OUTCOME[:draw] @home_team.draw! @visiting_team.draw! end end end class ScoreCard TEAM_NAMES = ['Team A', 'Team B', 'Team C', 'Team D'] attr_accessor :matches, :input, :teams_map, :teams def initialize(input_service = DummyData.new) @matches = [] @input = input_service.call @teams_map = TEAM_NAMES.inject({}) do |acc, team_name| acc[team_name] = Team.new(team_name) acc end @teams = @teams_map.values end def calculate self.matches = input.map do |match| home_team, visiting_team, outcome = match Match.new(teams_map[home_team], teams_map[visiting_team], outcome) end matches.each(&:call) teams.sort_by! { |team| [team.points * -1, team.name] } end def print_score_card puts "Score Board" puts "-----------------------------------" puts "Team name | MP | W | D | L | Points" puts "-----------------------------------" @teams.each do |team| puts "#{team.name} | #{team.match_played} | #{team.win_count} | #{team.draw_count} | #{team.loss_count} | #{team.points}" end puts "-----------------------------------" end def call calculate && print_score_card end end ScoreCard.new.call # Score Board # ----------------------------------- # Team name | MP | W | D | L | Points # ----------------------------------- # Team A | 3 | 2 | 1 | 0 | 7 # Team B | 3 | 2 | 0 | 1 | 6 # Team C | 3 | 1 | 0 | 2 | 3 # Team D | 3 | 0 | 1 | 2 | 1 # -----------------------------------