From f10bcdbd1a66081ee8208676a12a2ea677a097e2 Mon Sep 17 00:00:00 2001 From: ZippyDev Date: Mon, 2 Dec 2019 20:26:53 -0700 Subject: [PATCH] add divisions. add standings. add football. --- Gemfile | 6 ++- Rakefile | 8 ++-- bin/console | 7 +-- lib/ncaa/base.rb | 4 +- lib/ncaa/basketball.rb | 17 +++++++ lib/ncaa/football.rb | 30 +++++++++++++ lib/ncaa/parser/html/standings.rb | 75 ++++++++++++++++++++++++++++++- lib/ncaa/version.rb | 4 +- spec/ncaa_spec.rb | 25 ++++++++++- 9 files changed, 163 insertions(+), 13 deletions(-) create mode 100644 lib/ncaa/football.rb diff --git a/Gemfile b/Gemfile index 7b78cf7..f91f1ee 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,8 @@ -source "https://rubygems.org" +# frozen_string_literal: true -git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } +source 'https://rubygems.org' + +git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } # Specify your gem's dependencies in ncaa.gemspec gemspec diff --git a/Rakefile b/Rakefile index b7e9ed5..82bb534 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,8 @@ -require "bundler/gem_tasks" -require "rspec/core/rake_task" +# frozen_string_literal: true + +require 'bundler/gem_tasks' +require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) -task :default => :spec +task default: :spec diff --git a/bin/console b/bin/console index 74f7acc..8c8b098 100755 --- a/bin/console +++ b/bin/console @@ -1,7 +1,8 @@ #!/usr/bin/env ruby +# frozen_string_literal: true -require "bundler/setup" -require "ncaa" +require 'bundler/setup' +require 'ncaa' # You can add fixtures and/or initialization code here to make experimenting # with your gem easier. You can also use a different console, if you like. @@ -10,5 +11,5 @@ require "ncaa" # require "pry" # Pry.start -require "irb" +require 'irb' IRB.start(__FILE__) diff --git a/lib/ncaa/base.rb b/lib/ncaa/base.rb index e32b871..6a96cf2 100644 --- a/lib/ncaa/base.rb +++ b/lib/ncaa/base.rb @@ -10,7 +10,9 @@ module Ncaa attr_reader :client, :logger, :division, :sport # @param client [Ncaa::Client::Base] - # @param division [String] Vaild values: d1, d2, d3 + # @param division [String] + # basketball-men: d1, d2, d3 + # football: fbs, fcs, d2, d3 def initialize(client:, division: 'd1', **args) @client = client @logger = client.logger diff --git a/lib/ncaa/basketball.rb b/lib/ncaa/basketball.rb index b068dfc..fb0f42c 100644 --- a/lib/ncaa/basketball.rb +++ b/lib/ncaa/basketball.rb @@ -2,6 +2,23 @@ module Ncaa class Basketball < Base + DIVISIONS = %w[d1 d2 d3].freeze + RANKINGS = D1_RANKINGS + D2_RANKINGS + D3_RANKINGS + D1_RANKINGS = %w[associated-press ncaa-mens-basketball-net-rankings usa-today-coaches].freeze + D2_RANKINGS = %w[nabc-coaches regional-ranking d2sida].freeze + D3_RANKINGS = %w[d3hoopscom regional-rankings-0].freeze + + def metadata + { + divisions: DIVISIONS, + rankings: { + d1: D1_RANKINGS, + d2: D2_RANKINGS, + d3: D3_RANKINGS + } + } + end + protected def sport_uri diff --git a/lib/ncaa/football.rb b/lib/ncaa/football.rb new file mode 100644 index 0000000..5527080 --- /dev/null +++ b/lib/ncaa/football.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +module Ncaa + class Football < Base + DIVISIONS = %w[fbs fcs d2 d3].freeze + RANKINGS = FBS_RANKINGS + FCS_RANKINGS + D2_RANKINGS + D3_RANKINGS + FBS_RANKINGS = %w[associated-press college-football-playoff usa-today-coaches-poll].freeze + FCS_RANKINGS = %w[fcs-coaches-poll stats-fcs-top-25 simple-ratings-system].freeze + D2_RANKINGS = %w[regional-rankings afca-coaches d2footballcom].freeze + D3_RANKINGS = %w[regional-rankings afca-coaches d3footballcom].freeze + + def metadata + { + divisions: DIVISIONS, + rankings: { + fbs: FBS_RANKINGS, + fcs: FCS_RANKINGS, + d2: D2_RANKINGS, + d3: D3_RANKINGS + } + } + end + + protected + + def sport_uri + 'football' + end + end +end diff --git a/lib/ncaa/parser/html/standings.rb b/lib/ncaa/parser/html/standings.rb index 6c10e29..69c86f1 100644 --- a/lib/ncaa/parser/html/standings.rb +++ b/lib/ncaa/parser/html/standings.rb @@ -5,7 +5,80 @@ module Ncaa module Html class Standings < Base def build - raise NotImplementedError.new + { + type: 'standings', + sort: 'by_conference', + last_updated: last_updated, + data: standings + } + end + + private + + def conferences + @conferences ||= html.css('figure.standings-conference') + end + + def table(conference) + conference.next_element.css('table') + end + + def team_rows(table) + table.css('tbody tr') + end + + # @return [Array] + def keys(table) + @keys ||= table.css('thead th').map { |x| x.text.remove(/\s/).underscore.to_sym } + end + + # @return [Time] + def last_updated + @last_updated ||= begin + updated = html.css('figure.standings-last-updated').text + date = updated[/\w+{3,}\.? \d+{1,2}, \d+{2,4} .+/] + Time.parse(date) + end + end + + def team_standing(row) + standings = row.css('td') + + { + school: standings[0].text.strip, + school_image_url: standings[0].css('img').attr('src').value, + conference: { + wins: standings[1].text.to_i, + losses: standings[2].text.to_i, + percentage: standings[3].text.to_f + }, + overall: { + wins: standings[4].text.to_i, + losses: standings[5].text.to_i, + percentage: standings[6].text.to_f + }, + streak: standings[7].text + } + end + + # @return [Array] + def standings + @standings ||= begin + conferences.each.with_object([]) do |conference, arr| + standing = { + conference: conference.text.strip, + conference_image_url: conference.css('img').attr('src').value, + standings: [] + } + + conference_table = table(conference) + teams = team_rows(conference_table) + + teams.each { |team| standing[:standings] << team_standing(team) } + + arr << standing + end + end end end end diff --git a/lib/ncaa/version.rb b/lib/ncaa/version.rb index 8ca699e..77dcb31 100644 --- a/lib/ncaa/version.rb +++ b/lib/ncaa/version.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Ncaa - VERSION = "0.1.0" + VERSION = '0.1.0' end diff --git a/spec/ncaa_spec.rb b/spec/ncaa_spec.rb index c54c449..9d40e9b 100644 --- a/spec/ncaa_spec.rb +++ b/spec/ncaa_spec.rb @@ -1,11 +1,32 @@ # frozen_string_literal: true RSpec.describe Ncaa do + let(:type) { :basketball } + it 'has a version number' do expect(Ncaa::VERSION).not_to be nil end - it 'does something useful' do - expect(false).to eq(true) + describe '.new' do + it 'returns sport client' do + sub = described_class.new(type: type) + expect(sub).to be_a(Ncaa::Basketball) + expect(sub.client).to be_a(Ncaa::Client::Base) + end + end + + describe '.klass' do + it 'returns valid class' do + sub = described_class.klass(type: type) + expect(sub).to eq(Ncaa::Basketball) + end + + it 'raises error when type is missing' do + expect { described_class.klass }.to raise_error(ArgumentError) + end + + it 'raises error when type is invalid' do + expect { described_class.klass(type: 'foobar') }.to raise_error(ArgumentError) + end end end