From 5af5260a211af65ce9d45336cf00170d1da18c99 Mon Sep 17 00:00:00 2001 From: ZippyDev Date: Sun, 10 Nov 2019 15:42:15 -0700 Subject: [PATCH] add initializer helpers and project cleanup --- .rubocop.yml | 2 +- .ruby-version | 2 +- lib/ncaa.rb | 36 +++++++++- lib/ncaa/base.rb | 145 +++++++++++++++++++++++++++++++++++++++++ lib/ncaa/basketball.rb | 11 ++++ 5 files changed, 191 insertions(+), 5 deletions(-) create mode 100644 lib/ncaa/base.rb create mode 100644 lib/ncaa/basketball.rb diff --git a/.rubocop.yml b/.rubocop.yml index 92c2759..f8d0365 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,5 +1,5 @@ AllCops: - TargetRubyVersion: 2.5 + TargetRubyVersion: 2.6 Documentation: Enabled: false LineLength: diff --git a/.ruby-version b/.ruby-version index 73462a5..57cf282 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.5.1 +2.6.5 diff --git a/lib/ncaa.rb b/lib/ncaa.rb index 560aa89..3242e9f 100644 --- a/lib/ncaa.rb +++ b/lib/ncaa.rb @@ -1,11 +1,41 @@ # frozen_string_literal: true -require 'ncaa/version' -require 'ncaa/base' +require 'active_support' +require 'active_support/inflector' +require 'active_support/core_ext/object' +require 'ncaa/version' require 'ncaa/client/base' +require 'ncaa/base' +require 'ncaa/basketball' + module Ncaa class Error < StandardError; end - # Your code goes here... + + module_function + + # @param args [Hash] + # @param args [Symbol] :type Sport type + # @param args [Logger] :logger Defaults to Logger.new(STDOUT) + # @param args [Integer] :timeout Defaults to 10 + # @return [Client::Base] + def new(**args) + client = Client::Base.new(**args) + klass(**args).new(client: client, **args) + end + + # @param args [Hash] + # @param args [Symbol] :type Sport type + # @return [Ncaa::Base] + # @raise [ArgumentError] When sport is invalid + def klass(**args) + raise ArgumentError.new('type is required') if args[:type].blank? + + sport = args[:type].to_s.camelize + type = "Ncaa::#{sport}".safe_constantize + raise ArgumentError.new("#{type} is not a valid type") if type.nil? + + type + end end diff --git a/lib/ncaa/base.rb b/lib/ncaa/base.rb new file mode 100644 index 0000000..e32b871 --- /dev/null +++ b/lib/ncaa/base.rb @@ -0,0 +1,145 @@ +# frozen_string_literal: true + +require 'ncaa/parser/html/base' + +module Ncaa + class Base + SERVER = 'casablanca' + CLIENT_URL = 'https://www.ncaa.com' + + attr_reader :client, :logger, :division, :sport + + # @param client [Ncaa::Client::Base] + # @param division [String] Vaild values: d1, d2, d3 + def initialize(client:, division: 'd1', **args) + @client = client + @logger = client.logger + @division = division.downcase + @sport = args[:type] + end + + # @param date [Time] Must respond to DateTime methods: #year, #month, #day + # @param options [Hash] + # @param headers [Hash] + # @return [Hash] + # @see https://data.ncaa.com/casablanca/scoreboard/basketball-men/d3/2019/01/17/scoreboard.json + def scoreboard(date = Time.now.utc, options: {}, headers: {}) + endpoint = "/#{SERVER}/scoreboard/#{sport_uri}/#{division}" \ + "/#{date.year}/#{format_date(date.month)}/#{format_date(date.day)}/scoreboard.json" + + resp = client.get(endpoint, options: options, headers: headers) + parse_json(resp.body) + end + + alias games scoreboard + alias schedule scoreboard + + # @param game_uri [String] Game uri + # @param options [Hash] + # @param headers [Hash] + # @return [Hash] + # @see https://data.ncaa.com/casablanca/game/3909829/boxscore.json + def boxscore(game_uri, options: {}, headers: {}) + endpoint = "/#{SERVER}/#{game_uri}/boxscore.json" + resp = client.get(endpoint, options: options, headers: headers) + parse_json(resp.body) + end + + alias game boxscore + + # @param game_uri [String] Game uri + # @param options [Hash] + # @param headers [Hash] + # @return [Hash] + # @see https://data.ncaa.com/casablanca/game/3909829/gameInfo.json + def game_info(game_uri, options: {}, headers: {}) + endpoint = "/#{SERVER}/#{game_uri}/gameInfo.json" + resp = client.get(endpoint, options: options, headers: headers) + parse_json(resp.body) + end + + alias info game_info + + # @param game_uri [String] Game uri + # @param options [Hash] + # @param headers [Hash] + # @return [Hash] + # @see https://data.ncaa.com/casablanca/game/3909829/pbp.json + def play_by_play(game_uri, options: {}, headers: {}) + endpoint = "/#{SERVER}/#{game_uri}/pbp.json" + resp = client.get(endpoint, options: options, headers: headers) + parse_json(resp.body) + end + + alias live play_by_play + + # @param type [String] Valid: associated-press, usa-today-coaches + # @param options [Hash] + # @param headers [Hash] + # @see https://www.ncaa.com/rankings/basketball-men/d1/ncaa-mens-basketball-net-rankings + def rankings(type = 'ncaa-mens-basketball-net-rankings', options: {}, headers: {}) + endpoint = "/rankings/#{sport_uri}/#{division}/#{type}" + resp = client_request do + client.get(endpoint, options: options, headers: headers) + end + Ncaa::Parser::Html::Rankings.parse(resp) + end + + # @param options [Hash] + # @param headers [Hash] + # @see https://www.ncaa.com/standings/basketball-men/d1/all-conferences + def standings(options: {}, headers: {}) + endpoint = "/standings/#{sport_uri}/#{division}/all-conferences" + resp = client_request do + client.get(endpoint, options: options, headers: headers) + end + Ncaa::Parser::Html::Standings.parse(resp) + end + + # @param options [Hash] + # @param headers [Hash] + # @return [Hash] + # @see # https://www.ncaa.com/json/schools + def schools(options: {}, headers: {}) + endpoint = '/json/schools' + resp = client_request do + client.get(endpoint, options: options, headers: headers) + end + parse_json(resp.body) + end + + alias teams schools + + protected + + def sport_uri + raise NotImplementedError.new('sport_uri needs to be implemented') + end + + private + + # @param response [String] + # @return [Hash] + def parse_json(response, symbolize: true) + JSON.parse(response, symbolize_names: symbolize) + rescue StandardError => e + raise InvalidJsonResponseError.new(error: 'Invalid Json', response: response, message: e.message) + end + + def format_date(number, formatter: '%02d') + format(formatter, number) + end + + # Request html url for parsing non-Json endpoints for data + # Resets client to data Json url after block is completed + def client_request + data_url = client.host + client.host = CLIENT_URL + results = yield + client.host = data_url + results + end + + class InvalidJsonResponseError < StandardError; end + end +end diff --git a/lib/ncaa/basketball.rb b/lib/ncaa/basketball.rb new file mode 100644 index 0000000..b068dfc --- /dev/null +++ b/lib/ncaa/basketball.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Ncaa + class Basketball < Base + protected + + def sport_uri + 'basketball-men' + end + end +end