ehbrs_ruby_utils 0.22.0 → 0.23.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ehbrs_ruby_utils/bga/parsers/game_stats/players.rb +25 -0
  3. data/lib/ehbrs_ruby_utils/bga/parsers/game_stats.rb +47 -0
  4. data/lib/ehbrs_ruby_utils/bga/parsers/table/options.rb +31 -0
  5. data/lib/ehbrs_ruby_utils/bga/parsers/table/players.rb +28 -0
  6. data/lib/ehbrs_ruby_utils/bga/parsers/table.rb +41 -0
  7. data/lib/ehbrs_ruby_utils/bga/session/login.rb +62 -0
  8. data/lib/ehbrs_ruby_utils/bga/session/player.rb +28 -0
  9. data/lib/ehbrs_ruby_utils/bga/session/table.rb +39 -0
  10. data/lib/ehbrs_ruby_utils/bga/session.rb +28 -0
  11. data/lib/ehbrs_ruby_utils/bga/table/option.rb +20 -0
  12. data/lib/ehbrs_ruby_utils/bga/table/player.rb +20 -0
  13. data/lib/ehbrs_ruby_utils/bga/table.rb +41 -0
  14. data/lib/ehbrs_ruby_utils/bga/urls.rb +34 -0
  15. data/lib/ehbrs_ruby_utils/executables.rb +5 -0
  16. data/lib/ehbrs_ruby_utils/version.rb +1 -1
  17. data/spec/lib/ehbrs_ruby_utils/bga/parsers/game_stats_spec.rb +7 -0
  18. data/spec/lib/ehbrs_ruby_utils/bga/parsers/game_stats_spec_files/1.source.html +1082 -0
  19. data/spec/lib/ehbrs_ruby_utils/bga/parsers/game_stats_spec_files/1.target.yaml +151 -0
  20. data/spec/lib/ehbrs_ruby_utils/bga/parsers/table_spec.rb +7 -0
  21. data/spec/lib/ehbrs_ruby_utils/bga/parsers/table_spec_files/table_302873643.source.html +1491 -0
  22. data/spec/lib/ehbrs_ruby_utils/bga/parsers/table_spec_files/table_302873643.target.yaml +34 -0
  23. data/spec/lib/ehbrs_ruby_utils/bga/parsers/table_spec_files/table_357408039.source.html +1500 -0
  24. data/spec/lib/ehbrs_ruby_utils/bga/parsers/table_spec_files/table_357408039.target.yaml +54 -0
  25. data/spec/lib/ehbrs_ruby_utils/bga/parsers/table_spec_files/table_368448439.source.html +1497 -0
  26. data/spec/lib/ehbrs_ruby_utils/bga/parsers/table_spec_files/table_368448439.target.yaml +48 -0
  27. data/spec/lib/ehbrs_ruby_utils/bga/parsers/table_spec_files/table_373602409.source.html +1441 -0
  28. data/spec/lib/ehbrs_ruby_utils/bga/parsers/table_spec_files/table_373602409.target.yaml +24 -0
  29. data/spec/lib/ehbrs_ruby_utils/bga/parsers/table_spec_files/table_373747455.source.html +1521 -0
  30. data/spec/lib/ehbrs_ruby_utils/bga/parsers/table_spec_files/table_373747455.target.yaml +53 -0
  31. data/spec/lib/ehbrs_ruby_utils/circular_list_spreader_spec.rb +4 -2
  32. metadata +59 -24
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2a241af9b0a27b447cef66e7d719fbda116547b7cfe5ceac348b9bb1bd5662d9
4
- data.tar.gz: b02d61f6840f2a602535c24c655bc6a5655a6daa531995a9d78523165517c066
3
+ metadata.gz: 90c029952b15c0fa9fd3034c5766583e9f8679c8efd16a005304ede77774b1ee
4
+ data.tar.gz: 8862eaf9b276fd42e92856ea98fa42e38d991c5e3c825ec1e1474ebaaaddefc6
5
5
  SHA512:
6
- metadata.gz: 54762c964c78d7335f8efc92b19c29b6b7281a37d473e1b3cdd5515177e3e54492808c84481ce075c6a758c3d5d6ccb1fe1ad07ca5d75512600cb026a605697d
7
- data.tar.gz: bf4f9ea658f93e2285735d98f22dde951a921f8d7f271b16c5d91c677119ef4c1f6c5f073427b30a4dc7b8dd207fe3bea2b05b00db0af76558b6e21cd246ec60
6
+ metadata.gz: fbc869e81f0a95f04cf9a393eb4f6f9b1d79e3d77ac3ff9f720b3115722adf41fbe6478e9c7d9878b297c8c46342686ce79a11fceb2f8b5d52c197044724372b
7
+ data.tar.gz: aab5320864d3863cc32878679ae7ee7cfa84610ed24bd0ade989c60a20a3285fb0a348efeb2aafc7eed71bf824c1ff6ee7dcc2c12467ab5efbd89722f058474f
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'aranha/parsers/html/item_list'
4
+ require 'eac_ruby_utils/core_ext'
5
+
6
+ module EhbrsRubyUtils
7
+ module Bga
8
+ module Parsers
9
+ class GameStats < ::Aranha::Parsers::Html::ItemList
10
+ class Players < ::Aranha::Parsers::Html::ItemList
11
+ ITEMS_XPATH = '//div[@class = "simple-score-entry"]'
12
+
13
+ field :rank, :integer, './div[@class = "rank"]'
14
+ field :id, :integer, './div[@class = "name"]/a/@href'
15
+ field :name, :string, './div[@class = "name"]/a/text()'
16
+ field :score, :integer, './div[@class = "score"]'
17
+
18
+ def items_xpath
19
+ ITEMS_XPATH
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'aranha/parsers/html/item_list'
4
+ require 'eac_ruby_utils/core_ext'
5
+
6
+ module EhbrsRubyUtils
7
+ module Bga
8
+ module Parsers
9
+ class GameStats < ::Aranha::Parsers::Html::ItemList
10
+ ITEMS_XPATH = '//table[@id = "gamelist_inner"]/tr'
11
+
12
+ field :game_name, :string, './td[1]/a[1]/text()'
13
+ field :table_name, :string, './td[1]/a[2]/text()'
14
+ field :time_string, :string, './td[2]/div[1]/text()'
15
+ field :leave_penalty, :integer, './td[4]/span[1]/text()'
16
+ field :rank_increment, :integer, './td[4]/span[2]/text()'
17
+ field :rank_after, :integer, './td[4]//*[@class = "gamerank_value"]/text()'
18
+ field :players, :node, './td[3]'
19
+
20
+ def items_xpath
21
+ ITEMS_XPATH
22
+ end
23
+
24
+ def item_data(item)
25
+ r = super
26
+ r[:table_id] = table_name_to_id(r.delete(:table_name))
27
+ r[:players] = players_data(r.delete(:players))
28
+ r
29
+ end
30
+
31
+ private
32
+
33
+ def players_data(players_node)
34
+ ::EhbrsRubyUtils::Bga::Parsers::GameStats::Players.from_node(
35
+ players_node
36
+ ).data
37
+ end
38
+
39
+ def table_name_to_id(name)
40
+ name.gsub(/\A\#/, '')
41
+ end
42
+
43
+ require_sub __FILE__
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'aranha/parsers/html/item'
4
+ require 'aranha/parsers/html/item_list'
5
+ require 'eac_ruby_utils/core_ext'
6
+
7
+ module EhbrsRubyUtils
8
+ module Bga
9
+ module Parsers
10
+ class Table < ::Aranha::Parsers::Html::Item
11
+ class Options < ::Aranha::Parsers::Html::ItemList
12
+ ITEMS_XPATH = '//div[starts-with(@id, "gameoption_")' \
13
+ ' and not(contains(@style, "none"))]'
14
+
15
+ field :label, :string, './div[@class = "row-label"]/text()'
16
+ field :value, :string, './div[@class = "row-value"]' \
17
+ "//*[#{xpath_ends_with('@id', "'_displayed_value'")}]/text()"
18
+ field :description, :string, './div[@class = "gameoption_description"]/text()'
19
+
20
+ def items_xpath
21
+ ITEMS_XPATH
22
+ end
23
+
24
+ def data
25
+ super.reject { |item| item.fetch(:label).blank? }
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'aranha/parsers/html/item'
4
+ require 'aranha/parsers/html/item_list'
5
+ require 'eac_ruby_utils/core_ext'
6
+
7
+ module EhbrsRubyUtils
8
+ module Bga
9
+ module Parsers
10
+ class Table < ::Aranha::Parsers::Html::Item
11
+ class Players < ::Aranha::Parsers::Html::ItemList
12
+ ITEMS_XPATH = '//div[starts-with(@id, "score_entry_")]'
13
+
14
+ field :table_rank, :integer, './div[@class = "rank"]'
15
+ field :id, :integer, './div[@class = "name"]/a/@href'
16
+ field :name, :string, './div[@class = "name"]/a/text()'
17
+ field :score, :integer, './div[@class = "score"]'
18
+ field :win_points, :string, './/*[starts-with(@id, "winpoints_value_")]/text()'
19
+ field :game_rank, :integer, './/*[@class = "gamerank_value"]/text()'
20
+
21
+ def items_xpath
22
+ ITEMS_XPATH
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'aranha/parsers/html/item'
4
+ require 'eac_ruby_utils/core_ext'
5
+
6
+ module EhbrsRubyUtils
7
+ module Bga
8
+ module Parsers
9
+ class Table < ::Aranha::Parsers::Html::Item
10
+ ITEM_XPATH = '/'
11
+
12
+ field :game_name, :string, './/*[@id = "table_name"]/text()'
13
+ field :creation_time, :string, './/*[@id = "creationtime"]/text()'
14
+ field :estimated_duration, :string, './/*[@id = "estimated_duration"]/text()'
15
+ field :options, :node, './/*[@id = "gameoptions"]'
16
+ field :players, :node, './/*[@id = "game_result"]'
17
+
18
+ def item_xpath
19
+ ITEM_XPATH
20
+ end
21
+
22
+ def data
23
+ r = super
24
+ %i[options players].each do |key|
25
+ r[key] = self.class.const_get(key.to_s.camelize).from_node(r.fetch(key)).data
26
+ end
27
+ r[:creation_time] = process_creation_time(r[:creation_time])
28
+ r
29
+ end
30
+
31
+ private
32
+
33
+ def process_creation_time(creation_time)
34
+ creation_time.gsub('Criado:', '').strip
35
+ end
36
+
37
+ require_sub __FILE__
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module EhbrsRubyUtils
6
+ module Bga
7
+ class Session < ::SimpleDelegator
8
+ module Login
9
+ LOGIN_PATH = 'account'
10
+ USERNAME_INPUT_ID = 'username_input'
11
+ PASSWORD_INPUT_ID = 'password_input'
12
+ SUBMIT_ID = 'login_button'
13
+ LOGGED_MESSAGE_PATTERNS = [
14
+ /Page not found/ # Page not found: join.js
15
+ ].freeze
16
+ UNLOGGED_MESSAGE_PATTERSN = [
17
+ /Recover my password/ # Oops, we don't recognize your username or password. Don't panic.
18
+ # (Recover my password)
19
+ ].freeze
20
+
21
+ # @return [Boolean]
22
+ def login
23
+ navigate_to_login_page
24
+ input_username
25
+ input_password
26
+ submit_login
27
+ logged_by_message?(message_info)
28
+ end
29
+
30
+ def login_url
31
+ build_url(LOGIN_PATH)
32
+ end
33
+
34
+ private
35
+
36
+ def navigate_to_login_page
37
+ navigate.to(login_url)
38
+ end
39
+
40
+ def input_username
41
+ wait_for_element(id: USERNAME_INPUT_ID).send_keys(username)
42
+ end
43
+
44
+ def input_password
45
+ wait_for_element(id: PASSWORD_INPUT_ID).send_keys(password)
46
+ end
47
+
48
+ def submit_login
49
+ wait_for_click(id: SUBMIT_ID)
50
+ end
51
+
52
+ # @return [Boolean]
53
+ def logged_by_message?(message_info)
54
+ return true if LOGGED_MESSAGE_PATTERNS.any? { |p| p.match?(message_info) }
55
+ return false if UNLOGGED_MESSAGE_PATTERNS.any? { |p| p.match?(message_info) }
56
+
57
+ raise("Unmapped login message: \"#{message_info}\"")
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ehbrs_ruby_utils/bga/parsers/game_stats'
4
+ require 'ehbrs_ruby_utils/bga/urls'
5
+ require 'eac_ruby_utils/core_ext'
6
+
7
+ module EhbrsRubyUtils
8
+ module Bga
9
+ class Session < ::SimpleDelegator
10
+ class Player
11
+ include ::EhbrsRubyUtils::Bga::Urls
12
+ GAME_HISTORY_XPATH = '//h3[text() = "Games history"]'
13
+ common_constructor :session, :player_id
14
+
15
+ def tables
16
+ session.navigate.to game_stats_url
17
+ session.wait_for_element(xpath: GAME_HISTORY_XPATH)
18
+ ::EhbrsRubyUtils::Bga::Parsers::GameStats.from_content(session.current_source).data
19
+ end
20
+
21
+ # @return [Addressable::URI]
22
+ def game_stats_url
23
+ session.url("/gamestats?player=#{player_id}")
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ehbrs_ruby_utils/bga/parsers/table'
4
+ require 'ehbrs_ruby_utils/bga/table'
5
+ require 'ehbrs_ruby_utils/bga/urls'
6
+ require 'eac_ruby_utils/core_ext'
7
+
8
+ module EhbrsRubyUtils
9
+ module Bga
10
+ class Session < ::SimpleDelegator
11
+ class Table
12
+ include ::EhbrsRubyUtils::Bga::Urls
13
+ enable_method_class
14
+ enable_simple_cache
15
+ common_constructor :session, :table_id
16
+
17
+ def result
18
+ ::EhbrsRubyUtils::Bga::Table.new(
19
+ fetch_data
20
+ )
21
+ end
22
+
23
+ # @return [Addressable::URI]
24
+ def url
25
+ table_url(table_id)
26
+ end
27
+
28
+ private
29
+
30
+ def fetch_data
31
+ session.navigate.to url
32
+ { id: table_id }.merge(
33
+ ::EhbrsRubyUtils::Bga::Parsers::Table.from_content(session.current_source).data
34
+ )
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'aranha/selenium/session'
4
+ require 'eac_ruby_utils/core_ext'
5
+ require 'ehbrs_ruby_utils/bga/urls'
6
+
7
+ module EhbrsRubyUtils
8
+ module Bga
9
+ class Session < ::SimpleDelegator
10
+ include ::EhbrsRubyUtils::Bga::Urls
11
+ MESSAGE_ID = 'head_infomsg_1'
12
+
13
+ common_constructor :username, :password, super_args: -> { [::Aranha::Selenium::Session.new] }
14
+
15
+ # @return [String]
16
+ def message_info
17
+ wait_for_click(id: MESSAGE_ID).text
18
+ end
19
+
20
+ # @return [EhbrsRubyUtils::Bga::Session::Player]
21
+ def player(id)
22
+ ::EhbrsRubyUtils::Bga::Session::Player.new(self, id)
23
+ end
24
+
25
+ require_sub __FILE__, include_modules: true, require_mode: :kernel
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ehbrs_ruby_utils/bga/parsers/table/options'
4
+ require 'eac_ruby_utils/core_ext'
5
+
6
+ module EhbrsRubyUtils
7
+ module Bga
8
+ class Table
9
+ class Option
10
+ common_constructor :table, :data
11
+
12
+ ::EhbrsRubyUtils::Bga::Parsers::Table::Options.fields.each do |field|
13
+ define_method field.name do
14
+ data.fetch(field.name)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ehbrs_ruby_utils/bga/parsers/table/players'
4
+ require 'eac_ruby_utils/core_ext'
5
+
6
+ module EhbrsRubyUtils
7
+ module Bga
8
+ class Table
9
+ class Player
10
+ common_constructor :table, :data
11
+
12
+ ::EhbrsRubyUtils::Bga::Parsers::Table::Players.fields.each do |field|
13
+ define_method field.name do
14
+ data.fetch(field.name)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ehbrs_ruby_utils/bga/parsers/table/options'
4
+ require 'ehbrs_ruby_utils/bga/urls'
5
+ require 'eac_ruby_utils/core_ext'
6
+
7
+ module EhbrsRubyUtils
8
+ module Bga
9
+ class Table
10
+ include ::EhbrsRubyUtils::Bga::Urls
11
+ enable_simple_cache
12
+ common_constructor :data
13
+
14
+ SET_ITEMS = %i[options players].freeze
15
+
16
+ ([:id] + ::EhbrsRubyUtils::Bga::Parsers::Table.fields.map(&:name) - SET_ITEMS)
17
+ .each do |field|
18
+ define_method field do
19
+ data.fetch(field)
20
+ end
21
+ end
22
+
23
+ # @return [Addressable::URI]
24
+ def url
25
+ table_url(id)
26
+ end
27
+
28
+ private
29
+
30
+ SET_ITEMS.each do |item|
31
+ define_method "#{item}_uncached" do
32
+ data.fetch(item).map do |item_data|
33
+ self.class.const_get(item.to_s.singularize.camelize).new(self, item_data)
34
+ end
35
+ end
36
+ end
37
+
38
+ require_sub __FILE__
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'aranha/selenium/session'
4
+ require 'eac_ruby_utils/core_ext'
5
+
6
+ module EhbrsRubyUtils
7
+ module Bga
8
+ module Urls
9
+ common_concern
10
+
11
+ module InstanceMethods
12
+ ROOT_URL = 'https://en.boardgamearena.com'
13
+
14
+ # @param suffix [String]
15
+ # @return [Addressable::URI]
16
+ def build_url(suffix)
17
+ root_url + suffix
18
+ end
19
+
20
+ # @return [Addressable::URI]
21
+ def root_url
22
+ ROOT_URL.to_uri
23
+ end
24
+
25
+ # @return [Addressable::URI]
26
+ def table_url(table_id)
27
+ build_url("/table?table=#{table_id}")
28
+ end
29
+ end
30
+
31
+ extend InstanceMethods
32
+ end
33
+ end
34
+ end
@@ -23,6 +23,11 @@ module EhbrsRubyUtils
23
23
  end
24
24
  end
25
25
  end
26
+
27
+ # @return [EacRubyUtils::Envs::Executable]
28
+ def mudslide_uncached
29
+ env.executable('mudslide', exec_args: %w[npx mudslide@latest], check_args: %w[--version])
30
+ end
26
31
  end
27
32
  end
28
33
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EhbrsRubyUtils
4
- VERSION = '0.22.0'
4
+ VERSION = '0.23.0'
5
5
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ehbrs_ruby_utils/bga/parsers/game_stats'
4
+
5
+ ::RSpec.describe ::EhbrsRubyUtils::Bga::Parsers::GameStats do
6
+ include_examples 'source_target_fixtures', __FILE__
7
+ end