hlockey 0.1 → 1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Season
4
+ NUMBER = 1
5
+ START_TIME = Time.utc(2022, 7, 4, 17).localtime.freeze
6
+ ELECTION = {
7
+ 'Bribery': {
8
+ 'Eat More RAM': 'Add an online interface to the league.',
9
+ 'Weather': 'Move all the stadiums outdoors.',
10
+ 'We Do A Little Losing': 'Recognize the losingest teams with an Underbracket.'
11
+ },
12
+ 'Treasure': {
13
+ 'Vengence': 'All your team\'s stats are boosted by your team\'s losses * 0.005.',
14
+ 'Dave': 'The worst stat on your team is set to 4.5.',
15
+ 'Nice': 'Boost your worst player by 0.69 in every stat.',
16
+ 'Convenient Math Error': 'Your team starts the next season with 5 wins.'
17
+ },
18
+ 'Coaching': {
19
+ 'Player Swapping': 'Swap the positions of 2 players on your team.',
20
+ 'Stat Swapping': 'Swap 2 stats of a player on your team.',
21
+ 'Draft': 'Replace a player with a random new player.',
22
+ 'Small Gamble': 'All your team\'s stats go up or down by 0.5 at random.',
23
+ 'Big Gamble': 'All your team\'s stats go up or down by 1.0 at random.'
24
+ }
25
+ }.freeze
26
+ ELECTION_FORM = 'https://forms.gle/saLp3ucxg2ERsY9L7'
27
+ end
data/lib/game.rb CHANGED
@@ -1,16 +1,17 @@
1
- require_relative "./messages"
1
+ # frozen_string_literal: true
2
+
3
+ require_relative('./messages')
2
4
 
3
5
  class Game
4
- attr_reader :home, :away, :stream, :in_progress
6
+ attr_reader(:home, :away, :stream, :in_progress)
5
7
 
6
- def initialize home, away, prng
7
- @home, @away, @prng = [home, away, prng]
8
+ def initialize(home, away, prng)
9
+ @home = home
10
+ @away = away
11
+ @prng = prng
8
12
  @stream = [Messages.StartOfGame(to_s)]
9
13
  @in_progress = true
10
- @score = {
11
- :home => 0,
12
- :away => 0
13
- }
14
+ @score = { home: 0, away: 0 }
14
15
  @actions = 0
15
16
  @period = 1
16
17
  @face_off = true
@@ -27,7 +28,7 @@ class Game
27
28
  def update
28
29
  return unless @in_progress
29
30
 
30
- @stream << Messages.StartOfPeriod(@period) if @actions == 0
31
+ @stream << Messages.StartOfPeriod(@period) if @actions.zero?
31
32
  @actions += 1
32
33
 
33
34
  if @actions == 60
@@ -36,7 +37,7 @@ class Game
36
37
  @period += 1
37
38
  start_faceoff
38
39
 
39
- if @period > 3 and not(@score[:home] == @score[:away] and @period < 12)
40
+ if @period > 3 && !(@score[:home] == @score[:away] && @period < 12)
40
41
  # Game is over
41
42
  @in_progress = false
42
43
 
@@ -50,12 +51,15 @@ class Game
50
51
  end
51
52
 
52
53
  if @face_off
53
- if @puck_holder == nil
54
+ if @puck_holder.nil?
54
55
  # Pass opposite team to who wins the puck to switch_team_with_puck,
55
56
  # so @team_with_puck & @puckless_team are set to the correct values.
56
- switch_team_with_puck(
57
- action_succeeds?(@home.roster[:center].stats[:offense],
58
- @away.roster[:center].stats[:offense]) ? @away : @home)
57
+ switch_team_with_puck(if action_succeeds?(@home.roster[:center].stats[:offense],
58
+ @away.roster[:center].stats[:offense])
59
+ @away
60
+ else
61
+ @home
62
+ end)
59
63
 
60
64
  @puck_holder = @team_with_puck.roster[:center]
61
65
  @stream << Messages.FaceOff(@puck_holder)
@@ -74,9 +78,9 @@ class Game
74
78
  @stream << Messages.Hit(@puck_holder, defender,
75
79
  try_take_puck(defender, 0, :defense))
76
80
  else # Shoot
77
- unless @shooting_chance < 5 and
78
- try_block_shot @puckless_team.roster[@prng.rand(2) == 0 ? :ldef : :rdef] or
79
- try_block_shot @puckless_team.roster[:goalie]
81
+ unless @shooting_chance < 5 &&
82
+ try_block_shot(@puckless_team.roster[@prng.rand(2).zero? ? :ldef : :rdef]) ||
83
+ try_block_shot(@puckless_team.roster[:goalie])
80
84
  @score[@team_with_puck == @home ? :home : :away] += 1
81
85
 
82
86
  @stream << Messages.Shoot(@puck_holder,
@@ -85,13 +89,14 @@ class Game
85
89
  *@score.values)
86
90
 
87
91
  start_faceoff
88
- @actions = 60 if @period > 3 # Sudden death overtime
92
+ @actions = 59 if @period > 3 # Sudden death overtime
89
93
  end
90
94
  end
91
95
  end
92
96
 
93
97
  private
94
- def action_succeeds? helping_stat, hindering_stat
98
+
99
+ def action_succeeds?(helping_stat, hindering_stat)
95
100
  @prng.rand(10) + helping_stat - hindering_stat > 4
96
101
  end
97
102
 
@@ -101,9 +106,12 @@ class Game
101
106
  @puck_holder = nil
102
107
  end
103
108
 
104
- def switch_team_with_puck team_with_puck = @team_with_puck
105
- @team_with_puck, @puckless_team = team_with_puck == @home ?
106
- [@away, @home] : [@home, @away]
109
+ def switch_team_with_puck(team_with_puck = @team_with_puck)
110
+ @team_with_puck, @puckless_team = if team_with_puck == @home
111
+ [@away, @home]
112
+ else
113
+ [@home, @away]
114
+ end
107
115
  @shooting_chance = 0
108
116
  end
109
117
 
@@ -112,7 +120,7 @@ class Game
112
120
  receiver = puckless_non_goalie(@team_with_puck)
113
121
  interceptor = puckless_non_goalie
114
122
 
115
- if not @face_off and try_take_puck interceptor, 2 # Pass intercepted
123
+ if !@face_off && try_take_puck(interceptor, 4) # Pass intercepted
116
124
  @stream << Messages.Pass(sender, receiver, interceptor)
117
125
  return
118
126
  end
@@ -122,7 +130,7 @@ class Game
122
130
  @shooting_chance += 1
123
131
  end
124
132
 
125
- def try_take_puck player, dis = 0, stat = :agility
133
+ def try_take_puck(player, dis = 0, stat = :agility)
126
134
  return false unless action_succeeds?(player.stats[stat] - dis,
127
135
  @puck_holder.stats[stat])
128
136
 
@@ -132,7 +140,7 @@ class Game
132
140
  true
133
141
  end
134
142
 
135
- def try_block_shot blocker
143
+ def try_block_shot(blocker)
136
144
  return false unless action_succeeds?(blocker.stats[:defense],
137
145
  @puck_holder.stats[:offense])
138
146
 
@@ -142,10 +150,9 @@ class Game
142
150
  true
143
151
  end
144
152
 
145
- def puckless_non_goalie team = @puckless_team
153
+ def puckless_non_goalie(team = @puckless_team)
146
154
  team.roster.values.select do |p|
147
155
  p != team.roster[:goalie] and p != @puck_holder
148
- end.sample random: @prng
156
+ end.sample(random: @prng)
149
157
  end
150
158
  end
151
-
data/lib/league.rb CHANGED
@@ -1,48 +1,52 @@
1
- require_relative "./game"
2
- require_relative "./team"
1
+ # frozen_string_literal: true
2
+
3
+ require('yaml')
4
+ require_relative('./game')
3
5
 
4
6
  class League
5
- attr_reader :day, :divisions, :games_in_progress, :playoff_teams, :champion_team
7
+ attr_reader(:divisions, :day, :games_in_progress, :playoff_teams, :champion_team)
8
+
9
+ class Team
10
+ private_class_method(:new)
11
+
12
+ attr_accessor(:wins, :losses)
13
+ attr_reader(:name, :emoji, :roster)
14
+
15
+ def to_s
16
+ "#{@emoji} #{@name}"
17
+ end
18
+
19
+ def print_win_loss
20
+ puts(" #{to_s.ljust 26} #{@wins}-#{@losses}")
21
+ end
22
+
23
+ def print_roster
24
+ puts(to_s)
25
+ @roster.each do |pos, player|
26
+ puts(" #{pos.to_s.ljust(6)}: #{player}")
27
+ player.stats.each { |stat, value| puts(" #{stat}: #{value.round 1}") }
28
+ end
29
+ end
30
+
31
+ def self.sort(teams)
32
+ teams.sort { |a, b| b.wins - b.losses <=> a.wins - a.losses }
33
+ end
34
+ end
35
+
36
+ def initialize(season, start_time)
37
+ # The YAML file is included with the program,
38
+ # so this is as safe as anything else
39
+ @divisions = YAML.unsafe_load_file(File.expand_path('data/divisions.yaml',
40
+ File.dirname(__FILE__)))
6
41
 
7
- def initialize season, start_time
8
42
  @day = 0
9
- @divisions = {
10
- "Wet Warm": [
11
- Team.new("Antalya Pirates", "🌊"),
12
- Team.new("Baden Hallucinations", "🍄"),
13
- Team.new("Kópavogur Seals", "🦭"),
14
- Team.new("Lagos Soup", "🥣"),
15
- Team.new("Pica Acid", "🧪")
16
- ],
17
- "Dry Warm": [
18
- Team.new("Dawson City Impostors", "🔪"),
19
- Team.new("Erlangen Ohms", "🇴"),
20
- Team.new("Pompei Eruptions", "🌋"),
21
- Team.new("Rio de Janeiro Directors", "🎦"),
22
- Team.new("Wyrzysk Rockets", "🚀")
23
- ],
24
- "Wet Cool": [
25
- Team.new("Cape Town Transplants", "🌱"),
26
- Team.new("Manbij Fish", "🐠"),
27
- Team.new("Nagqu Paint", "🎨"),
28
- Team.new("Nice Backflippers", "🔄"),
29
- Team.new("Orcadas Base Fog", "🌁")
30
- ],
31
- "Dry Cool": [
32
- Team.new("Baghdad Abacuses", "🧮"),
33
- Team.new("Jakarta Architects", "📐"),
34
- Team.new("Kyoto Payphones", "📳"),
35
- Team.new("Stony Brook Reapers", "💀"),
36
- Team.new("Sydney Thinkers", "🤔")
37
- ]
38
- }
39
43
  @games_in_progress = []
40
44
  @games = []
41
45
  @champion_team = nil
42
46
  @last_update_time = start_time
43
47
  @passed_updates = 0
44
- @prng = Random.new 69420 * season
45
- @shuffled_teams = @divisions.values.reduce(:+).shuffle random: @prng
48
+ @prng = Random.new(69_420 * season)
49
+ @shuffled_teams = @divisions.values.reduce(:+).shuffle(random: @prng)
46
50
  @playoff_teams = nil
47
51
  @game_in_matchup = 3
48
52
  end
@@ -50,30 +54,31 @@ class League
50
54
  def update_state
51
55
  return if @champion_team
52
56
 
53
- now = Time.now
54
- five_sec_intervals = (now - @last_update_time).floor / 5
57
+ now = Time.at(Time.now.to_i)
58
+ five_sec_intervals = (now - @last_update_time).div(5)
55
59
 
56
- if five_sec_intervals > 0
57
- five_sec_intervals.times do |i|
58
- if (i + @passed_updates) % 720 == 0
59
- new_games
60
- else
61
- update_games
62
- end
60
+ return unless five_sec_intervals.positive?
63
61
 
64
- break if @champion_team
62
+ five_sec_intervals.times do |i|
63
+ if ((i + @passed_updates) % 720).zero?
64
+ new_games
65
+ else
66
+ update_games
65
67
  end
66
68
 
67
- @last_update_time = now
68
- @passed_updates += five_sec_intervals
69
+ break if @champion_team
69
70
  end
71
+
72
+ @last_update_time = now
73
+ @passed_updates += five_sec_intervals
70
74
  end
71
75
 
72
76
  private
77
+
73
78
  def new_games
74
79
  if @game_in_matchup != (@day > 38 ? 5 : 3)
75
80
  # New game in matchups
76
- @games.map! do |game| Game.new(game.away, game.home, @prng) end
81
+ @games.map! { |game| Game.new(game.away, game.home, @prng) }
77
82
  @game_in_matchup += 1
78
83
  return
79
84
  end
@@ -92,15 +97,15 @@ class League
92
97
 
93
98
  @shuffled_teams.insert 1, @shuffled_teams.pop
94
99
  when 0
95
- @playoff_teams = Team.sort_teams(
100
+ @playoff_teams = Team.sort(
96
101
  @divisions.values.map do |teams|
97
- Team.sort_teams(teams).first(2)
98
- end.reduce(:+).map &:clone
99
- )
102
+ Team.sort(teams).first(2)
103
+ end.reduce(:+)
104
+ ).map(&:clone)
100
105
 
101
106
  new_playoff_matchups
102
107
  when 1
103
- @playoff_teams = Team.sort_teams(@playoff_teams).first(@playoff_teams.length / 2)
108
+ @playoff_teams = Team.sort(@playoff_teams).first(@playoff_teams.length / 2)
104
109
 
105
110
  if @playoff_teams.length == 1
106
111
  @champion_team = @playoff_teams[0]
@@ -112,8 +117,8 @@ class League
112
117
  end
113
118
 
114
119
  def update_games
115
- @games_in_progress = @games.select &:in_progress
116
- @games_in_progress.each do |game| game.update end
120
+ @games_in_progress.each(&:update)
121
+ @games_in_progress = @games.select(&:in_progress)
117
122
  end
118
123
 
119
124
  def new_playoff_matchups
@@ -122,9 +127,14 @@ class League
122
127
  team.losses = 0
123
128
  end
124
129
 
125
- (0...@playoff_teams.length).step 2 do |i|
130
+ (0...@playoff_teams.length).step(2) do |i|
126
131
  @games << Game.new(*@playoff_teams[i, 2], @prng)
127
132
  end
128
133
  end
129
- end
130
134
 
135
+ class Player
136
+ private_class_method(:new)
137
+
138
+ attr_reader(:stats, :to_s)
139
+ end
140
+ end
data/lib/messages.rb CHANGED
@@ -1,26 +1,28 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Messages
2
- def initialize event, fields, data
4
+ def initialize(event, fields, data)
3
5
  @event = event
4
- fields.zip data do |(f, d)|
5
- instance_variable_set "@" + f.to_s, d
6
+ fields.zip(data) do |(f, d)|
7
+ instance_variable_set("@#{f}", d)
6
8
  end
7
9
  end
8
10
 
9
- private_class_method :new
11
+ private_class_method(:new)
10
12
 
11
13
  class << self
12
14
  [
13
- [:StartOfGame, :title],
14
- [:EndOfGame, :winning_team],
15
- [:StartOfPeriod, :period],
16
- [:EndOfPeriod, :period, :home, :away, :home_score, :away_score],
17
- [:FaceOff, :winning_player],
18
- [:Hit, :puck_holder, :defender, :puck_taken],
19
- [:Pass, :sender, :receiver, :interceptor],
20
- [:Shoot, :shooter, :blocker, :puck_taken, :home, :away, :home_score, :away_score]
15
+ %i[StartOfGame title],
16
+ %i[EndOfGame winning_team],
17
+ %i[StartOfPeriod period],
18
+ %i[EndOfPeriod period home away home_score away_score],
19
+ %i[FaceOff winning_player],
20
+ %i[Hit puck_holder defender puck_taken],
21
+ %i[Pass sender receiver interceptor],
22
+ %i[Shoot shooter blocker puck_taken home away home_score away_score]
21
23
  ].each do |event, *fields|
22
24
  define_method event do |*data|
23
- new event, fields, data
25
+ new(event, fields, data)
24
26
  end
25
27
  end
26
28
  end
@@ -28,29 +30,28 @@ class Messages
28
30
  def to_s
29
31
  case @event
30
32
  when :StartOfGame
31
- @title + "\nHocky!"
33
+ "#{@title}\nHocky!"
32
34
  when :EndOfGame
33
- "Game over.\n#{@winning_team or "Nobody"} wins!"
35
+ "Game over.\n#{@winning_team} wins!"
34
36
  when :StartOfPeriod
35
- "Start" + of_period
37
+ "Start#{of_period}"
36
38
  when :EndOfPeriod
37
- "End" + of_period + score
39
+ "End#{of_period}#{score}"
38
40
  when :FaceOff
39
41
  "#{@winning_player} wins the faceoff!"
40
42
  when :Hit
41
43
  "#{@defender} hits #{@puck_holder.to_s + takes}!"
42
44
  when :Pass
43
- "#{@sender} passes to #{@receiver}#{@interceptor ?
44
- "... intercepted by #{@interceptor}!" : "."}"
45
+ "#{@sender} passes to #{@receiver}" +
46
+ (@interceptor ? "... intercepted by #{@interceptor}!" : '.')
45
47
  when :Shoot
46
- "#{@shooter} takes a shot... #{@blocker ?
47
- "#{@blocker} blocks the shot#{takes}!" : "and scores!" + score}"
48
- else
49
- raise "Unknown message"
48
+ "#{@shooter} takes a shot... " +
49
+ (@blocker ? "#{@blocker} blocks the shot#{takes}!" : "and scores!#{score}")
50
50
  end
51
51
  end
52
52
 
53
53
  private
54
+
54
55
  def of_period
55
56
  " of period #{@period}."
56
57
  end
@@ -60,7 +61,6 @@ class Messages
60
61
  end
61
62
 
62
63
  def takes
63
- @puck_taken ? " and takes the puck" : ""
64
+ @puck_taken ? ' and takes the puck' : ''
64
65
  end
65
66
  end
66
-
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hlockey
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.1'
4
+ version: '1'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lavender Perry
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-06-26 00:00:00.000000000 Z
11
+ date: 2022-07-03 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Hockey sports sim.
14
14
  email: endie2@protonmail.com
@@ -18,12 +18,11 @@ extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
20
  - bin/hlockey
21
- - lib/data/names_markov_chain.rb
21
+ - lib/data/divisions.yaml
22
+ - lib/data/season.rb
22
23
  - lib/game.rb
23
24
  - lib/league.rb
24
25
  - lib/messages.rb
25
- - lib/player.rb
26
- - lib/team.rb
27
26
  homepage: https://github.com/Lavender-Perry/hlockey
28
27
  licenses:
29
28
  - LicenseRef-LICENSE.md
@@ -47,5 +46,5 @@ requirements: []
47
46
  rubygems_version: 3.3.7
48
47
  signing_key:
49
48
  specification_version: 4
50
- summary: Hlockey season 0.1.
49
+ summary: Hlockey season 1.
51
50
  test_files: []