in_or_out 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.rvmrc +53 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +71 -0
- data/Rakefile +7 -0
- data/config/analyser.yml +1 -0
- data/data/team_shortcode_data.yml +18 -0
- data/in_or_out.gemspec +31 -0
- data/lib/in_or_out.rb +23 -0
- data/lib/in_or_out/models/match.rb +45 -0
- data/lib/in_or_out/models/player.rb +61 -0
- data/lib/in_or_out/models/player_extractor.rb +92 -0
- data/lib/in_or_out/models/scraper.rb +15 -0
- data/lib/in_or_out/models/shortcode_converter.rb +21 -0
- data/lib/in_or_out/models/team.rb +8 -0
- data/lib/in_or_out/version.rb +3 -0
- data/spec/data/finialised_teams.html +3405 -0
- data/spec/data/unfinialised_interchange.html +3360 -0
- data/spec/in_and_out/models/match_spec.rb +86 -0
- data/spec/in_and_out/models/player_extractor_spec.rb +135 -0
- data/spec/in_and_out/models/player_spec.rb +78 -0
- data/spec/in_and_out/models/scraper_spec.rb +17 -0
- data/spec/in_and_out/models/shortcode_converter_spec.rb +19 -0
- data/spec/in_and_out/models/team_spec.rb +4 -0
- data/spec/in_and_out_spec.rb +49 -0
- data/spec/spec_helper.rb +7 -0
- metadata +196 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f4dd703cd0fabc5178cf7f78240aba70e0dcbf5a
|
4
|
+
data.tar.gz: abbaedde667fdf04b18d72b8a82e1abc099c4db7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e9dde58fde3ce4cafccea66a2a280a4e0dba373eea31b6a029dfb1ec29061f158aea493018894ec909f843e2ebfad5ced01b00e76142af8b2aea0d6aa523ba7e
|
7
|
+
data.tar.gz: 3600da635554f2881acfaf210fe077c952394ca159cd1e2655e2c270096cd8c506d8015dda2282990cf602ea8461ff5cd3e021691b1a53da5d6202c67998ec5b
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
# This is an RVM Project .rvmrc file, used to automatically load the ruby
|
4
|
+
# development environment upon cd'ing into the directory
|
5
|
+
|
6
|
+
# First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
|
7
|
+
# Only full ruby name is supported here, for short names use:
|
8
|
+
# echo "rvm use 2.0.0" > .rvmrc
|
9
|
+
environment_id="ruby-2.0.0-p0@in_or_out"
|
10
|
+
|
11
|
+
# Uncomment the following lines if you want to verify rvm version per project
|
12
|
+
# rvmrc_rvm_version="1.18.15 (master)" # 1.10.1 seams as a safe start
|
13
|
+
# eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
|
14
|
+
# echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
|
15
|
+
# return 1
|
16
|
+
# }
|
17
|
+
|
18
|
+
# First we attempt to load the desired environment directly from the environment
|
19
|
+
# file. This is very fast and efficient compared to running through the entire
|
20
|
+
# CLI and selector. If you want feedback on which environment was used then
|
21
|
+
# insert the word 'use' after --create as this triggers verbose mode.
|
22
|
+
if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
|
23
|
+
&& -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
|
24
|
+
then
|
25
|
+
\. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
|
26
|
+
for __hook in "${rvm_path:-$HOME/.rvm}/hooks/after_use"*
|
27
|
+
do
|
28
|
+
if [[ -f "${__hook}" && -x "${__hook}" && -s "${__hook}" ]]
|
29
|
+
then \. "${__hook}" || true
|
30
|
+
fi
|
31
|
+
done
|
32
|
+
unset __hook
|
33
|
+
else
|
34
|
+
# If the environment file has not yet been created, use the RVM CLI to select.
|
35
|
+
rvm --create "$environment_id" || {
|
36
|
+
echo "Failed to create RVM environment '${environment_id}'."
|
37
|
+
return 1
|
38
|
+
}
|
39
|
+
fi
|
40
|
+
|
41
|
+
# If you use bundler, this might be useful to you:
|
42
|
+
# if [[ -s Gemfile ]] && {
|
43
|
+
# ! builtin command -v bundle >/dev/null ||
|
44
|
+
# builtin command -v bundle | GREP_OPTIONS= \grep $rvm_path/bin/bundle >/dev/null
|
45
|
+
# }
|
46
|
+
# then
|
47
|
+
# printf "%b" "The rubygem 'bundler' is not installed. Installing it now.\n"
|
48
|
+
# gem install bundler
|
49
|
+
# fi
|
50
|
+
# if [[ -s Gemfile ]] && builtin command -v bundle >/dev/null
|
51
|
+
# then
|
52
|
+
# bundle install | GREP_OPTIONS= \grep -vE '^Using|Your bundle is complete'
|
53
|
+
# fi
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Sebastian Glazebrook
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# InOrOut
|
2
|
+
|
3
|
+
The aim of this gem is to help automate the process of finding out whether your favorite AFL players are playing on this week.
|
4
|
+
|
5
|
+
This is hopefully useful for anyone involved in fantasy football, or if you simply want to know where they will be on a Saturday arvo.
|
6
|
+
|
7
|
+
The data for this app is based on the AFL's team lineups
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem 'in_or_out'
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install in_or_out
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
Hopefully you find the gem easy to use:
|
26
|
+
|
27
|
+
Simple usage:
|
28
|
+
|
29
|
+
require 'in_or_out'
|
30
|
+
|
31
|
+
# They are considered in if they are listed on the field or on the interchange
|
32
|
+
|
33
|
+
InOrOut::Player.new('Jobe Watson', 'Essendon').status
|
34
|
+
=> 'In'
|
35
|
+
|
36
|
+
InOrOut::Player.new('Jobe Watson', 'Essendon').position
|
37
|
+
=> 'Centre'
|
38
|
+
|
39
|
+
# They are considered out if they are not found on the list
|
40
|
+
|
41
|
+
InOrOut::Player.new('Tim Watson', 'Essendon').status
|
42
|
+
=> 'Out'
|
43
|
+
|
44
|
+
# They are 'possible' they are are an Emergency part of an unfinilised Interchange
|
45
|
+
|
46
|
+
InOrOut::Player.new('Joe Daniher', 'Essendon').status
|
47
|
+
=> 'Possible'
|
48
|
+
|
49
|
+
InOrOut::Player.new('Joe Daniher', 'Essendon').position
|
50
|
+
=> 'Interchange/Emergency'
|
51
|
+
|
52
|
+
# They are 'unknown' if the teams are not released
|
53
|
+
|
54
|
+
InOrOut::Player.new('Joe Daniher', 'Essendon').status
|
55
|
+
=> 'Unknown'
|
56
|
+
|
57
|
+
Advanced usage:
|
58
|
+
|
59
|
+
# Get all your teams players in one go
|
60
|
+
|
61
|
+
InOrOut::Team.new('Essendon')
|
62
|
+
=> []
|
63
|
+
|
64
|
+
|
65
|
+
## Contributing
|
66
|
+
|
67
|
+
1. Fork it
|
68
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
69
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
70
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
71
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/config/analyser.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
afl_match_data_url: http://www.afl.com.au/match-centre
|
@@ -0,0 +1,18 @@
|
|
1
|
+
gcfc: Gold Coast
|
2
|
+
fre: Fremantle
|
3
|
+
ess: Essendon
|
4
|
+
nmfc: North Melbourne
|
5
|
+
syd: Sydney
|
6
|
+
melb: Melbourne
|
7
|
+
wce: West Coast
|
8
|
+
gws: Great Western Sydney
|
9
|
+
stk: St Kilda
|
10
|
+
bl: Brisbane
|
11
|
+
geel: Geelong
|
12
|
+
carl: Calrton
|
13
|
+
rich: Richmond
|
14
|
+
wb: Western Bulldogs
|
15
|
+
coll: Collingwood
|
16
|
+
haw: Hawthorn
|
17
|
+
port: Port Adelaide
|
18
|
+
adel: Adelaide
|
data/in_or_out.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'in_or_out/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'in_or_out'
|
8
|
+
spec.version = InOrOut::VERSION
|
9
|
+
spec.authors = ['Sebastian Glazebrook']
|
10
|
+
spec.email = ['me@sebglazebrook.com']
|
11
|
+
spec.description = %q{This gem will help you check whether you AFL fantasy football players are playing this week or not}
|
12
|
+
spec.summary = %q{Hopefully this can help you with your AFL fantasy football. It's an easy gem. Let me know if you find any issues.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'afl_schedule' , '~> 0.1.1'
|
22
|
+
spec.add_dependency 'active_support'
|
23
|
+
spec.add_dependency 'nokogiri'
|
24
|
+
spec.add_dependency 'mechanize'
|
25
|
+
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
27
|
+
spec.add_development_dependency "rake"
|
28
|
+
spec.add_development_dependency 'rspec', '2.13.0'
|
29
|
+
spec.add_development_dependency 'rspec-radar'
|
30
|
+
end
|
31
|
+
|
data/lib/in_or_out.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'in_or_out/version'
|
2
|
+
require 'in_or_out/models/player'
|
3
|
+
require 'in_or_out/models/scraper'
|
4
|
+
require 'in_or_out/models/team'
|
5
|
+
require 'in_or_out/models/match'
|
6
|
+
require 'in_or_out/models/player_extractor'
|
7
|
+
require 'in_or_out/models/shortcode_converter'
|
8
|
+
|
9
|
+
require 'yaml'
|
10
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
11
|
+
|
12
|
+
module InOrOut
|
13
|
+
|
14
|
+
|
15
|
+
def self.root
|
16
|
+
File.expand_path '../..', __FILE__
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.config
|
20
|
+
HashWithIndifferentAccess.new(YAML.load(File.read("#{self.root}/config/analyser.yml")))
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'active_support/inflector'
|
3
|
+
require 'afl_schedule'
|
4
|
+
|
5
|
+
module InOrOut
|
6
|
+
class Match
|
7
|
+
|
8
|
+
attr_reader :status, :players
|
9
|
+
|
10
|
+
def initialize(home_team, round, away_team = nil)
|
11
|
+
@home_team, @away_team, @round = home_team, away_team, round
|
12
|
+
@players = InOrOut::PlayerExtractor.new(download_match_data).extract
|
13
|
+
@players.empty? ? @status = 'pending' : @status = 'ready'
|
14
|
+
end
|
15
|
+
|
16
|
+
def find_player(player_name, team_name)
|
17
|
+
@players.detect { |player| player.name == player_name && player.team == team_name }
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.find(**options)
|
21
|
+
match = AFL::Schedule.new.next_match(options[:team])
|
22
|
+
if match
|
23
|
+
self.new(match[:home_team], match[:round], match[:away_team])
|
24
|
+
else
|
25
|
+
match
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def download_match_data
|
32
|
+
Nokogiri::HTML(InOrOut::Scraper.new.scrape(match_url))
|
33
|
+
end
|
34
|
+
|
35
|
+
def match_url
|
36
|
+
next_match = AFL::Schedule.new.next_match(@home_team) unless @away_team
|
37
|
+
"#{InOrOut.config[:afl_match_data_url]}/#{Time.now.year}/#{@round}/#{opponents_short_code(@home_team, @away_team)}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def opponents_short_code(home_team, away_team)
|
41
|
+
"#{InOrOut::ShortcodeConverter.find_shortcode(home_team)}-v-#{InOrOut::ShortcodeConverter.find_shortcode(away_team)}"
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module InOrOut
|
2
|
+
class Player
|
3
|
+
|
4
|
+
attr_reader :number, :position, :name, :team
|
5
|
+
|
6
|
+
def initialize(player_name, team_name, **options)
|
7
|
+
@name, @team = player_name, team_name
|
8
|
+
@number, @position, @status = options[:number], options[:position], options[:status]
|
9
|
+
end
|
10
|
+
|
11
|
+
def position
|
12
|
+
analyse unless @position
|
13
|
+
@position
|
14
|
+
end
|
15
|
+
|
16
|
+
def number
|
17
|
+
analyse unless @number
|
18
|
+
@number
|
19
|
+
end
|
20
|
+
|
21
|
+
def status
|
22
|
+
evaluate_status unless @status
|
23
|
+
@status
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def analyse
|
29
|
+
if next_match
|
30
|
+
populate_match_attributes
|
31
|
+
else
|
32
|
+
@status = 'Unknown'
|
33
|
+
end
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def next_match
|
38
|
+
@match = InOrOut::Match.find(team: @team)
|
39
|
+
end
|
40
|
+
|
41
|
+
def populate_match_attributes
|
42
|
+
player = @match.find_player(@name,@team)
|
43
|
+
if player
|
44
|
+
@status = player.status
|
45
|
+
@position = player.position
|
46
|
+
@number = player.number
|
47
|
+
else
|
48
|
+
@status = 'Off'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def evaluate_status
|
53
|
+
if position == 'Follower' || position == 'Centre' || position == 'Full Back' #@TODO add all positions
|
54
|
+
@status = 'On'
|
55
|
+
else
|
56
|
+
@status = 'Unknown'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module InOrOut
|
2
|
+
class PlayerExtractor
|
3
|
+
|
4
|
+
def initialize(match_data)
|
5
|
+
@data = match_data
|
6
|
+
end
|
7
|
+
|
8
|
+
def extract
|
9
|
+
if ready?
|
10
|
+
@data.css('.player').map do |player|
|
11
|
+
build_player(
|
12
|
+
extract_name(player),
|
13
|
+
extract_team(player),
|
14
|
+
extract_position(player),
|
15
|
+
extract_number(player)
|
16
|
+
)
|
17
|
+
end
|
18
|
+
else
|
19
|
+
[]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def ready?
|
26
|
+
if @data.inner_text.match('Team Lineups')
|
27
|
+
true
|
28
|
+
else
|
29
|
+
false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def build_player(name, team, position, number )
|
34
|
+
InOrOut::Player.new(name, team, position: position, number: number)
|
35
|
+
end
|
36
|
+
|
37
|
+
def extract_name(player_html_doc)
|
38
|
+
player_html_doc.inner_text[(player_html_doc.inner_text.rindex(/\d/)+1)..player_html_doc.inner_text.size].strip!.gsub(/\u00a0/, ' ')
|
39
|
+
end
|
40
|
+
|
41
|
+
def extract_team(player_html_doc)
|
42
|
+
InOrOut::ShortcodeConverter.convert(player_html_doc.ancestors('ul').first.attr('class').split.last.split('-').last)
|
43
|
+
end
|
44
|
+
|
45
|
+
def extract_number(player_html_doc)
|
46
|
+
player_html_doc.inner_text[(player_html_doc.inner_text.index(/\d/))..(player_html_doc.inner_text.rindex(/\d/))].to_i
|
47
|
+
end
|
48
|
+
|
49
|
+
def extract_position(player_html_doc)
|
50
|
+
res = player_html_doc.ancestors('div').first.attr('class').split.last.singularize.capitalize
|
51
|
+
if res == 'Posgroup'
|
52
|
+
res = convert_position_shorthand(player_html_doc.ancestors('ul').css('.pos').first.inner_text.strip)
|
53
|
+
end
|
54
|
+
res = check_if_emergency(player_html_doc) if res == 'Interchange'
|
55
|
+
res
|
56
|
+
end
|
57
|
+
|
58
|
+
def convert_position_shorthand(position)
|
59
|
+
case position
|
60
|
+
when 'HB'
|
61
|
+
'Half Back'
|
62
|
+
when 'HF'
|
63
|
+
'Half Forward'
|
64
|
+
when 'FF'
|
65
|
+
'Full Forward'
|
66
|
+
when 'FB'
|
67
|
+
'Full Back'
|
68
|
+
when 'C'
|
69
|
+
'Centre'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def check_if_emergency(player_html_doc)
|
74
|
+
positions = player_html_doc.ancestors('ul').first.css('.pos').size
|
75
|
+
if positions > 1
|
76
|
+
res = nil
|
77
|
+
while res == nil
|
78
|
+
previous = player_html_doc.previous_element
|
79
|
+
if previous.attr('class') == 'pos'
|
80
|
+
res = previous.inner_text.singularize.strip
|
81
|
+
else
|
82
|
+
player_html_doc = previous
|
83
|
+
end
|
84
|
+
end
|
85
|
+
else
|
86
|
+
res = 'Interchange'
|
87
|
+
end
|
88
|
+
res
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|