+-- | The home/away lines are 'Double's, but the over/under lines are
+-- textual. If we want to use one data type for both, we have to go
+-- with a 'String' and then attempt to 'read' a 'Double' later when we
+-- go to insert the thing.
+--
+-- The client_id and name shouldn't really be optional, but TSN has
+-- started to send us empty casinos:
+--
+-- \<Casino ClientID=\"\" Name=\"\"\>\</Casino\>
+--
+-- We need to parse these, but we'll silently drop them during the
+-- database import.
+--
+data OddsGameCasinoXml =
+ OddsGameCasinoXml {
+ xml_casino_client_id :: Maybe Int,
+ xml_casino_name :: Maybe String,
+ xml_casino_line :: Maybe String }
+ deriving (Eq, GHC.Generic, Show)
+
+
+-- | For 'Generics.to_tuple'.
+--
+instance Generic OddsGameCasinoXml
+
+
+-- | Try to get a 'Double' out of the 'xml_casino_line' which is a
+-- priori textual (because it might be an over/under line).
+--
+home_away_line :: OddsGameCasinoXml -> Maybe Double
+home_away_line = join . (fmap readMaybe) . xml_casino_line
+
+
+
+instance ToDb OddsGameCasinoXml where
+ -- | The database representation of an 'OddsGameCasinoXml' is an
+ -- 'OddsCasino'. When our XML representation is missing a
+ -- client_id or a name, we want to ignore it. So in that case,
+ -- when we convert to the database type, we want 'Nothing'.
+ --
+ type Db OddsGameCasinoXml = Maybe OddsCasino
+
+
+instance FromXml OddsGameCasinoXml where
+ -- | We convert from XML to the database by dropping the
+ -- 'xml_casino_line' field. If either the 'xml_casino_client_id'
+ -- or 'xml_casino_name' is missing ('Nothing'), we'll return
+ -- 'Nothing'.
+ --
+ from_xml (OddsGameCasinoXml Nothing _ _) = Nothing
+ from_xml (OddsGameCasinoXml _ Nothing _) = Nothing
+
+ from_xml (OddsGameCasinoXml (Just c) (Just n) _) =
+ Just OddsCasino { casino_client_id = c, casino_name = n }
+
+
+
+-- * OddsGameTeamXml / OddsGameTeamStarterXml
+
+-- | The XML representation of a \"starter\". It contains both an ID
+-- and a name. The ID does not appear to be optional, but the name
+-- can be absent. When the name is absent, the ID has always been
+-- set to \"0\". This occurs even though the entire starter element
+-- is optional (see 'OddsGameTeamXml' below).
+--
+data OddsGameTeamStarterXml =
+ OddsGameTeamStarterXml {
+ xml_starter_id :: Int,
+ xml_starter_name :: Maybe String }
+ deriving (Eq, GHC.Generic, Show)
+
+
+-- | For 'Generics.to_tuple'.
+--
+instance Generic OddsGameTeamStarterXml
+
+
+-- | The XML representation of a \<HomeTeam\> or \<AwayTeam\>, as
+-- found in \<Game\>s. We can't use the 'Team' representation
+-- directly because there are some other fields we need to parse.
+--
+data OddsGameTeamXml =
+ OddsGameTeamXml {
+ xml_team_id :: String, -- ^ The home/away team IDs
+ -- are three characters but
+ -- Postgres imposes no
+ -- performance penalty on
+ -- lengthless text fields,
+ -- so we ignore the probable
+ -- upper bound of three
+ -- characters.
+ xml_team_rotation_number :: Maybe Int,
+ xml_team_abbr :: String,
+ xml_team_name :: String,
+ xml_team_starter :: Maybe OddsGameTeamStarterXml,
+ xml_team_casinos :: [OddsGameCasinoXml] }
+ deriving (Eq, GHC.Generic, Show)
+
+
+-- | For 'Generics.to_tuple'.
+--
+instance Generic OddsGameTeamXml
+
+
+instance ToDb OddsGameTeamXml where
+ -- | The database representation of an 'OddsGameTeamXml' is an
+ -- 'OddsGameTeam'.
+ --
+ type Db OddsGameTeamXml = Team
+
+instance FromXml OddsGameTeamXml where
+ -- | We convert from XML to the database by dropping the lines and
+ -- rotation number (which are specific to the games, not the teams
+ -- themselves).
+ --
+ from_xml OddsGameTeamXml{..} =
+ Team {
+ team_id = xml_team_id,
+ abbreviation = Just xml_team_abbr,
+ name = Just xml_team_name }
+
+-- | This allows us to insert the XML representation
+-- 'OddsGameTeamXml' directly.
+--
+instance XmlImport OddsGameTeamXml where
+
+
+