+ xml_game_date :: UTCTime, -- ^ Contains only the date
+ xml_game_time :: Maybe UTCTime, -- ^ Contains only the time
+ xml_away_team :: OddsGameTeamXml,
+ xml_home_team :: OddsGameTeamXml,
+ xml_over_under :: OddsGameOverUnderXml }
+ deriving (Eq, GHC.Generic, Show)
+
+
+-- | For 'Generics.to_tuple'.
+--
+instance Generic OddsGameXml
+
+
+-- | Pseudo-field that lets us get the 'OddsGameCasinoXml's out of
+-- xml_over_under.
+--
+xml_over_under_casinos :: OddsGameXml -> [OddsGameCasinoXml]
+xml_over_under_casinos = xml_casinos . xml_over_under
+
+
+instance ToDb OddsGameXml where
+ -- | The database representation of an 'OddsGameXml' is an
+ -- 'OddsGame'.
+ --
+ type Db OddsGameXml = OddsGame
+
+
+instance Child OddsGameXml where
+ -- | Each 'OddsGameXml' is contained in an 'Odds'. In other words
+ -- the foreign key for 'OddsGame' points to an 'Odds'.
+ --
+ type Parent OddsGameXml = Odds
+
+
+instance FromXmlFkTeams OddsGameXml where
+ -- | To convert from the XML representation to the database one, we
+ -- drop the casino lines, but retain the home/away rotation
+ -- numbers and the starters. The foreign keys to 'Odds' and the
+ -- home/away teams are passed in.
+ --
+ from_xml_fk_teams fk fk_away fk_home OddsGameXml{..} =
+ OddsGame {
+ db_odds_id = fk,
+ db_away_team_id = fk_away,
+ db_home_team_id = fk_home,
+ db_game_id = xml_game_id,
+
+ db_game_time = make_game_time xml_game_date xml_game_time,
+
+ db_away_team_rotation_number =
+ (xml_team_rotation_number xml_away_team),
+
+ db_home_team_rotation_number =
+ (xml_team_rotation_number xml_home_team),
+
+ db_away_team_starter_id =
+ (xml_starter_id <$> xml_team_starter xml_away_team),
+
+ -- Sometimes the starter element is present but the name isn't,
+ -- so we combine the two maybes with join.
+ db_away_team_starter_name = join
+ (xml_starter_name <$> xml_team_starter xml_away_team),
+
+ db_home_team_starter_id =
+ (xml_starter_id <$> xml_team_starter xml_home_team),
+
+ -- Sometimes the starter element is present but the name isn't,
+ -- so we combine the two maybes with join.
+ db_home_team_starter_name = join
+ (xml_starter_name <$> xml_team_starter xml_home_team) }
+ where
+ -- | Construct the database game time from the XML \<Game_Date\>
+ -- and \<Game_Time\> elements. The \<Game_Time\> elements
+ -- sometimes have a value of \"TBA\"; in that case, we don't
+ -- want to pretend that we know the time by setting it to
+ -- e.g. midnight, so instead we make the entire date/time
+ -- Nothing.
+ make_game_time :: UTCTime -> Maybe UTCTime -> Maybe UTCTime
+ make_game_time _ Nothing = Nothing
+ make_game_time d (Just t) = Just $ UTCTime (utctDay d) (utctDayTime t)
+
+
+-- | This lets us insert the XML representation 'OddsGameXml' directly.
+--
+instance XmlImportFkTeams OddsGameXml
+
+
+-- * OddsGameWithNotes
+
+-- | This is our best guess at what occurs in the Odds_XML
+-- documents. It looks like each consecutive set of games can
+-- optionally have some notes appear before it. Each \"note\" comes
+-- as its own \<Notes\>...\</Notes\> element.
+--
+-- The notes are ignored completely in the database; we only bother
+-- with them to ensure that we're (un)pickling correctly.
+--
+-- We can't group the notes with a \"set\" of 'OddsGame's, because
+-- that leads to ambiguity in parsing. Since we're going to ignore
+-- the notes anyway, we just stick them with an arbitrary
+-- game. C'est la vie.
+--
+-- We have to take the same approach with the league. The
+-- \<League_Name\> elements are sitting outside of the games, and
+-- are presumably supposed to be interpreted in \"chronological\"
+-- order; i.e. the current league stays the same until we see
+-- another \<League_Name\> element. Unfortunately, that's not how
+-- XML works. So we're forced to ignore the league in the database
+-- and pull the same trick, pairing them with games.
+--
+data OddsGameWithNotes =
+ OddsGameWithNotes {
+ league :: Maybe String,
+ notes :: [String],
+ game :: OddsGameXml }