lx_data_validation 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5d57c15e760b4b13cd67d124d6e0c66c1f5d603c
4
+ data.tar.gz: 05207e5b3e1d45257a60e02cf4da04bf8b88eab0
5
+ SHA512:
6
+ metadata.gz: 7183dc0078c905252f2a9179ff5a05637fbeb863e3de117c672f74bec84ce522574a55d30b7b32588dcb9f604ccc276df709ca53ffb6752d1af09bc8211a4901
7
+ data.tar.gz: 4473bce485ba3e274b347ead5e9a0e0f1c47f6f3e73c6058649ca400b07fe5f8470ac6cf523199519de291bf8e1b3debff8b41001dd5268fc2dd56a62823d821
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .idea/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.0.0
5
+ before_install: gem install bundler -v 1.12.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in data_validation.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Roger Tong
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,37 @@
1
+ # DataValidation
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/data_validation`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'data_validation'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install lx_data_validation
21
+
22
+ ## Usage
23
+
24
+
25
+ ## Development
26
+
27
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
28
+
29
+ ## Contributing
30
+
31
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/data_validation.
32
+
33
+
34
+ ## License
35
+
36
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
37
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/compare ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'data_validation'
4
+
5
+ DataValidation.compare_with_season ARGV[0]
data/config/hosts.yml ADDED
@@ -0,0 +1,8 @@
1
+ int:
2
+ web_request_host: http://int-laxpower-phpadmin-01w.dev.activenetwork.com
3
+ api_request_host: https://awmobile-vip.qa.aw.dev.activenetwork.com
4
+
5
+ prod:
6
+ web_request_host: http://php.admin.laxpower.com
7
+ api_request_host: https://awmobile.active.com
8
+
@@ -0,0 +1,39 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'data_validation/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "lx_data_validation"
8
+ spec.version = DataValidation::VERSION
9
+ spec.authors = ["Roger Tong"]
10
+ spec.email = ["Roger.Tong@activenetwork.com", "tomtongt@live.com"]
11
+
12
+ spec.summary = "Data validation for LaxPower"
13
+ spec.description = "The validation is to compare values between web page values and mobile api responses"
14
+ spec.homepage = "https://gitlab.dev.activenetwork.com/rtong/data-validation-for-laxpower"
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RupwdbyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ # if spec.respond_to?(:metadata)
20
+ # spec.metadata['allowed_push_host'] = "input later"
21
+ # else
22
+ # raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
23
+ # end
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
+ spec.bindir = "bin"
27
+ spec.executables = ["compare"]
28
+ spec.require_paths = ["lib"]
29
+
30
+ spec.required_ruby_version = '>= 2.1.4'
31
+
32
+ spec.add_development_dependency "bundler", "~> 1.12"
33
+ spec.add_development_dependency "rake", "~> 10.0"
34
+ spec.add_development_dependency "rspec", "~> 3.0"
35
+
36
+ spec.add_runtime_dependency 'nokogiri', '1.6.6.2'
37
+ spec.add_runtime_dependency 'httparty', '0.8.1'
38
+
39
+ end
@@ -0,0 +1,169 @@
1
+ require 'data_validation/data_access'
2
+ require 'logger'
3
+
4
+ module DataValidation
5
+ module Comparison
6
+ class ComparisonBase
7
+ attr_reader :web_url, :logger_name, :category, :season, :division_id
8
+
9
+ def initialize(web_url)
10
+ @web_url = web_url
11
+ end
12
+
13
+ def compare
14
+ if api_path.nil?
15
+ raise 'Please define api_path'
16
+ end
17
+
18
+ if field_array.nil?
19
+ raise 'Please define field_array'
20
+ end
21
+
22
+ data_access = DataValidation::DataAccess.new(web_url, DataValidation.api_request_host + api_path, determine_request_body_and_logger_name)
23
+
24
+ puts 'requesting web page...'
25
+ web_data = data_access.get_main_table_data
26
+ puts 'requesting mobile api data: ' + DataValidation.api_request_host + api_path
27
+ api_data = data_access.get_response_from_mobile_api
28
+
29
+ if web_data.length != api_data['results']['results']['total']
30
+ logger.error "The record size between web page and api data is not the same: #{web_data.length} -- #{api_data['results']['results']['total']}"
31
+ return
32
+ end
33
+
34
+ web_data.each_with_index do |item, index|
35
+ team = api_data['results']['results']['teams'][index]
36
+
37
+ i = 0
38
+ field_array.each do |filed_name|
39
+
40
+ if filed_name.is_a? String
41
+ team_value = team[filed_name]
42
+ elsif filed_name.is_a? Array
43
+ team_value = team[filed_name[0]][filed_name[1]]
44
+ else
45
+ i += 1
46
+ next
47
+ end
48
+
49
+ if item.length < field_array.length && empty_field && empty_field == filed_name ## when the field is empty in the table
50
+ logger.error "team #{item[0]}'s #{filed_name} is not empty: #{team_value}" unless (team_value == 0 || team_value.nil?)
51
+ next
52
+ end
53
+
54
+
55
+ unless (team_value.is_a?(String) && team_value.include?(item[i])) ||
56
+ (team_value.is_a?(Float) && team_value == item[i].to_f) ||
57
+ (team_value.is_a?(Integer) && team_value == item[i].to_i)
58
+
59
+ logger.error "team #{item[0]}'s #{filed_name} is not correct: #{item[i]} -- #{team_value}"
60
+ end
61
+
62
+ i += 1
63
+ end
64
+
65
+ end
66
+ end
67
+
68
+ def compare_conf_standings(api_data, data_access)
69
+ puts 'Start to compare conf ranking tables'
70
+ conf_standing_data = data_access.conf_standing_data
71
+ conf_standing_data.each do |standing|
72
+ full_conf = ''
73
+ # puts standing.to_s
74
+ standing.each_with_index do |record, i|
75
+ if i == 0
76
+ state = record[0]
77
+ team_class = record[1]
78
+ conf = record[2]
79
+ full_conf = "#{state}, #{team_class}, #{conf}"
80
+
81
+ api_data = data_access.get_response_from_mobile_api_with_params(conf_rank_api_url, %Q|{"season": "#{season}", "conference": {"category": "#{category}", "conference": "#{conf}", "divisionId": #{division_id.to_i}, "state": "#{state}", "teamClass": "#{team_class}"}, "currPage": 1, "pageSize": 1000}|)
82
+
83
+ if api_data['results']['results']['total'] != standing.length - 1
84
+ logger.error "standing for #{full_conf} has incorrect length: #{standing.length - 1} : #{api_data['results']['results']['total']}"
85
+ break
86
+ end
87
+ else
88
+
89
+ team_data = api_data['results']['results']['teams'][i - 1]
90
+
91
+ record.each_with_index do |item, index|
92
+ if index == 0 && item.to_i != team_data['rank']
93
+ elsif index == 1 && item.to_f != team_data['powerRating']
94
+ logger.error "team #{i} has incorrect powerRating in #{full_conf}: #{item.to_f} -- #{team_data['powerRating']}"
95
+ elsif index == 2 && item.to_i != team_data['conference']['wins']
96
+ logger.error "team #{i} has incorrect conference wins in #{full_conf}: #{item.to_i} -- #{team_data['conference']['wins']}"
97
+ elsif index == 3 && item.to_i != team_data['conference']['losses']
98
+ logger.error "team #{i} has incorrect conference losses in #{full_conf}: #{item.to_i} -- #{team_data['conference']['losses']}"
99
+ elsif index == 4 && item.to_i != team_data['conference']['ties']
100
+ logger.error "team #{i} has incorrect conference ties in #{full_conf}: #{item.to_i} -- #{team_data['conference']['ties']}"
101
+ elsif index == 5 && item.to_f != team_data['winLossConf']
102
+ logger.error "team #{i} has incorrect winLossConf in #{full_conf}: #{item.to_f} -- #{team_data['winLossConf']}"
103
+ elsif index == 6 && item.to_i != team_data['total']['wins']
104
+ logger.error "team #{i} has incorrect total wins in #{full_conf}: #{item.to_i} -- #{team_data['total']['wins']}"
105
+ elsif index == 7 && item.to_i != team_data['total']['losses']
106
+ logger.error "team #{i} has incorrect total losses in #{full_conf}: #{item.to_i} -- #{team_data['total']['losses']}"
107
+ elsif index == 8 && item.to_i != team_data['total']['ties']
108
+ logger.error "team #{i} has incorrect total ties in #{full_conf}: #{item.to_i} -- #{team_data['total']['ties']}"
109
+ elsif index == 9 && item.to_f != team_data['winLossTotal']
110
+ logger.error "team #{i} has incorrect winLossTotal in #{full_conf}: #{item.to_f} -- #{team_data['winLossTotal']}"
111
+ end
112
+ end
113
+ end
114
+
115
+ end
116
+ end
117
+ end
118
+
119
+ protected
120
+
121
+ def api_path
122
+
123
+ end
124
+
125
+ def field_array
126
+
127
+ end
128
+
129
+ def empty_field
130
+
131
+ end
132
+
133
+ private
134
+
135
+ def logger
136
+ @logger ||= begin
137
+ tokens = logger_name.split('/')
138
+ 1.upto(tokens.size - 1) do |n|
139
+ dir = tokens[0...n].join('/')
140
+ Dir.mkdir(dir) unless Dir.exist?(dir)
141
+ end
142
+ Logger.new File.new(logger_name, 'w')
143
+ end
144
+ end
145
+
146
+ def determine_request_body_and_logger_name
147
+ @category = if web_url.match /bingrl/
148
+ 'GIRLS'
149
+ elsif web_url.match /binboy/
150
+ 'BOYS'
151
+ elsif web_url.match /binmen/
152
+ 'MEN'
153
+ elsif web_url.match /binwom/
154
+ 'WOMEN'
155
+ end
156
+
157
+ @season = "20#{web_url.match(/update(..)/)[1]}"
158
+
159
+ @division_id = web_url.match(/(\d+)\.php/)[1].to_i
160
+
161
+ operation = web_url.match(/\/([a-z]+)\d+.php/)[1]
162
+
163
+ @logger_name = "log/#{season}/#{category.downcase}/#{operation}/#{operation}_#{season}_#{category}_#{division_id}.log"
164
+
165
+ %Q|{"category":"#{category}","season":#{season},"divisionId":#{division_id},"currPage":1,"pageSize":1000}|
166
+ end
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,37 @@
1
+ require 'data_validation/comparison/div_ranking_pr_comparison'
2
+ require 'data_validation/comparison/ranking_table_mw_sos_comparison'
3
+ require 'data_validation/comparison/ranking_table_mw_rpi_comparison'
4
+ require 'data_validation/comparison/div_ranking_wl_comparison'
5
+ require 'data_validation/comparison/ranking_table_mw_qw_comparison'
6
+ require 'data_validation/comparison/ranking_table_mw_poll_comparison'
7
+ require 'data_validation/comparison/ranking_table_mw_trend_comparison'
8
+ require 'data_validation/comparison/ranking_table_mw_tsi_comparison'
9
+ require 'data_validation/comparison/ranking_table_mw_pr_comparison'
10
+
11
+ module DataValidation
12
+ module Comparison
13
+ class ComparisonFactory
14
+ def self.get_comparison(url)
15
+ if url.match /update\d\d\/bin(boy|grl)\/rating\d+.php/ # division Computer Rating page for boys/girls
16
+ return DivRankingPrComparison.new url
17
+ elsif url.match /update\d\d\/bin\S+\/rating\d+.php/ # division Computer Rating page for men and women
18
+ return RankingTableMwPrComparison.new url
19
+ elsif url.match /update\d\d\/bin\S+\/sos\d+.php/ # division Strength of Schedule page for boys/girls
20
+ return RankingTableMwSosComparison.new url
21
+ elsif url.match /update\d\d\/bin\S+\/rpi\d+.php/ # division RPI Rankings page for boys/girls
22
+ return RankingTableMwRpiComparison.new url
23
+ elsif url.match /update\d\d\/bin\S+\/wl\d+.php/ # division win-loss factor page for boys/girls
24
+ return DivRankingWlComparison.new url
25
+ elsif url.match /update\d\d\/bin\S+\/qwf\d+.php/ # division Quality Win Factor page for boys/girls
26
+ return RankingTableMwQwComparison.new url
27
+ elsif url.match /update\d\d\/bin\S+\/poll\d+.php/ # Poll page for collage division
28
+ return RankingTableMwPollComparison.new url
29
+ elsif url.match /update\d\d\/bin\S+\/trend\d+.php/ # Trend page for collage division
30
+ return RankingTableMwTrendComparison.new url
31
+ elsif url.match /update\d\d\/bin\S+\/tsi\d+.php/ # Trend page for collage division
32
+ return RankingTableMwTsiComparison.new url
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,72 @@
1
+ require 'data_validation/comparison/comparison_base'
2
+
3
+ module DataValidation
4
+ module Comparison
5
+ class RankingTableMwPollComparison < ComparisonBase
6
+
7
+ def compare
8
+
9
+ if api_path.nil?
10
+ raise 'Please define api_path'
11
+ end
12
+
13
+ data_access = DataValidation::DataAccess.new(web_url, DataValidation.api_request_host + api_path, determine_request_body_and_logger_name)
14
+
15
+ puts 'requesting web page...'
16
+ web_data = data_access.get_main_table_data
17
+ puts 'requesting mobile api data: ' + DataValidation.api_request_host + api_path
18
+ api_data = data_access.get_response_from_mobile_api
19
+
20
+ if web_data.length != api_data['results']['results']['total']
21
+ logger.error "The record size between web page and api data is not the same: #{web_data.length} -- #{api_data['results']['results']['total']}"
22
+ return
23
+ end
24
+
25
+ web_data.each_with_index do |item, index|
26
+ team = api_data['results']['results']['teams'][index]
27
+
28
+ field_array.each_with_index do |filed_name, index|
29
+ if filed_name.is_a? String
30
+ team_value = team[filed_name]
31
+ elsif filed_name.is_a? Array
32
+ team_value = team[filed_name[0]][filed_name[1]]
33
+ else
34
+ next
35
+ end
36
+
37
+ unless (team_value.is_a?(String) && team_value.include?(item[index])) ||
38
+ (team_value.is_a?(Float) && team_value == item[index].to_f) ||
39
+ (team_value.is_a?(Integer) && team_value == item[index].to_i)
40
+
41
+ logger.error "team #{item[0]}'s #{filed_name} is not correct: #{item[index]} -- #{team_value}"
42
+ end
43
+ end
44
+
45
+ end
46
+ end
47
+
48
+ end
49
+ end
50
+
51
+ def determine_request_body_and_logger_name
52
+ category = if web_url.match /bingrl/
53
+ 'GIRLS'
54
+ elsif web_url.match /binboy/
55
+ 'BOYS'
56
+ elsif web_url.match /binmen/
57
+ 'MEN'
58
+ elsif web_url.match /binwom/
59
+ 'WOMEN'
60
+ end
61
+
62
+ season = "20#{web_url.match(/update(..)/)[1]}"
63
+
64
+ division_id = web_url.match(/(\d+)\.php/)[1].to_i
65
+
66
+ operation = web_url.match(/\/([a-z]+)\d+.php/)[1]
67
+
68
+ @logger_name = "log/#{season}/#{category.downcase}/#{operation}/#{operation}_#{season}_#{category}_#{division_id}.log"
69
+
70
+ %Q|{"season":"#{season}", "conference": {"category": "#{category}",} "divisionId":#{division_id},"currPage":1,"pageSize":1000}|
71
+ end
72
+ end
@@ -0,0 +1,78 @@
1
+ require 'data_validation/comparison/comparison_base'
2
+
3
+ module DataValidation
4
+ module Comparison
5
+ class DivRankingPrComparison < ComparisonBase
6
+
7
+ def api_path
8
+ '/rest/LaxPower/divisionRankingPr'
9
+ end
10
+
11
+ def field_array
12
+ ['rank', 'teamName', 'powerRating', 'regInPr', 'correction', 'championship', 'winLossTotal', %w|record wins|, %w|record losses|, %w|record ties|]
13
+ end
14
+
15
+ def empty_field
16
+ ''
17
+ end
18
+
19
+ def compare
20
+
21
+ data_access = DataValidation::DataAccess.new(web_url, DataValidation.api_request_host + api_path, determine_request_body_and_logger_name)
22
+
23
+ puts 'requesting web page...'
24
+ web_data = data_access.get_main_table_data
25
+ puts 'requesting mobile api data: ' + DataValidation.api_request_host + api_path
26
+ api_data = data_access.get_response_from_mobile_api
27
+
28
+ if web_data.length != api_data['results']['results']['total']
29
+ logger.error "The record size between web page and api data is not the same: #{web_data.length} -- #{api_data['results']['results']['total']}"
30
+ return
31
+ end
32
+
33
+ ## compare first table
34
+ web_data.each_with_index do |item, index|
35
+ team = api_data['results']['results']['teams'][index]
36
+
37
+ i = 0
38
+ field_array.each do |filed_name|
39
+
40
+ if filed_name.is_a? String
41
+ team_value = team[filed_name]
42
+ elsif filed_name.is_a? Array
43
+ team_value = team[filed_name[0]][filed_name[1]]
44
+ else
45
+ next
46
+ end
47
+
48
+ if item.length < field_array.length && empty_field && empty_field == filed_name ## when the field is possibly empty in the table
49
+ logger.error "team #{item[0]}'s #{filed_name} is not empty: #{team_value}" unless (team_value == 0 || team_value.nil?)
50
+ next
51
+ end
52
+
53
+
54
+ unless (team_value.is_a?(String) && team_value.include?(item[i])) ||
55
+ (team_value.is_a?(Float) && team_value == item[i].to_f) ||
56
+ (team_value.is_a?(Integer) && team_value == item[i].to_i)
57
+
58
+ logger.error "team #{item[0]}'s #{filed_name} is not correct: #{item[i]} -- #{team_value}"
59
+ end
60
+
61
+ i += 1
62
+ end
63
+
64
+ end
65
+
66
+ ## compare standing tables
67
+ compare_conf_standings(api_data, data_access)
68
+ end
69
+
70
+
71
+
72
+ def conf_rank_api_url
73
+ DataValidation.api_request_host + '/rest/LaxPower/conferenceRankingTable'
74
+ end
75
+
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,17 @@
1
+ require 'data_validation/comparison/comparison_base'
2
+
3
+ module DataValidation
4
+ module Comparison
5
+ class DivRankingWlComparison < ComparisonBase
6
+
7
+ def api_path
8
+ '/rest/LaxPower/divisionRankingWl'
9
+ end
10
+
11
+ def field_array
12
+ ['rank', 'teamName', 'rank', 'winLossTotal', 'rankDivision', 'winLossDivision', 'rankDate', 'winLossDate', 'rankRoad', 'winLossRoad', %w|record wins|, %w|record losses|, %w|record ties|]
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ require 'data_validation/comparison/comparison_base'
2
+
3
+ module DataValidation
4
+ module Comparison
5
+ class RankingTableMwPollComparison < ComparisonBase
6
+
7
+ def api_path
8
+ '/rest/LaxPower/rankingTableMWpoll'
9
+ end
10
+
11
+ def field_array
12
+ ['rank', 'teamName', %w|record wins|, %w|record losses|, %w|record ties|, 'pollPoint', 'pollFirst', 'lastWeek']
13
+ end
14
+
15
+ def empty_field
16
+ 'pollFirst'
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,74 @@
1
+ require 'data_validation/comparison/comparison_base'
2
+
3
+ module DataValidation
4
+ module Comparison
5
+ class RankingTableMwPrComparison < ComparisonBase
6
+
7
+ def api_path
8
+ '/rest/LaxPower/rankingTableMWpr'
9
+ end
10
+
11
+ def field_array
12
+ ['rank', 'teamName', 'powerRating', 'pollRank', 'sosRank', 'rpiRank', 'qwfRank', 'tsiRank', %w|record wins|, %w|record losses|, %w|record ties|]
13
+ end
14
+
15
+ def empty_field
16
+ 'pollRank'
17
+ end
18
+
19
+ def compare
20
+ data_access = DataValidation::DataAccess.new(web_url, DataValidation.api_request_host + api_path, determine_request_body_and_logger_name)
21
+
22
+ puts 'requesting web page...'
23
+ web_data = data_access.get_main_table_data
24
+ puts 'requesting mobile api data: ' + DataValidation.api_request_host + api_path
25
+ api_data = data_access.get_response_from_mobile_api
26
+
27
+ if web_data.length != api_data['results']['results']['total']
28
+ logger.error "The record size between web page and api data is not the same: #{web_data.length} -- #{api_data['results']['results']['total']}"
29
+ return
30
+ end
31
+
32
+ ## compare first table
33
+ web_data.each_with_index do |item, index|
34
+ team = api_data['results']['results']['teams'][index]
35
+
36
+ i = 0
37
+ field_array.each do |filed_name|
38
+
39
+ if filed_name.is_a? String
40
+ team_value = team[filed_name]
41
+ elsif filed_name.is_a? Array
42
+ team_value = team[filed_name[0]][filed_name[1]]
43
+ else
44
+ next
45
+ end
46
+
47
+ if item.length < field_array.length && empty_field && empty_field == filed_name ## when the field is possibly empty in the table
48
+ logger.error "team #{item[0]}'s #{filed_name} is not empty: #{team_value}" unless (team_value == 0 || team_value.nil?)
49
+ next
50
+ end
51
+
52
+
53
+ unless (team_value.is_a?(String) && team_value.include?(item[i])) ||
54
+ (team_value.is_a?(Float) && team_value == item[i].to_f) ||
55
+ (team_value.is_a?(Integer) && team_value == item[i].to_i)
56
+
57
+ logger.error "team #{item[0]}'s #{filed_name} is not correct: #{item[i]} -- #{team_value}"
58
+ end
59
+
60
+ i += 1
61
+ end
62
+
63
+ end
64
+
65
+ compare_conf_standings api_data, data_access
66
+ end
67
+
68
+ def conf_rank_api_url
69
+ DataValidation.api_request_host + '/rest/LaxPower/conferenceRankingTable'
70
+ end
71
+
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,17 @@
1
+ require 'data_validation/comparison/comparison_base'
2
+
3
+ module DataValidation
4
+ module Comparison
5
+ class RankingTableMwQwComparison < ComparisonBase
6
+
7
+ def api_path
8
+ '/rest/LaxPower/rankingTableMWqw'
9
+ end
10
+
11
+ def field_array
12
+ ['rank', 'teamName', 'qwPrRank', 'qualityWinsPr', nil, 'qualityWinsPoll', 'qwRpiRank', 'qualityWinsRpi', %w|record wins|, %w|record losses|, %w|record ties|]
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ require 'data_validation/comparison/comparison_base'
2
+
3
+ module DataValidation
4
+ module Comparison
5
+ class RankingTableMwRpiComparison < ComparisonBase
6
+
7
+ def api_path
8
+ '/rest/LaxPower/rankingTableMWrpi'
9
+ end
10
+
11
+ def field_array
12
+ ['rank', 'teamName', nil, 'rpi', 'signWinsRank', 'signficantWins', 'signLossRank', 'signficantLosses',
13
+ %w|recordTotal wins|, %w|recordTotal losses|, %w|recordTotal ties|,
14
+ %w|recordRoad wins|, %w|recordRoad losses|, %w|recordRoad ties|,
15
+ %w|recordNeutral wins|, %w|recordNeutral losses|, %w|recordNeutral ties|,
16
+ %w|recordHome wins|, %w|recordHome losses|, %w|recordHome ties|]
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ require 'data_validation/comparison/comparison_base'
2
+
3
+ module DataValidation
4
+ module Comparison
5
+ class RankingTableMwSosComparison < ComparisonBase
6
+
7
+ def api_path
8
+ '/rest/LaxPower/rankingTableMWsos'
9
+ end
10
+
11
+ def field_array
12
+ ['rank', 'teamName', 'totalGames', nil, 'sosAverage', 'sosWeightedRank', 'sosWeighted', 'sosRpiRank', 'sosRpi', %w|record wins|, %w|record losses|, %w|record ties|]
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ require 'data_validation/comparison/comparison_base'
2
+
3
+ module DataValidation
4
+ module Comparison
5
+ class RankingTableMwTrendComparison < ComparisonBase
6
+
7
+ def api_path
8
+ '/rest/LaxPower/rankingTableMWtrend
9
+ '
10
+ end
11
+
12
+ def field_array
13
+ ['rank', 'teamName', %w|record wins|, %w|record losses|, %w|record ties|, 'trend']
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,21 @@
1
+ require 'data_validation/comparison/comparison_base'
2
+
3
+ module DataValidation
4
+ module Comparison
5
+ class RankingTableMwTsiComparison < ComparisonBase
6
+
7
+ def api_path
8
+ '/rest/LaxPower/rankingTableMWtsi'
9
+ end
10
+
11
+ def field_array
12
+ ['rank', 'teamName', 'tsi', 'pollRank', 'prRank', 'rpiRank', 'sosRank', 'qwf', 'loss', 'trend', %w|record wins|, %w|record losses|, %w|record ties|]
13
+ end
14
+
15
+ def empty_field
16
+ 'pollRank'
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,140 @@
1
+ require 'nokogiri'
2
+ require 'httparty'
3
+ require 'open-uri'
4
+
5
+ module DataValidation
6
+ class DataAccess
7
+
8
+ attr_reader :html_url, :api_url, :api_body, :conf_standing_data
9
+
10
+ def initialize(html_url, api_url, api_body)
11
+ @html_url = html_url
12
+ @api_url = api_url
13
+ @api_body = api_body
14
+ end
15
+
16
+ def get_main_table_data
17
+ doc = Nokogiri::HTML(open(html_url))
18
+
19
+ if html_url.match /rating/
20
+ extract_conf_standing_data(doc)
21
+ end
22
+
23
+ team_names = doc.search('div.cs1 div.cs1 a').map { |node| node.text if /^[A-Z\d]+.PHP$/.match(node.attr('href')) }.compact ## extract team names
24
+
25
+ doc.search('div.cs1 div.cs1 a').remove ## then remove all links from the doc
26
+
27
+ index = 0
28
+ doc.search('div.cs1 div.cs1').text.lines.map do |line|
29
+ if /^\s*(?<rank>\d+)\s+(?<rest>.*)/ =~ line
30
+ data_array = ([rank] << team_names[index]) + rest.split(' ')
31
+ index += 1
32
+ data_array
33
+ end
34
+ end.compact
35
+ end
36
+
37
+ def extract_conf_standing_data(doc)
38
+ category = if html_url.match /bingrl/
39
+ 'GIRLS'
40
+ elsif html_url.match /binboy/
41
+ 'BOYS'
42
+ elsif html_url.match /binmen/
43
+ 'MEN'
44
+ elsif html_url.match /binwom/
45
+ 'WOMEN'
46
+ end
47
+
48
+ season = "20#{html_url.match(/update(..)/)[1]}"
49
+
50
+ div_id = html_url.match(/(\d+)\.php/)[1].to_i
51
+
52
+ conf_data = get_conference(season, category, div_id)['results']['results']['conferences']
53
+
54
+ # is_for_mw_pr = html_url.include?('binmen') || html_url.include?('binwomen')
55
+
56
+ ## only rating page has conf standing tables
57
+ doc.search('div.laxcss a').remove ## remove team names from conf standing tables
58
+ @conf_standing_data = []
59
+ conf_standing_record = []
60
+ lines = doc.search('div.laxcs1, div.laxcss').text.lines
61
+
62
+ conf_data_index = 0
63
+ lines.each_with_index do |line, index|
64
+ if line.match /^\s[A-Z]/
65
+ if conf_standing_record.length > 0 ## it's a new conf standing table
66
+ @conf_standing_data << conf_standing_record
67
+ conf_standing_record = []
68
+ end
69
+
70
+ conf = conf_data[conf_data_index]
71
+
72
+ if conf.nil?
73
+ puts 'No independent conf data'
74
+ @conf_standing_data << conf_standing_record
75
+ break
76
+ end
77
+
78
+ conf_standing_record << [conf['state'], conf['teamClass'], conf['conference']]
79
+
80
+ conf_data_index += 1
81
+ elsif /^\s*\d+\s+/.match line
82
+ conf_standing_record << line.split(' ')
83
+ end
84
+
85
+ if (index == lines.length - 1)
86
+ @conf_standing_data << conf_standing_record
87
+ end
88
+ end
89
+ end
90
+
91
+ def get_response_from_mobile_api
92
+ HTTParty.post(api_url, headers: {'Content-Type' => 'application/json'}, body: api_body)
93
+ end
94
+
95
+ def get_response_from_mobile_api_with_params(url, body)
96
+ HTTParty.post(url, headers: {'Content-Type' => 'application/json'}, body: body)
97
+ end
98
+
99
+ def get_conference(season, category, div_id)
100
+ puts "get conference data for #{season}, #{category}, #{div_id} from " + DataValidation.api_request_host + '/rest/LaxPower/getConferences'
101
+ HTTParty.post(DataValidation.api_request_host + '/rest/LaxPower/getConferences',
102
+ headers: {'Content-Type' => 'application/json'},
103
+ body: %Q|{"season": "#{season}","category": "#{category}", "divisionId": #{div_id}}|)
104
+ end
105
+
106
+ def self.get_high_school_div_stat_urls(season='17', category='boys')
107
+ is_for_hs = category == 'boys' || category == 'girls'
108
+ high_school_div_stat_main_url = if is_for_hs
109
+ "#{DataValidation.web_request_host}/common/hs_#{category}.php"
110
+ else
111
+ "#{DataValidation.web_request_host}/common/college_#{category}.php"
112
+ end
113
+ doc = Nokogiri::HTML(open(high_school_div_stat_main_url))
114
+ urls = doc.search('div#content_well a[href*=rating]').map do |item|
115
+ href = item.attr('href')
116
+ if href.match /rating\d\d/
117
+ href.sub!('..', DataValidation.web_request_host)
118
+ href.sub!('update17', "update#{season}") if season!= '17'
119
+ href
120
+ end
121
+ end.compact
122
+
123
+ final_urls = [] + urls
124
+ ## append other metrics e.g. sos, rpi
125
+ if is_for_hs
126
+ %w|sos rpi wl qwf|.each { |stat_name| final_urls += replace_with_stat_name(urls, stat_name) }
127
+ else
128
+ %w|tsi poll rpi sos qwf trend|.each { |stat_name| final_urls += replace_with_stat_name(urls, stat_name) }
129
+ end
130
+ puts "totally #{final_urls.length} urls for #{season}, #{category}"
131
+ final_urls
132
+ end
133
+
134
+ def self.replace_with_stat_name urls, stat_name
135
+ urls.map do |url|
136
+ url.sub 'rating', stat_name
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,3 @@
1
+ module DataValidation
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,49 @@
1
+ require 'data_validation/comparison/comparison_factory'
2
+ require 'data_validation/data_access'
3
+ require 'yaml'
4
+
5
+ module DataValidation
6
+ class << self
7
+
8
+ def web_request_host
9
+ @web_request_host ||= begin
10
+ YAML.load_file('config/hosts.yml')['prod']['web_request_host']
11
+ end
12
+ end
13
+
14
+ def api_request_host
15
+ @api_request_host ||= begin
16
+ YAML.load_file('config/hosts.yml')['prod']['api_request_host']
17
+ end
18
+ end
19
+
20
+ def configure_with_env(env)
21
+ yaml_config = YAML.load_file('config/hosts.yml')
22
+ hash_config = yaml_config[env]
23
+ @web_request_host = hash_config['web_request_host']
24
+ @api_request_host = hash_config['api_request_host']
25
+ end
26
+
27
+ def compare_with_season_and_category(season = '17', category = 'boys')
28
+ web_urls = DataAccess.get_high_school_div_stat_urls season, category
29
+ web_urls.each do |url|
30
+ compare_with_url url
31
+ end
32
+ end
33
+
34
+ def compare_with_season(season = '17')
35
+ %w|men women boys girls|.each { |category| compare_with_season_and_category season, category }
36
+ end
37
+
38
+ def compare_with_url(url)
39
+ puts "Start validation of web url: #{url}"
40
+
41
+ comparison = DataValidation::Comparison::ComparisonFactory.get_comparison(url)
42
+ comparison.compare
43
+
44
+ puts "Complete validation of web url: #{url}"
45
+ puts '=============================='
46
+ end
47
+ end
48
+
49
+ end
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lx_data_validation
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Roger Tong
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-02-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.12'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: nokogiri
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 1.6.6.2
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 1.6.6.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: httparty
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 0.8.1
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 0.8.1
83
+ description: The validation is to compare values between web page values and mobile
84
+ api responses
85
+ email:
86
+ - Roger.Tong@activenetwork.com
87
+ - tomtongt@live.com
88
+ executables:
89
+ - compare
90
+ extensions: []
91
+ extra_rdoc_files: []
92
+ files:
93
+ - ".gitignore"
94
+ - ".rspec"
95
+ - ".travis.yml"
96
+ - Gemfile
97
+ - LICENSE.txt
98
+ - README.md
99
+ - Rakefile
100
+ - bin/compare
101
+ - config/hosts.yml
102
+ - data_validation.gemspec
103
+ - lib/data_validation.rb
104
+ - lib/data_validation/comparison/comparison_base.rb
105
+ - lib/data_validation/comparison/comparison_factory.rb
106
+ - lib/data_validation/comparison/conference_ranking_table_comparison.rb
107
+ - lib/data_validation/comparison/div_ranking_pr_comparison.rb
108
+ - lib/data_validation/comparison/div_ranking_wl_comparison.rb
109
+ - lib/data_validation/comparison/ranking_table_mw_poll_comparison.rb
110
+ - lib/data_validation/comparison/ranking_table_mw_pr_comparison.rb
111
+ - lib/data_validation/comparison/ranking_table_mw_qw_comparison.rb
112
+ - lib/data_validation/comparison/ranking_table_mw_rpi_comparison.rb
113
+ - lib/data_validation/comparison/ranking_table_mw_sos_comparison.rb
114
+ - lib/data_validation/comparison/ranking_table_mw_trend_comparison.rb
115
+ - lib/data_validation/comparison/ranking_table_mw_tsi_comparison.rb
116
+ - lib/data_validation/data_access.rb
117
+ - lib/data_validation/version.rb
118
+ homepage: https://gitlab.dev.activenetwork.com/rtong/data-validation-for-laxpower
119
+ licenses:
120
+ - MIT
121
+ metadata: {}
122
+ post_install_message:
123
+ rdoc_options: []
124
+ require_paths:
125
+ - lib
126
+ required_ruby_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: 2.1.4
131
+ required_rubygems_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ requirements: []
137
+ rubyforge_project:
138
+ rubygems_version: 2.4.5
139
+ signing_key:
140
+ specification_version: 4
141
+ summary: Data validation for LaxPower
142
+ test_files: []
143
+ has_rdoc: