hlockey 1 → 3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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