diff --git a/nflgame/__init__.py b/nflgame/__init__.py index 2b82b1d2..02f1741d 100644 --- a/nflgame/__init__.py +++ b/nflgame/__init__.py @@ -434,9 +434,13 @@ def _search_schedule(year=None, week=None, home=None, away=None, kind='REG', for info in nflgame.sched.games.values(): y, t, w = info['year'], info['season_type'], info['week'] h, a = info['home'], info['away'] - if eid is not None and eid == info['eid']: - # Always return a non-array if eid is a match - return info + if eid is not None: + if eid == info['eid']: + # Always return a non-array if eid is a match + return info + else: + # if eid is supplied and doesn't match, skip + continue if year is not None: if isinstance(year, list) and y not in year: continue diff --git a/nflgame/game.py b/nflgame/game.py index ff474d57..8ce2df95 100644 --- a/nflgame/game.py +++ b/nflgame/game.py @@ -5,6 +5,9 @@ import json import socket import sys +import datetime +import time +import logging import urllib.request, urllib.error, urllib.parse from collections import OrderedDict @@ -12,6 +15,20 @@ import nflgame.sched import nflgame.seq import nflgame.statmap +import nflgame.live + +try: + import pytz +except ImportError: + pass + + +log_level = os.getenv("NFLGAME_LOG_LEVEL", '') +logging.basicConfig() +logger = logging.getLogger('nflgame') + +if log_level == "INFO": + logger.root.setLevel(logging.INFO) _MAX_INT = sys.maxsize @@ -249,47 +266,49 @@ class Game (object): """ def __new__(cls, eid=None, fpath=None, **kwargs): - # If we can't get a valid JSON data, exit out and return None. - try: - rawData = _get_json_data(eid, fpath) - except urllib.error.URLError: - return None - if rawData is None or rawData.strip() == '{}': - gameData = dict() + logger.info("EID: {}".format(eid)) + if eid is not None: + game_starting_soon, schedule_info = _infer_gc_json_available(eid) - # find the schedule data if it wasn't supplied in the kwargs - if len(kwargs) == 0 and eid is not None: - kwargs = nflgame._search_schedule(eid=eid) - - if len(kwargs) == 0: + if game_starting_soon: + try: + rawData = _get_json_data(eid, fpath) + except urllib.error.URLError: + # @TODO - find when this happens, likely never as ln# 868 catches + # 404 errors and returns None + return None + else: + if len(schedule_info) == 0: + # No game was found in the schedule return None gameData = { 'home': { - 'abbr': kwargs['home'], + 'abbr': schedule_info['home'], 'score': { 'T': 0 } }, 'away': { - 'abbr': kwargs['away'], + 'abbr': schedule_info['away'], 'score': { 'T': 0 } }, - "gamekey": kwargs['gamekey'], + "gamekey": schedule_info['gamekey'], "qtr": 'Pregame', "gcJsonAvailable": False, "clock": 0 } game = object.__new__(cls) - game.rawData = rawData - if game.rawData is None: + # IF the game isn't starting dump what schedule data we have + if not game_starting_soon: game.data = gameData game.eid = eid else: + game.rawData = rawData try: if eid is not None: game.eid = eid @@ -403,7 +422,7 @@ def save(self, fpath=None): with gzip.open(fpath, 'w+') as outfile: outfile.write(self.rawData) except IOError: - print("Could not cache JSON data. Please " \ + logger.info("Could not cache JSON data. Please " \ "make '%s' writable." \ % os.path.dirname(fpath), file=sys.stderr) @@ -862,16 +881,43 @@ def _get_json_data(eid=None, fpath=None): fpath = _jsonf % eid if os.access(fpath, os.R_OK): + logger.info("_get_json_data: json cache found, returning cached data ") return gzip.open(fpath).read() try: + logger.info("_get_json_data: firing request") return urllib.request.urlopen(_json_base_url % (eid, eid), timeout=5).read() except urllib.error.HTTPError: pass except socket.timeout: pass + + logger.info("_get_json_data: Failed request, returning None") return None +def _infer_gc_json_available(eid): + """ + Check to see if the game-center json even has a chance to be available, i.e. + the game starts in <= 10 minutes. This is used to prevent superfluous calls + to the nfl api. + + returns a tuple - True/False if the game is about to start and the schedule data + """ + logger.info("Checking to see if the game exists in the schedule") + schedule_info = nflgame._search_schedule(eid=eid) + if len(schedule_info) == 0: + logger.info("No game found") + #No game found + return False, [] + + gametime = nflgame.live._game_datetime(schedule_info) + now = nflgame.live._now() + + game_starting_soon = (gametime - now).total_seconds() <= 600 + logger.info("Game Starting Soon Check: {}".format(game_starting_soon)) + return game_starting_soon, schedule_info + + def _tryint(v): """ Tries to convert v to an integer. If it fails, return 0. diff --git a/nflgame/live.py b/nflgame/live.py index bde1d4a1..3fdcd53a 100644 --- a/nflgame/live.py +++ b/nflgame/live.py @@ -33,6 +33,8 @@ import time import math import requests +import logging +import os try: import pytz @@ -42,6 +44,13 @@ import nflgame import nflgame.game +log_level = os.getenv("NFLGAME_LOG_LEVEL", '') +logging.basicConfig() +logger = logging.getLogger('nflgame') + +if log_level == "INFO": + logger.root.setLevel(logging.INFO) + # [00:21] burntsushi: Alright, the schedule changes on Wednesday 7:00 # UTC during the regular season @@ -93,6 +102,7 @@ def current_season_phase(): _update_week_number() return _cur_season_phase + def current_year_and_week(): """ Returns a tuple (year, week) where year is the current year of the season @@ -188,18 +198,15 @@ def run(callback, active_interval=15, inactive_interval=900, wakeup_time=900, st active = False last_week_check = _update_week_number() + logger.info("Starting live loop") + # Before we start with the main loop, we make a first pass at what we # believe to be the active games. Of those, we check to see if any of # them are actually already over, and add them to _completed. for info in _active_games(inactive_interval): game = nflgame.game.Game(info['eid']) - # If we couldn't get a game, that probably means the JSON feed - # isn't available yet. (i.e., we're early.) - if game is None: - continue - - # Otherwise, if the game is over, add it to our list of completed + # if the game is over, add it to our list of completed # games and move on. if game.game_over(): _completed.append(info['eid']) @@ -334,6 +341,7 @@ def _game_datetime(info): def _now(): return datetime.datetime.now(pytz.utc) + def _update_week_number(): global _cur_week, _cur_year, _cur_season_phase