1 {-# LANGUAGE DeriveGeneric #-}
2 {-# LANGUAGE DeriveDataTypeable #-}
3 {-# LANGUAGE FlexibleInstances #-}
5 {-# LANGUAGE QuasiQuotes #-}
6 {-# LANGUAGE RecordWildCards #-}
7 {-# LANGUAGE TemplateHaskell #-}
8 {-# LANGUAGE TypeFamilies #-}
10 -- | Parse TSN XML for the DTD \"MLB_Boxscore_XML.dtd\".
12 module TSN.XML.MLBBoxScore (
16 -- auto_racing_results_tests,
17 -- * WARNING: these are private but exported to silence warnings
18 MLBBoxScore_MLBBoxScoreTeamBreakdownConstructor(..),
19 MLBBoxScoreConstructor(..),
20 MLBBoxScoreHomerunStatsListingConstructor(..),
21 MLBBoxScoreHomerunStatsListingPitcherConstructor(..),
22 MLBBoxScoreMiscellaneousGameInfo(..),
23 MLBBoxScoreMiscPitchingStatsHitByPitchConstructor(..),
24 MLBBoxScoreMiscPitchingStatsIntentionalWalkConstructor(..),
25 MLBBoxScoreRunsByInningsConstructor(..),
26 MLBBoxScoreTeamBreakdownConstructor(..),
27 MLBBoxScoreTeamSummary(..) -- can go eventually
32 import Control.Monad ( forM_ )
33 import Data.Data ( Data )
34 import Data.Maybe ( fromMaybe )
35 import Data.Time ( UTCTime(..) )
36 import Data.Tuple.Curry ( uncurryN )
37 import qualified Data.Vector.HFixed as H ( HVector, cons, convert, tail )
38 import Data.Typeable ( Typeable )
39 import Database.Groundhog (
43 import Database.Groundhog.Core ( DefaultKey )
44 import Database.Groundhog.TH (
47 import qualified GHC.Generics as GHC ( Generic )
48 import Text.XML.HXT.Core (
64 import TSN.Codegen ( tsn_codegen_config )
65 import TSN.DbImport ( DbImport(..), ImportResult(..), run_dbmigrate )
70 import TSN.Team ( Team(..), FromXmlFkTeams(..) )
71 import TSN.XmlImport ( XmlImport(..), XmlImportFk(..) )
79 -- | The DTD to which this module corresponds. Used to invoke dbimport.
82 dtd = "MLB_Boxscore_XML.dtd"
85 -- * DB/XML data types
88 -- MLBBoxScore/Message
90 -- | Database representation of a 'Message'. The vteam/hteam have been
91 -- removed since they use the TSN.Team representation. The
92 -- 'xml_game_date' and 'xml_game_time' fields have also been
93 -- combined into 'db_game_time'. Finally, the summaries are missing
94 -- since they'll be keyed to us.
98 db_xml_file_id :: Int,
100 db_category :: String,
103 db_schedule_id :: Int,
104 db_vteam_id :: DefaultKey Team,
105 db_hteam_id :: DefaultKey Team,
107 db_season_type :: String,
108 db_game_time :: UTCTime,
109 db_game_number :: Int,
111 db_wild_pitches :: Maybe Int, -- From misc pitching stats
113 db_time_stamp :: UTCTime }
118 -- | XML Representation of an 'MBLBoxScore'. It has the same fields,
119 -- but in addition contains the hteam/vteams and a game_date that
120 -- will eventually be combined with the time. It also has a list of
125 xml_xml_file_id :: Int,
126 xml_heading :: String,
127 xml_category :: String,
130 xml_schedule_id :: Int,
133 xml_vteam_id :: String,
134 xml_hteam_id :: String,
135 xml_season :: String,
136 xml_season_type :: String,
138 xml_game_date :: UTCTime,
139 xml_game_time :: UTCTime,
140 xml_game_number :: Int,
142 xml_game_breakdown :: MLBBoxScoreGameBreakdownXml,
143 xml_team_summaries :: [MLBBoxScoreTeamSummaryXml],
144 xml_misc_pitching_stats :: MLBBoxScoreMiscPitchingStatsXml,
145 xml_homerun_stats_listings :: Maybe [MLBBoxScoreHomerunStatsListingXml],
146 xml_miscellaneous_game_info :: MLBBoxScoreMiscellaneousGameInfoXml,
147 xml_time_stamp :: UTCTime }
148 deriving (Eq, GHC.Generic, Show)
151 -- | For 'H.convert'.
153 instance H.HVector Message
155 instance ToDb Message where
156 -- | The database analogue of a 'Message' is a 'MLBBoxScore'.
158 type Db Message = MLBBoxScore
162 -- | This ugly hack allows us to make 'Message' an instance of
163 -- 'FromXmlFkTeams'. That class usually requires that its instances
164 -- have a parent, but 'Message' does not. So we declare it the
165 -- parent of itself, and then ignore it.
166 instance Child Message where
167 type Parent Message = MLBBoxScore
169 -- | The 'FromXmlFk' instance for 'Message' is required for the
170 -- 'XmlImport' instance.
171 instance FromXmlFkTeams Message where
172 -- | To convert a 'Message' to an 'MLBBoxScore', we drop the
173 -- teams/summaries and combine the date/time. Also missing are the
174 -- embedded elements game_breakdown, homerun_stats, and
175 -- miscellaneous_game_info.
177 from_xml_fk_teams _ vteam_id hteam_id Message{..} =
179 db_xml_file_id = xml_xml_file_id,
180 db_heading = xml_heading,
181 db_category = xml_category,
182 db_sport = xml_sport,
183 db_game_id = xml_game_id,
184 db_schedule_id = xml_schedule_id,
185 db_vteam_id = vteam_id,
186 db_hteam_id = hteam_id,
187 db_season = xml_season,
188 db_season_type = xml_season_type,
189 db_game_time = make_game_time,
190 db_game_number = xml_game_number,
191 db_capacity = xml_capacity,
192 db_wild_pitches = xml_wild_pitches xml_misc_pitching_stats,
193 db_title = xml_title,
194 db_time_stamp = xml_time_stamp }
197 UTCTime (utctDay xml_game_date) (utctDayTime xml_game_time)
200 data MLBBoxScoreTeamSummary = MLBBoxScoreTeamSummary
201 data MLBBoxScoreTeamSummaryXml = MLBBoxScoreTeamSummaryXml deriving (Eq, Show)
203 data MLBBoxScoreGameBreakdownXml =
204 MLBBoxScoreGameBreakdownXml {
205 xml_away_team :: MLBBoxScoreTeamBreakdownXml,
206 xml_home_team :: MLBBoxScoreTeamBreakdownXml }
207 deriving (Eq, GHC.Generic, Show)
211 instance H.HVector MLBBoxScoreGameBreakdownXml
214 -- | The leading underscores prevent unused field warnings.
216 data MLBBoxScoreHomerunStatsListingBatter =
217 MLBBoxScoreHomerunStatsListingBatter {
218 _db_batter_first_name :: String,
219 _db_batter_last_name :: String,
220 _db_batter_rbis :: Int,
221 _db_batter_id :: Int }
222 deriving (Data, Eq, GHC.Generic, Show, Typeable)
226 instance H.HVector MLBBoxScoreHomerunStatsListingBatter
229 data MLBBoxScoreHomerunStatsListing =
230 MLBBoxScoreHomerunStatsListing {
231 db_mlb_box_scores_id :: DefaultKey MLBBoxScore,
232 db_batter :: MLBBoxScoreHomerunStatsListingBatter, -- embedded
233 db_season_homeruns :: Int }
235 data MLBBoxScoreHomerunStatsListingXml =
236 MLBBoxScoreHomerunStatsListingXml {
237 xml_batter :: MLBBoxScoreHomerunStatsListingBatter,
238 xml_season_homeruns :: Int,
239 xml_pitchers :: [MLBBoxScoreHomerunStatsListingPitcherXml] }
240 deriving (Eq, GHC.Generic, Show)
244 instance H.HVector MLBBoxScoreHomerunStatsListingXml
246 instance Child MLBBoxScoreHomerunStatsListingXml where
247 -- | Each 'MLBBoxScoreHomerunStatsListingXml' is contained in (i.e. has a
248 -- foreign key to) a 'MLBBoxScore'.
250 type Parent MLBBoxScoreHomerunStatsListingXml = MLBBoxScore
253 instance ToDb MLBBoxScoreHomerunStatsListingXml where
254 -- | The database representation of
255 -- 'MLBBoxScoreHomerunStatsListingXml' is
256 -- 'MLBBoxScoreHomerunStatsListing'.
258 type Db MLBBoxScoreHomerunStatsListingXml = MLBBoxScoreHomerunStatsListing
260 instance FromXmlFk MLBBoxScoreHomerunStatsListingXml where
261 -- | To convert an 'MLBBoxScoreHomerunStatsListingXml' to an
262 -- 'MLBBoxScoreHomerunStatsListing', we add the foreign key and
263 -- drop the pitchers.
265 from_xml_fk fk MLBBoxScoreHomerunStatsListingXml{..} =
266 MLBBoxScoreHomerunStatsListing {
267 db_mlb_box_scores_id = fk,
268 db_batter = xml_batter,
269 db_season_homeruns = xml_season_homeruns }
272 -- | This allows us to insert the XML representation
273 -- 'MLBBoxScoreHomerunStatsListingXml' directly.
275 instance XmlImportFk MLBBoxScoreHomerunStatsListingXml
278 -- | The leading underscores prevent unused field warnings.
280 data MLBBoxScoreHomerunStatsListingPitcher =
281 MLBBoxScoreHomerunStatsListingPitcher {
282 _db_mlb_box_score_homerun_stats_listings_id ::
283 DefaultKey MLBBoxScoreHomerunStatsListing,
284 _db_homeruns_off_pitcher :: Int,
285 _db_pitcher_first_name :: String,
286 _db_pitcher_last_name :: String,
287 _db_pitchers_pitcher_id :: Int }
288 deriving ( GHC.Generic )
291 -- | For 'H.cons' and 'H.convert'.
293 instance H.HVector MLBBoxScoreHomerunStatsListingPitcher
296 -- | The leading underscores prevent unused field warnings.
298 data MLBBoxScoreHomerunStatsListingPitcherXml =
299 MLBBoxScoreHomerunStatsListingPitcherXml {
300 _xml_homeruns_off_pitcher :: Int,
301 _xml_pitcher_first_name :: String,
302 _xml_pitcher_last_name :: String,
303 _xml_pitchers_pitcher_id :: Int }
304 deriving (Eq, GHC.Generic, Show)
308 instance H.HVector MLBBoxScoreHomerunStatsListingPitcherXml
310 instance Child MLBBoxScoreHomerunStatsListingPitcherXml where
311 -- | Each 'MLBBoxScoreHomerunStatsListingPitcherXml' is contained in
312 -- (i.e. has a foreign key to) a 'MLBBoxScoreHomerunStatsListing'.
314 type Parent MLBBoxScoreHomerunStatsListingPitcherXml =
315 MLBBoxScoreHomerunStatsListing
318 instance ToDb MLBBoxScoreHomerunStatsListingPitcherXml where
319 -- | The database representation of
320 -- 'MLBBoxScoreHomerunStatsListingPitcherXml' is
321 -- 'MLBBoxScoreHomerunStatsListingPitcher'.
323 type Db MLBBoxScoreHomerunStatsListingPitcherXml = MLBBoxScoreHomerunStatsListingPitcher
326 instance FromXmlFk MLBBoxScoreHomerunStatsListingPitcherXml where
327 -- | To convert an 'MLBBoxScoreHomerunStatsListingPitcherXml' to an
328 -- 'MLBBoxScoreHomerunStatsListingPitcher', we add the foreign key.
333 -- | This allows us to insert the XML representation
334 -- 'MLBBoxScoreHomerunStatsListingPitcherXml' directly.
336 instance XmlImportFk MLBBoxScoreHomerunStatsListingPitcherXml
341 data MLBBoxScoreMiscellaneousGameInfo = MLBBoxScoreMiscellaneousGameInfo
342 data MLBBoxScoreMiscellaneousGameInfoXml = MLBBoxScoreMiscellaneousGameInfoXml
348 -- | The leading underscores prevent unused field warnings.
350 data MLBBoxScoreTeamBreakdown =
351 MLBBoxScoreTeamBreakdown {
355 deriving ( GHC.Generic )
357 -- | For 'H.cons' and 'H.convert'.
359 instance H.HVector MLBBoxScoreTeamBreakdown
361 -- | The leading underscores prevent unused field warnings.
363 data MLBBoxScoreTeamBreakdownXml =
364 MLBBoxScoreTeamBreakdownXml {
365 xml_runs_by_innings :: [MLBBoxScoreRunsByInningsXml],
369 deriving (Eq, GHC.Generic, Show)
372 -- | For 'H.convert'.
373 instance H.HVector MLBBoxScoreTeamBreakdownXml
375 instance ToDb MLBBoxScoreTeamBreakdownXml where
376 -- | The database analogue of a 'MLBBoxScoreTeamBreakdownXml' is
377 -- a 'MLBBoxScoreTeamBreakdown'.
379 type Db MLBBoxScoreTeamBreakdownXml = MLBBoxScoreTeamBreakdown
382 -- | The 'FromXml' instance for 'MLBBoxScoreTeamBreakdownXml' is
383 -- required for the 'XmlImport' instance.
385 instance FromXml MLBBoxScoreTeamBreakdownXml where
386 -- | To convert a 'MLBBoxScoreTeamBreakdownXml' to an
387 -- 'MLBBoxScoreTeamBreakdown', we just drop the
388 -- 'xml_runs_by_innings'.
392 instance XmlImport MLBBoxScoreTeamBreakdownXml
396 -- | The leading underscores prevent unused field warnings.
398 data MLBBoxScoreRunsByInnings =
399 MLBBoxScoreRunsByInnings {
400 _db_mlb_box_scores_team_breakdowns_id :: DefaultKey
401 MLBBoxScoreTeamBreakdown,
402 _db_runs_by_innings_inning_number :: Int,
403 _db_runs_by_innings_runs :: Int }
404 deriving ( GHC.Generic )
407 -- | For 'H.cons' and 'H.convert'.
408 instance H.HVector MLBBoxScoreRunsByInnings
411 -- | The leading underscores prevent unused field warnings.
413 data MLBBoxScoreRunsByInningsXml =
414 MLBBoxScoreRunsByInningsXml {
415 _xml_runs_by_innings_inning_number :: Int,
416 _xml_runs_by_innings_runs :: Int }
417 deriving (Eq, GHC.Generic, Show)
420 -- * MLBBoxScore_MLBBoxScoreTeamSummary
422 -- | Mapping between 'MLBBoxScore' records and
423 -- 'MLBBoxScoreTeamSummary' records in the database. We don't use
424 -- the names anywhere, so we let Groundhog choose them.
426 data MLBBoxScore_MLBBoxScoreTeamBreakdown =
427 MLBBoxScore_MLBBoxScoreTeamBreakdown
428 (DefaultKey MLBBoxScore)
429 (DefaultKey MLBBoxScoreTeamBreakdown) -- Away team
430 (DefaultKey MLBBoxScoreTeamBreakdown) -- Home team
434 -- | For 'H.convert'.
436 instance H.HVector MLBBoxScoreRunsByInningsXml
439 instance ToDb MLBBoxScoreRunsByInningsXml where
440 -- | The database analogue of a 'MLBBoxScoreRunsByInningsXml' is
441 -- a 'MLBBoxScoreRunsByInnings'.
443 type Db MLBBoxScoreRunsByInningsXml = MLBBoxScoreRunsByInnings
446 instance Child MLBBoxScoreRunsByInningsXml where
447 -- | Each 'MLBBoxScoreRunsByInningsXml' is contained in (i.e. has a
448 -- foreign key to) a 'MLBBoxScoreTeamBreakdownXml'.
450 type Parent MLBBoxScoreRunsByInningsXml = MLBBoxScoreTeamBreakdown
453 instance FromXmlFk MLBBoxScoreRunsByInningsXml where
454 -- | To convert an 'MLBBoxScoreRunsByInningsXml' to an
455 -- 'MLBBoxScoreRunsByInnings', we add the foreign key and copy
456 -- everything else verbatim.
461 -- | This allows us to insert the XML representation
462 -- 'MLBBoxScoreRunsByInningsXml' directly.
464 instance XmlImportFk MLBBoxScoreRunsByInningsXml
468 -- | The type representing \<Misc_Pitching_Stats\> XML elements. It
469 -- has no associated database type; the 'xml_wild_pitches' are
470 -- stored directly in the 'MLBBoxScore', and the two linked tables
471 -- are treated as children of the 'MLBBoxScore'.
473 data MLBBoxScoreMiscPitchingStatsXml =
474 MLBBoxScoreMiscPitchingStatsXml {
475 xml_wild_pitches :: Maybe Int,
476 xml_intentional_walks :: [MLBBoxScoreMiscPitchingStatsIntentionalWalkXml],
477 xml_hits_by_pitch :: [MLBBoxScoreMiscPitchingStatsHitByPitchXml] }
478 deriving (Eq, GHC.Generic, Show)
481 -- | For 'H.convert'.
483 instance H.HVector MLBBoxScoreMiscPitchingStatsXml
486 -- * MLBBoxScoreMiscPitchingStatsIntentionalWalk
488 -- | Database representation of an intentional walk. The weird
489 -- prefixes avoid collisions with the other batter/pitcher_ids, and
490 -- still get mangled properly by Groundhog.
492 -- The leading underscores prevent unused field warnings.
494 data MLBBoxScoreMiscPitchingStatsIntentionalWalk =
495 MLBBoxScoreMiscPitchingStatsIntentionalWalk {
496 _dbiw_mlb_box_scores_id :: DefaultKey MLBBoxScore,
497 _dbiw_batter_id :: Int,
498 _dbiw_pitcher_id :: Int,
499 _dbiw_number_of_times_walked :: Int }
500 deriving ( GHC.Generic )
503 -- | For 'H.cons' and 'H.convert'.
505 instance H.HVector MLBBoxScoreMiscPitchingStatsIntentionalWalk
507 -- | The leading underscores prevent unused field warnings.
509 data MLBBoxScoreMiscPitchingStatsIntentionalWalkXml =
510 MLBBoxScoreMiscPitchingStatsIntentionalWalkXml {
511 _xml_iw_batter_id :: Int,
512 _xml_iw_pitcher_id :: Int,
513 _xml_iw_number_of_times_walked :: Int }
514 deriving (Eq, GHC.Generic, Show)
516 -- | For 'H.convert'.
518 instance H.HVector MLBBoxScoreMiscPitchingStatsIntentionalWalkXml
521 instance ToDb MLBBoxScoreMiscPitchingStatsIntentionalWalkXml where
522 -- | The database analogue of a
523 -- 'MLBBoxScoreMiscPitchingStatsIntentionalWalkXml' is a
524 -- 'MLBBoxScoreMiscPitchingStatsIntentionalWalk'.
526 type Db MLBBoxScoreMiscPitchingStatsIntentionalWalkXml =
527 MLBBoxScoreMiscPitchingStatsIntentionalWalk
530 instance Child MLBBoxScoreMiscPitchingStatsIntentionalWalkXml where
531 -- | Each 'MLBBoxScoreMiscPitchingStatsIntentionalWalkXml' is
532 -- contained in (i.e. has a foreign key to) a 'MLBBoxScore'.
534 type Parent MLBBoxScoreMiscPitchingStatsIntentionalWalkXml =
538 instance FromXmlFk MLBBoxScoreMiscPitchingStatsIntentionalWalkXml where
539 -- | To convert an 'MLBBoxScoreMiscPitchingStatsIntentionalWalkXml'
540 -- to an 'MLBBoxScoreMiscPitchingStatsIntentionalWalk', we add the
541 -- foreign key and copy everything else verbatim.
546 -- | This allows us to insert the XML representation
547 -- 'MLBBoxScoreMiscPitchingStatsIntentionalWalkXml' directly.
549 instance XmlImportFk MLBBoxScoreMiscPitchingStatsIntentionalWalkXml
553 -- * MLBBoxScoreMiscPitchingStatsHitByPitchXml
555 -- | The leading underscores prevent unused field warnings.
557 data MLBBoxScoreMiscPitchingStatsHitByPitch =
558 MLBBoxScoreMiscPitchingStatsHitByPitch {
559 _dbhbp_mlb_box_scores_id :: DefaultKey MLBBoxScore,
560 _dbhbp_batter_id :: Int,
561 _dbhbp_pitcher_id :: Int,
562 _dbhbp_number_of_times_hit :: Int }
563 deriving ( GHC.Generic )
565 -- | For 'H.cons' and 'H.convert'.
567 instance H.HVector MLBBoxScoreMiscPitchingStatsHitByPitch
569 instance ToDb MLBBoxScoreMiscPitchingStatsHitByPitchXml where
570 -- | The database analogue of a
571 -- 'MLBBoxScoreMiscPitchingStatsHitByPitchXml' is a
572 -- 'MLBBoxScoreMiscPitchingStatsHitByPitch'.
574 type Db MLBBoxScoreMiscPitchingStatsHitByPitchXml =
575 MLBBoxScoreMiscPitchingStatsHitByPitch
578 instance Child MLBBoxScoreMiscPitchingStatsHitByPitchXml where
579 -- | Each 'MLBBoxScoreMiscPitchingStatsHitByPitchXml' is
580 -- contained in (i.e. has a foreign key to) a 'MLBBoxScore'.
582 type Parent MLBBoxScoreMiscPitchingStatsHitByPitchXml =
586 instance FromXmlFk MLBBoxScoreMiscPitchingStatsHitByPitchXml where
587 -- | To convert an 'MLBBoxScoreMiscPitchingStatsHitByPitchXml'
588 -- to an 'MLBBoxScoreMiscPitchingStatsHitByPitch', we add the
589 -- foreign key and copy everything else verbatim.
594 -- | This allows us to insert the XML representation
595 -- 'MLBBoxScoreMiscPitchingStatsHitByPitchXml' directly.
597 instance XmlImportFk MLBBoxScoreMiscPitchingStatsHitByPitchXml
600 -- | The leading underscores prevent unused field warnings.
602 data MLBBoxScoreMiscPitchingStatsHitByPitchXml =
603 MLBBoxScoreMiscPitchingStatsHitByPitchXml {
604 _xml_hbp_batter_id :: Int,
605 _xml_hbp_pitcher_id :: Int,
606 _xml_hbp_number_of_times_hit :: Int }
607 deriving (Eq, GHC.Generic, Show)
610 -- | For 'H.convert'.
612 instance H.HVector MLBBoxScoreMiscPitchingStatsHitByPitchXml
619 instance DbImport Message where
622 migrate (undefined :: MLBBoxScore)
623 migrate (undefined :: MLBBoxScoreMiscPitchingStatsIntentionalWalk)
624 migrate (undefined :: MLBBoxScoreMiscPitchingStatsHitByPitch)
625 migrate (undefined :: MLBBoxScoreHomerunStatsListing)
626 migrate (undefined :: MLBBoxScoreHomerunStatsListingPitcher)
627 migrate (undefined :: MLBBoxScoreTeamBreakdown)
628 migrate (undefined :: MLBBoxScoreRunsByInnings)
629 migrate (undefined :: MLBBoxScore_MLBBoxScoreTeamBreakdown)
631 -- | We insert the message.
633 -- First, get the vteam/hteam out of the XML message.
634 let vteam = Team (xml_vteam_id m) Nothing (Just $ xml_vteam m)
635 let hteam = Team (xml_hteam_id m) Nothing (Just $ xml_hteam m)
638 vteam_fk <- insert vteam
639 hteam_fk <- insert hteam
641 -- Now we can key the message to the teams/breakdowns we just
643 let db_msg = from_xml_fk_teams undefined vteam_fk hteam_fk m
644 msg_id <- insert db_msg
646 -- Next, the vteam/hteam breakdowns, also needed to construct the
647 -- main message record
648 let vteam_bd = xml_away_team $ xml_game_breakdown m
649 let hteam_bd = xml_home_team $ xml_game_breakdown m
651 vteam_bd_fk <- insert_xml vteam_bd
652 hteam_bd_fk <- insert_xml hteam_bd
654 -- Insert the runs-by-innings associated with the vteam/hteam
656 forM_ (xml_runs_by_innings vteam_bd) $ insert_xml_fk_ vteam_bd_fk
657 forM_ (xml_runs_by_innings hteam_bd) $ insert_xml_fk_ hteam_bd_fk
659 -- Now the join table record that ties the message to its two team
661 let msg__breakdown = MLBBoxScore_MLBBoxScoreTeamBreakdown
666 insert_ msg__breakdown
668 -- Now insert the homerun stats listings, keyed to the message.
669 -- They need not be present, but we're going to loop through them
670 -- all anyway, so if we have 'Nothing', we convert that to an
671 -- empty list instead. This simplifies the `forM_` code.
672 let listings = fromMaybe [] (xml_homerun_stats_listings m)
673 forM_ listings $ \listing -> do
674 -- Insert the listing itself.
675 listing_id <- insert_xml_fk msg_id listing
676 -- And all of its pitchers
677 forM_ (xml_pitchers listing) $ insert_xml_fk listing_id
679 -- We have two tables of pitching stats that need to be keyed to
681 let iws = xml_intentional_walks (xml_misc_pitching_stats m)
682 forM_ iws $ insert_xml_fk_ msg_id
684 let hbps = xml_hits_by_pitch (xml_misc_pitching_stats m)
685 forM_ hbps $ insert_xml_fk_ msg_id
687 return ImportSucceeded
691 mkPersist tsn_codegen_config [groundhog|
692 - entity: MLBBoxScore
693 dbName: mlb_box_scores
697 - name: unique_mlb_box_scores
699 # Prevent multiple imports of the same message.
700 fields: [db_xml_file_id]
704 - entity: MLBBoxScoreMiscPitchingStatsIntentionalWalk
705 dbName: mlb_box_scores_misc_pitching_stats_intentional_walks
707 - name: MLBBoxScoreMiscPitchingStatsIntentionalWalk
709 - name: _dbiw_mlb_box_scores_id
714 - entity: MLBBoxScoreMiscPitchingStatsHitByPitch
715 dbName: mlb_box_scores_misc_pitching_stats_hits_by_pitch
717 - name: MLBBoxScoreMiscPitchingStatsHitByPitch
719 - name: _dbhbp_mlb_box_scores_id
724 - embedded: MLBBoxScoreHomerunStatsListingBatter
726 - name: _db_batter_first_name
727 dbName: batter_first_name
728 - name: _db_batter_last_name
729 dbName: batter_last_name
730 - name: _db_batter_rbis
732 - name: _db_batter_id
735 - entity: MLBBoxScoreHomerunStatsListing
736 dbName: mlb_box_score_homerun_stats_listings
738 - name: MLBBoxScoreHomerunStatsListing
742 - {name: batter_first_name, dbName: batter_first_name}
743 - {name: batter_last_name, dbName: batter_last_name}
744 - {name: batter_rbis, dbName: batter_rbis}
745 - {name: batter_id, dbName: batter_id}
747 - entity: MLBBoxScoreHomerunStatsListingPitcher
748 dbName: mlb_box_score_homerun_stats_listing_pitchers
750 - name: MLBBoxScoreHomerunStatsListingPitcher
752 - name: _db_mlb_box_score_homerun_stats_listings_id
756 - entity: MLBBoxScoreTeamBreakdown
757 dbName: mlb_box_scores_team_breakdowns
759 - name: MLBBoxScoreTeamBreakdown
761 - entity: MLBBoxScoreRunsByInnings
762 dbName: mlb_box_scores_team_breakdowns_runs_by_innings
764 - name: MLBBoxScoreRunsByInnings
766 - name: _db_mlb_box_scores_team_breakdowns_id
771 - entity: MLBBoxScore_MLBBoxScoreTeamBreakdown
772 dbName: mlb_box_scores__mlb_box_scores_team_breakdowns
774 - name: MLBBoxScore_MLBBoxScoreTeamBreakdown
776 - name: mLBBoxScore_MLBBoxScoreTeamBreakdown0
777 dbName: mlb_box_scores_id
780 - name: mLBBoxScore_MLBBoxScoreTeamBreakdown1
781 dbName: mlb_box_scores_team_breakdowns_away_team_id
784 - name: mLBBoxScore_MLBBoxScoreTeamBreakdown2
785 dbName: db_mlb_box_scores_team_breakdowns_home_team_id
796 pickle_message :: PU Message
799 xpWrap (from_tuple, H.convert) $
800 xp23Tuple (xpElem "XML_File_ID" xpInt)
801 (xpElem "heading" xpText)
802 (xpElem "category" xpText)
803 (xpElem "sport" xpText)
804 (xpElem "game_id" xpInt)
805 (xpElem "schedule_id" xpInt)
806 (xpElem "vteam" xpText)
807 (xpElem "hteam" xpText)
808 (xpElem "vteam_id" xpText)
809 (xpElem "hteam_id" xpText)
810 (xpElem "Season" xpText)
811 (xpElem "SeasonType" xpText)
812 (xpElem "title" xpText)
813 (xpElem "Game_Date" xp_date)
814 (xpElem "Game_Time" xp_time)
815 (xpElem "GameNumber" xpInt)
816 (xpElem "Capacity" xpInt)
817 pickle_game_breakdown
818 (xpList pickle_team_summary)
819 pickle_misc_pitching_stats
820 (xpOption pickle_homerun_stats_listings)
821 pickle_miscellaneous_game_info
822 (xpElem "time_stamp" xp_time_stamp)
824 from_tuple = uncurryN Message
827 pickle_team_summary :: PU MLBBoxScoreTeamSummaryXml
828 pickle_team_summary =
829 xpElem "Team_Summary" $ xpWrap (from_tuple, to_tuple') xpUnit
831 from_tuple _ = MLBBoxScoreTeamSummaryXml
834 pickle_game_breakdown :: PU MLBBoxScoreGameBreakdownXml
835 pickle_game_breakdown =
836 xpElem "Game_Breakdown" $
837 xpWrap (from_tuple, H.convert) $
838 xpPair pickle_away_team
841 from_tuple = uncurry MLBBoxScoreGameBreakdownXml
844 pickle_runs_by_innings :: PU MLBBoxScoreRunsByInningsXml
845 pickle_runs_by_innings =
846 xpElem "Runs_By_Innings" $
847 xpWrap (from_tuple, H.convert) $
848 xpPair (xpAttr "Inning" xpInt)
851 from_tuple = uncurry MLBBoxScoreRunsByInningsXml
854 pickle_team :: PU MLBBoxScoreTeamBreakdownXml
856 xpWrap (from_tuple, H.convert) $
857 xp4Tuple (xpList pickle_runs_by_innings)
858 (xpElem "Runs" xpInt)
859 (xpElem "Hits" xpInt)
860 (xpElem "Errors" xpInt)
862 from_tuple = uncurryN MLBBoxScoreTeamBreakdownXml
865 pickle_away_team :: PU MLBBoxScoreTeamBreakdownXml
867 xpElem "AwayTeam" pickle_team
869 pickle_home_team :: PU MLBBoxScoreTeamBreakdownXml
871 xpElem "HomeTeam" pickle_team
874 pickle_batter :: PU MLBBoxScoreHomerunStatsListingBatter
876 xpElem "HRS_Batter_ID" $
877 xpWrap (from_tuple, H.convert) $
878 xp4Tuple (xpAttr "HRS_Batter_FirstName" xpText)
879 (xpAttr "HRS_Batter_LastName" xpText)
880 (xpAttr "RBIs" xpInt)
883 from_tuple = uncurryN MLBBoxScoreHomerunStatsListingBatter
886 pickle_pitcher :: PU MLBBoxScoreHomerunStatsListingPitcherXml
888 xpElem "HRS_Pitcher_ID" $
889 xpWrap (from_tuple, H.convert) $
890 xp4Tuple (xpAttr "HRS_Homeruns_Off_Pitcher" xpInt)
891 (xpAttr "HRS_Pitcher_FirstName" xpText)
892 (xpAttr "HRS_Pitcher_LastName" xpText)
895 from_tuple = uncurryN MLBBoxScoreHomerunStatsListingPitcherXml
898 pickle_homerun_stats_listing :: PU MLBBoxScoreHomerunStatsListingXml
899 pickle_homerun_stats_listing =
900 xpElem "HRS_Listing" $
901 xpWrap (from_tuple, H.convert) $
902 xpTriple pickle_batter
903 (xpElem "Season_Homeruns" xpInt)
904 (xpList pickle_pitcher)
906 from_tuple = uncurryN MLBBoxScoreHomerunStatsListingXml
909 pickle_homerun_stats_listings :: PU [MLBBoxScoreHomerunStatsListingXml]
910 pickle_homerun_stats_listings =
911 xpElem "Homerun_Stats" $ xpList pickle_homerun_stats_listing
914 pickle_misc_pitching_stats :: PU MLBBoxScoreMiscPitchingStatsXml
915 pickle_misc_pitching_stats =
916 xpElem "Misc_Pitching_Stats" $
917 xpWrap (from_tuple, H.convert) $
918 xpTriple (xpOption $ xpElem "Wild_Pitches" xpInt)
919 pickle_intentional_walks
922 from_tuple = uncurryN MLBBoxScoreMiscPitchingStatsXml
926 pickle_intentional_walks :: PU [MLBBoxScoreMiscPitchingStatsIntentionalWalkXml]
927 pickle_intentional_walks =
928 xpElem "Intentional_Walks" $ xpList $ xpElem "IW_Listing" $
929 xpWrap (from_tuple, H.convert) $
930 xpTriple (xpElem "IW_Batter_ID" xpInt)
931 (xpElem "IW_Pitcher_ID" xpInt)
932 (xpElem "IW_Number_Of_Times_Walked" xpInt)
934 from_tuple = uncurryN MLBBoxScoreMiscPitchingStatsIntentionalWalkXml
938 pickle_hits_by_pitch :: PU [MLBBoxScoreMiscPitchingStatsHitByPitchXml]
939 pickle_hits_by_pitch =
940 xpElem "Hit_By_Pitch" $ xpList $ xpElem "HBP_Listing" $
941 xpWrap (from_tuple, H.convert) $
942 xpTriple (xpElem "HBP_Batter_ID" xpInt)
943 (xpElem "HBP_Pitcher_ID" xpInt)
944 (xpElem "HBP_Number_Of_Times_Hit" xpInt)
946 from_tuple = uncurryN MLBBoxScoreMiscPitchingStatsHitByPitchXml
950 pickle_miscellaneous_game_info :: PU MLBBoxScoreMiscellaneousGameInfoXml
951 pickle_miscellaneous_game_info =
952 xpElem "Miscelaneous_Game_Info" $ xpWrap (from_tuple, to_tuple') xpUnit
954 from_tuple _ = MLBBoxScoreMiscellaneousGameInfoXml