hlockey 1 → 3

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.
@@ -0,0 +1,63 @@
1
+ require("hlockey/utils")
2
+
3
+ module Hlockey
4
+ class Player
5
+ attr_accessor(:stats)
6
+ attr_reader(:to_s)
7
+
8
+ @@cached_chain = nil
9
+
10
+ def initialize(prng = Random)
11
+ @to_s = make_name(prng)
12
+ # Generate stats
13
+ @stats = {}
14
+ %i[offense defense agility].each { |stat| @stats[stat] = prng.rand * 5 }
15
+ end
16
+
17
+ private
18
+
19
+ def make_name(prng)
20
+ Array.new(2) do
21
+ combination = "__"
22
+ next_letter = ""
23
+ result = ""
24
+
25
+ 10.times do
26
+ next_letters = name_chain[combination]
27
+ break if next_letters.nil?
28
+
29
+ cumulative_weights = []
30
+ next_letters.each_value do |v|
31
+ cumulative_weights << v + (cumulative_weights.last or 0)
32
+ end
33
+
34
+ next_letter = Utils.weighted_random(next_letters, prng)
35
+ break if next_letter == "_"
36
+
37
+ result += next_letter
38
+ combination = combination[1] + next_letter
39
+ end
40
+
41
+ result
42
+ end.join(" ")
43
+ end
44
+
45
+ def name_chain
46
+ if @@cached_chain.nil?
47
+ @@cached_chain = {}
48
+ File.open(File.expand_path("../../data/external/names.txt", __dir__)).each do |n|
49
+ name = "__#{n.chomp}__"
50
+ (name.length - 3).times do |i|
51
+ combination = name[i, 2]
52
+ next_letter = name[i + 2]
53
+ @@cached_chain[combination] ||= {}
54
+ @@cached_chain[combination][next_letter] ||= 0
55
+ @@cached_chain[combination][next_letter] += 1
56
+ end
57
+ end
58
+ end
59
+
60
+ @@cached_chain
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,59 @@
1
+ require("hlockey/player")
2
+
3
+ module Hlockey
4
+ # Created by League when data is loaded
5
+ class Team
6
+ attr_accessor(:wins, :losses, :roster)
7
+ attr_reader(:to_s, :emoji)
8
+
9
+ # rand is only used if roster is nil
10
+ def initialize(name, emoji, roster: nil, random: Random)
11
+ @to_s = name
12
+ @emoji = emoji
13
+
14
+ if roster.nil?
15
+ @roster = {}
16
+ %i[lwing center rwing ldef goalie rdef].each do |pos|
17
+ @roster[pos] = Player.new(random)
18
+ end
19
+ else
20
+ @roster = roster
21
+ end
22
+
23
+ @wins = 0
24
+ @losses = 0
25
+ end
26
+
27
+ def random_player(random, filter_predicate = nil)
28
+ players = @roster.values
29
+ players.select!(&filter_predicate) unless filter_predicate.nil?
30
+ players.sample(random: random)
31
+ end
32
+
33
+ def w_l
34
+ "#{@wins}-#{@losses}"
35
+ end
36
+
37
+ def worst_player_pos
38
+ @roster.transform_values do |player|
39
+ player.stats.values.reduce(:+)
40
+ end.min_by { |k, v| v }.first
41
+ end
42
+
43
+ # Takes symbol from Team roster & converts it to full position name
44
+ def self.pos_name(pos)
45
+ case pos
46
+ when :lwing
47
+ "Left wing"
48
+ when :rwing
49
+ "Right wing"
50
+ when :ldef
51
+ "Left defender"
52
+ when :rdef
53
+ "Right defender"
54
+ else
55
+ pos.capitalize.to_s
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,12 @@
1
+ module Hlockey
2
+ module Utils
3
+ # Does a weighted random with a hash,
4
+ # where the keys are elements being randomly selected,
5
+ # and the values are the weights
6
+ def self.weighted_random(hash, prng = Random)
7
+ cumulative_weights = []
8
+ hash.each_value { |v| cumulative_weights << v + (cumulative_weights.last or 0) }
9
+ hash.keys[cumulative_weights.index { |n| prng.rand(cumulative_weights.last) < n }]
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module Hlockey
2
+ VERSION = "3"
3
+ end
@@ -0,0 +1,114 @@
1
+ require("hlockey/game")
2
+ require("hlockey/message")
3
+ require("hlockey/player")
4
+
5
+ module Hlockey
6
+ class Weather
7
+ def initialize(game)
8
+ @game = game
9
+ end
10
+
11
+ def to_s
12
+ self.class.to_s.split("::").last
13
+ end
14
+
15
+ def on_game_start() end
16
+
17
+ def on_game_end() end
18
+
19
+ def on_period_end() end
20
+
21
+ def on_action() end
22
+
23
+ def on_goal(scoring_team) end
24
+
25
+ private
26
+
27
+ def worst_player_rand_replace(message, apprx_times_per_game = 1, store_old_in = nil)
28
+ return unless @game.prng.rand(Game::NON_OT_ACTIONS / apprx_times_per_game).zero?
29
+
30
+ team = @game.prng.rand(2).zero? ? @game.home : @game.away
31
+ pos = team.worst_player_pos
32
+
33
+ prev_player = team.roster[pos]
34
+ next_player = Player.new(@game.prng)
35
+
36
+ team.roster[pos] = next_player
37
+ store_old_in[team][pos] ||= prev_player unless store_old_in.nil?
38
+
39
+ @game.stream << Message.send(message, prev_player, next_player)
40
+ end
41
+ end
42
+
43
+ class Chicken < Weather
44
+ def on_game_start
45
+ @chickened_out = { @game.home => {}, @game.away => {} }
46
+ end
47
+
48
+ def on_action
49
+ worst_player_rand_replace(:ChickenedOut, 5, @chickened_out)
50
+ end
51
+
52
+ def on_game_end
53
+ @chickened_out.each { |team, players| team.roster.merge!(players) }
54
+ end
55
+ end
56
+
57
+ class Inclines < Weather
58
+ def on_game_start
59
+ make_incline
60
+ end
61
+
62
+ def on_goal(scoring_team)
63
+ return unless scoring_team == @favored_team
64
+
65
+ @game.score[scoring_team] += @game.prng.rand(0.1..0.5)
66
+ make_incline
67
+ end
68
+
69
+ private
70
+
71
+ def make_incline
72
+ new_favored_team = @game.prng.rand(2).zero? ? :home : :away
73
+ return unless new_favored_team != @favored_team
74
+
75
+ @favored_team = new_favored_team
76
+ @game.stream << Message.InclineFavors(@game.send(@favored_team))
77
+ end
78
+ end
79
+
80
+ class Stars < Weather
81
+ def on_period_end
82
+ return unless @game.score[:home] != @game.score[:away]
83
+
84
+ losing_team = @game.score.min_by { |_k, v| v }.first
85
+ @game.score[losing_team] += 0.5
86
+ @game.stream << Message.StarsPity(@game.send(losing_team))
87
+ end
88
+ end
89
+
90
+ class Sunset < Weather
91
+ def on_game_start
92
+ @score_amt = { home: 0, away: 0 }
93
+ end
94
+
95
+ def on_goal(scoring_team)
96
+ @score_amt[scoring_team] += 1
97
+ @game.score[scoring_team] -= @score_amt[scoring_team] * 0.2
98
+ end
99
+ end
100
+
101
+ class Waves < Weather
102
+ def on_action
103
+ worst_player_rand_replace(:WavesWashedAway)
104
+ end
105
+ end
106
+
107
+ Weather::WEIGHTS = {
108
+ Chicken => 4,
109
+ Inclines => 4,
110
+ Stars => 4,
111
+ Sunset => 4,
112
+ Waves => 3
113
+ }.freeze
114
+ end
data/lib/hlockey.rb ADDED
@@ -0,0 +1 @@
1
+ require("hlockey/league")
metadata CHANGED
@@ -1,33 +1,44 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hlockey
3
3
  version: !ruby/object:Gem::Version
4
- version: '1'
4
+ version: '3'
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-07-03 00:00:00.000000000 Z
11
+ date: 2023-06-02 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Hockey sports sim.
13
+ description: Hlockey library.
14
14
  email: endie2@protonmail.com
15
- executables:
16
- - hlockey
15
+ executables: []
17
16
  extensions: []
18
17
  extra_rdoc_files: []
19
18
  files:
20
- - bin/hlockey
21
- - lib/data/divisions.yaml
22
- - lib/data/season.rb
23
- - lib/game.rb
24
- - lib/league.rb
25
- - lib/messages.rb
26
- homepage: https://github.com/Lavender-Perry/hlockey
19
+ - data/election.yaml
20
+ - data/external/names.txt
21
+ - data/information.yaml
22
+ - data/league.yaml
23
+ - data/links.yaml
24
+ - lib/hlockey.rb
25
+ - lib/hlockey/constants.rb
26
+ - lib/hlockey/data.rb
27
+ - lib/hlockey/game.rb
28
+ - lib/hlockey/game/actions.rb
29
+ - lib/hlockey/game/fight.rb
30
+ - lib/hlockey/league.rb
31
+ - lib/hlockey/message.rb
32
+ - lib/hlockey/player.rb
33
+ - lib/hlockey/team.rb
34
+ - lib/hlockey/utils.rb
35
+ - lib/hlockey/version.rb
36
+ - lib/hlockey/weather.rb
37
+ homepage: https://github.com/Hlockey/lib
27
38
  licenses:
28
39
  - LicenseRef-LICENSE.md
29
40
  metadata:
30
- source_code_uri: https://github.com/Lavender-Perry/hlockey
41
+ source_code_uri: https://github.com/Hlockey/lib
31
42
  post_install_message:
32
43
  rdoc_options: []
33
44
  require_paths:
@@ -43,8 +54,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
43
54
  - !ruby/object:Gem::Version
44
55
  version: '0'
45
56
  requirements: []
46
- rubygems_version: 3.3.7
57
+ rubygems_version: 3.4.10
47
58
  signing_key:
48
59
  specification_version: 4
49
- summary: Hlockey season 1.
60
+ summary: Hlockey season 3.
50
61
  test_files: []
data/bin/hlockey DELETED
@@ -1,90 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # frozen_string_literal: true
4
-
5
- require_relative('../lib/league')
6
- require_relative('../lib/data/season')
7
-
8
- def menu_input(default, *choices)
9
- puts('Please enter a number...')
10
- # Adding 1 to i when printing choices
11
- # to avoid confusing a non-numerical input with the first choice
12
- choices.each_with_index { |choice, i| puts("#{(i + 1).to_s.rjust(2)} - #{choice}") }
13
- puts("anything else - #{default}")
14
-
15
- # Subtract 1 here to undo adding 1 earlier
16
- gets.to_i - 1
17
- end
18
-
19
- # Each element from choices should implement to_s
20
- def menu_input_elem(default, choices)
21
- i = menu_input(default, *choices)
22
- choices[i] unless i.negative?
23
- end
24
-
25
- PUTS = method(:puts)
26
- league = League.new(Season::NUMBER, Season::START_TIME)
27
-
28
- if Time.now < Season::START_TIME
29
- puts Season::START_TIME
30
- .strftime("Season #{Season::NUMBER} starts at %H:%M on %A, %B %d.")
31
- end
32
-
33
- loop do
34
- league.update_state
35
-
36
- puts("Season #{Season::NUMBER} day #{league.day}")
37
-
38
- case menu_input('Exit', 'Games', 'Standings', 'Rosters', 'Election')
39
- when 0 # Games
40
- if league.games_in_progress.empty?
41
- puts('There are currently no games being played.')
42
- next
43
- end
44
-
45
- game = menu_input_elem('Back', league.games_in_progress)
46
- next if game.nil?
47
-
48
- loop do
49
- league.update_state
50
-
51
- game.stream.each(&PUTS)
52
-
53
- break unless game.in_progress
54
-
55
- game.stream.clear
56
- sleep(5)
57
- end
58
- when 1 # Standings
59
- if league.champion_team
60
- puts("Your season #{Season::NUMBER} champions are the "\
61
- "#{league.champion_team.name}!")
62
- elsif league.playoff_teams
63
- puts('Playoffs')
64
- league.playoff_teams.each(&:print_win_loss)
65
- end
66
-
67
- league.divisions.each do |name, teams|
68
- puts(name)
69
- League::Team.sort(teams).each(&:print_win_loss)
70
- end
71
- when 2 # Rosters
72
- teams = league.divisions.values.reduce(:+)
73
- team = menu_input_elem('All teams', teams)
74
-
75
- if team.nil?
76
- teams.each(&:print_roster)
77
- next
78
- end
79
- team.print_roster
80
- when 3 # Election
81
- Season::ELECTION.each do |category, options|
82
- puts(category)
83
- options.each { |name, description| puts(" #{name}: #{description}") }
84
- end
85
- puts("Go to #{Season::ELECTION_FORM} to vote.\n"\
86
- "If you don't want to use Google Forms, DM me on Discord (Lavender#9223).")
87
- else
88
- exit
89
- end
90
- end