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, convert )
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 data MLBBoxScoreHomerunStatsListingBatter =
215 MLBBoxScoreHomerunStatsListingBatter {
216 db_batter_first_name :: String,
217 db_batter_last_name :: String,
218 db_batter_rbis :: Int,
219 db_batter_id :: Int }
220 deriving (Data, Eq, GHC.Generic, Show, Typeable)
224 instance H.HVector MLBBoxScoreHomerunStatsListingBatter
227 data MLBBoxScoreHomerunStatsListing =
228 MLBBoxScoreHomerunStatsListing {
229 db_mlb_box_scores_id :: DefaultKey MLBBoxScore,
230 db_batter :: MLBBoxScoreHomerunStatsListingBatter, -- embedded
231 db_season_homeruns :: Int }
233 data MLBBoxScoreHomerunStatsListingXml =
234 MLBBoxScoreHomerunStatsListingXml {
235 xml_batter :: MLBBoxScoreHomerunStatsListingBatter,
236 xml_season_homeruns :: Int,
237 xml_pitchers :: [MLBBoxScoreHomerunStatsListingPitcherXml] }
238 deriving (Eq, GHC.Generic, Show)
242 instance H.HVector MLBBoxScoreHomerunStatsListingXml
244 instance Child MLBBoxScoreHomerunStatsListingXml where
245 -- | Each 'MLBBoxScoreHomerunStatsListingXml' is contained in (i.e. has a
246 -- foreign key to) a 'MLBBoxScore'.
248 type Parent MLBBoxScoreHomerunStatsListingXml = MLBBoxScore
251 instance ToDb MLBBoxScoreHomerunStatsListingXml where
252 -- | The database representation of
253 -- 'MLBBoxScoreHomerunStatsListingXml' is
254 -- 'MLBBoxScoreHomerunStatsListing'.
256 type Db MLBBoxScoreHomerunStatsListingXml = MLBBoxScoreHomerunStatsListing
258 instance FromXmlFk MLBBoxScoreHomerunStatsListingXml where
259 -- | To convert an 'MLBBoxScoreHomerunStatsListingXml' to an
260 -- 'MLBBoxScoreHomerunStatsListing', we add the foreign key and
261 -- drop the pitchers.
263 from_xml_fk fk MLBBoxScoreHomerunStatsListingXml{..} =
264 MLBBoxScoreHomerunStatsListing {
265 db_mlb_box_scores_id = fk,
266 db_batter = xml_batter,
267 db_season_homeruns = xml_season_homeruns }
270 -- | This allows us to insert the XML representation
271 -- 'MLBBoxScoreHomerunStatsListingXml' directly.
273 instance XmlImportFk MLBBoxScoreHomerunStatsListingXml
276 data MLBBoxScoreHomerunStatsListingPitcher =
277 MLBBoxScoreHomerunStatsListingPitcher {
278 db_mlb_box_score_homerun_stats_listings_id ::
279 DefaultKey MLBBoxScoreHomerunStatsListing,
280 db_homeruns_off_pitcher :: Int,
281 db_pitcher_first_name :: String,
282 db_pitcher_last_name :: String,
283 db_pitchers_pitcher_id :: Int }
285 data MLBBoxScoreHomerunStatsListingPitcherXml =
286 MLBBoxScoreHomerunStatsListingPitcherXml {
287 xml_homeruns_off_pitcher :: Int,
288 xml_pitcher_first_name :: String,
289 xml_pitcher_last_name :: String,
290 xml_pitchers_pitcher_id :: Int }
291 deriving (Eq, GHC.Generic, Show)
295 instance H.HVector MLBBoxScoreHomerunStatsListingPitcherXml
297 instance Child MLBBoxScoreHomerunStatsListingPitcherXml where
298 -- | Each 'MLBBoxScoreHomerunStatsListingPitcherXml' is contained in
299 -- (i.e. has a foreign key to) a 'MLBBoxScoreHomerunStatsListing'.
301 type Parent MLBBoxScoreHomerunStatsListingPitcherXml =
302 MLBBoxScoreHomerunStatsListing
305 instance ToDb MLBBoxScoreHomerunStatsListingPitcherXml where
306 -- | The database representation of
307 -- 'MLBBoxScoreHomerunStatsListingPitcherXml' is
308 -- 'MLBBoxScoreHomerunStatsListingPitcher'.
310 type Db MLBBoxScoreHomerunStatsListingPitcherXml = MLBBoxScoreHomerunStatsListingPitcher
313 instance FromXmlFk MLBBoxScoreHomerunStatsListingPitcherXml where
314 -- | To convert an 'MLBBoxScoreHomerunStatsListingPitcherXml' to an
315 -- 'MLBBoxScoreHomerunStatsListingPitcher', we add the foreign key.
317 from_xml_fk fk MLBBoxScoreHomerunStatsListingPitcherXml{..} =
318 MLBBoxScoreHomerunStatsListingPitcher {
319 db_mlb_box_score_homerun_stats_listings_id = fk,
320 db_homeruns_off_pitcher = xml_homeruns_off_pitcher,
321 db_pitcher_first_name = xml_pitcher_first_name,
322 db_pitcher_last_name = xml_pitcher_last_name,
323 db_pitchers_pitcher_id = xml_pitchers_pitcher_id }
326 -- | This allows us to insert the XML representation
327 -- 'MLBBoxScoreHomerunStatsListingPitcherXml' directly.
329 instance XmlImportFk MLBBoxScoreHomerunStatsListingPitcherXml
334 data MLBBoxScoreMiscellaneousGameInfo = MLBBoxScoreMiscellaneousGameInfo
335 data MLBBoxScoreMiscellaneousGameInfoXml = MLBBoxScoreMiscellaneousGameInfoXml
340 data MLBBoxScoreTeamBreakdown =
341 MLBBoxScoreTeamBreakdown {
345 data MLBBoxScoreTeamBreakdownXml =
346 MLBBoxScoreTeamBreakdownXml {
347 xml_runs_by_innings :: [MLBBoxScoreRunsByInningsXml],
351 deriving (Eq, GHC.Generic, Show)
354 -- | For 'H.convert'.
355 instance H.HVector MLBBoxScoreTeamBreakdownXml
357 instance ToDb MLBBoxScoreTeamBreakdownXml where
358 -- | The database analogue of a 'MLBBoxScoreTeamBreakdownXml' is
359 -- a 'MLBBoxScoreTeamBreakdown'.
361 type Db MLBBoxScoreTeamBreakdownXml = MLBBoxScoreTeamBreakdown
364 -- | The 'FromXml' instance for 'MLBBoxScoreTeamBreakdownXml' is
365 -- required for the 'XmlImport' instance.
367 instance FromXml MLBBoxScoreTeamBreakdownXml where
368 -- | To convert a 'MLBBoxScoreTeamBreakdownXml' to an
369 -- 'MLBBoxScoreTeamBreakdown', we just drop the
370 -- 'xml_runs_by_innings'.
372 from_xml MLBBoxScoreTeamBreakdownXml{..} =
373 MLBBoxScoreTeamBreakdown {
376 db_errors = xml_errors }
378 instance XmlImport MLBBoxScoreTeamBreakdownXml
381 data MLBBoxScoreRunsByInnings =
382 MLBBoxScoreRunsByInnings {
383 db_mlb_box_scores_team_breakdowns_id :: DefaultKey
384 MLBBoxScoreTeamBreakdown,
385 db_runs_by_innings_inning_number :: Int,
386 db_runs_by_innings_runs :: Int }
388 data MLBBoxScoreRunsByInningsXml =
389 MLBBoxScoreRunsByInningsXml {
390 xml_runs_by_innings_inning_number :: Int,
391 xml_runs_by_innings_runs :: Int }
392 deriving (Eq, GHC.Generic, Show)
395 -- * MLBBoxScore_MLBBoxScoreTeamSummary
397 -- | Mapping between 'MLBBoxScore' records and
398 -- 'MLBBoxScoreTeamSummary' records in the database. We don't use
399 -- the names anywhere, so we let Groundhog choose them.
401 data MLBBoxScore_MLBBoxScoreTeamBreakdown =
402 MLBBoxScore_MLBBoxScoreTeamBreakdown
403 (DefaultKey MLBBoxScore)
404 (DefaultKey MLBBoxScoreTeamBreakdown) -- Away team
405 (DefaultKey MLBBoxScoreTeamBreakdown) -- Home team
409 -- | For 'H.convert'.
411 instance H.HVector MLBBoxScoreRunsByInningsXml
414 instance ToDb MLBBoxScoreRunsByInningsXml where
415 -- | The database analogue of a 'MLBBoxScoreRunsByInningsXml' is
416 -- a 'MLBBoxScoreRunsByInnings'.
418 type Db MLBBoxScoreRunsByInningsXml = MLBBoxScoreRunsByInnings
421 instance Child MLBBoxScoreRunsByInningsXml where
422 -- | Each 'MLBBoxScoreRunsByInningsXml' is contained in (i.e. has a
423 -- foreign key to) a 'MLBBoxScoreTeamBreakdownXml'.
425 type Parent MLBBoxScoreRunsByInningsXml = MLBBoxScoreTeamBreakdown
428 instance FromXmlFk MLBBoxScoreRunsByInningsXml where
429 -- | To convert an 'MLBBoxScoreRunsByInningsXml' to an
430 -- 'MLBBoxScoreRunsByInnings', we add the foreign key and copy
431 -- everything else verbatim.
433 from_xml_fk fk MLBBoxScoreRunsByInningsXml{..} =
434 MLBBoxScoreRunsByInnings {
435 db_mlb_box_scores_team_breakdowns_id = fk,
436 db_runs_by_innings_inning_number = xml_runs_by_innings_inning_number,
437 db_runs_by_innings_runs = xml_runs_by_innings_runs }
440 -- | This allows us to insert the XML representation
441 -- 'MLBBoxScoreRunsByInningsXml' directly.
443 instance XmlImportFk MLBBoxScoreRunsByInningsXml
447 -- | The type representing \<Misc_Pitching_Stats\> XML elements. It
448 -- has no associated database type; the 'xml_wild_pitches' are
449 -- stored directly in the 'MLBBoxScore', and the two linked tables
450 -- are treated as children of the 'MLBBoxScore'.
452 data MLBBoxScoreMiscPitchingStatsXml =
453 MLBBoxScoreMiscPitchingStatsXml {
454 xml_wild_pitches :: Maybe Int,
455 xml_intentional_walks :: [MLBBoxScoreMiscPitchingStatsIntentionalWalkXml],
456 xml_hits_by_pitch :: [MLBBoxScoreMiscPitchingStatsHitByPitchXml] }
457 deriving (Eq, GHC.Generic, Show)
460 -- | For 'H.convert'.
462 instance H.HVector MLBBoxScoreMiscPitchingStatsXml
465 -- * MLBBoxScoreMiscPitchingStatsIntentionalWalk
467 -- | Database representation of an intentional walk. The weird
468 -- prefixes avoid collisiont with the other batter/pitcher_ids, and
469 -- still get mangled properly by Groundhog.
471 data MLBBoxScoreMiscPitchingStatsIntentionalWalk =
472 MLBBoxScoreMiscPitchingStatsIntentionalWalk {
473 dbiw_mlb_box_scores_id :: DefaultKey MLBBoxScore,
474 dbiw_batter_id :: Int,
475 dbiw_pitcher_id :: Int,
476 dbiw_number_of_times_walked :: Int }
479 data MLBBoxScoreMiscPitchingStatsIntentionalWalkXml =
480 MLBBoxScoreMiscPitchingStatsIntentionalWalkXml {
481 xml_iw_batter_id :: Int,
482 xml_iw_pitcher_id :: Int,
483 xml_iw_number_of_times_walked :: Int }
484 deriving (Eq, GHC.Generic, Show)
486 -- | For 'H.convert'.
488 instance H.HVector MLBBoxScoreMiscPitchingStatsIntentionalWalkXml
491 instance ToDb MLBBoxScoreMiscPitchingStatsIntentionalWalkXml where
492 -- | The database analogue of a
493 -- 'MLBBoxScoreMiscPitchingStatsIntentionalWalkXml' is a
494 -- 'MLBBoxScoreMiscPitchingStatsIntentionalWalk'.
496 type Db MLBBoxScoreMiscPitchingStatsIntentionalWalkXml =
497 MLBBoxScoreMiscPitchingStatsIntentionalWalk
500 instance Child MLBBoxScoreMiscPitchingStatsIntentionalWalkXml where
501 -- | Each 'MLBBoxScoreMiscPitchingStatsIntentionalWalkXml' is
502 -- contained in (i.e. has a foreign key to) a 'MLBBoxScore'.
504 type Parent MLBBoxScoreMiscPitchingStatsIntentionalWalkXml =
508 instance FromXmlFk MLBBoxScoreMiscPitchingStatsIntentionalWalkXml where
509 -- | To convert an 'MLBBoxScoreMiscPitchingStatsIntentionalWalkXml'
510 -- to an 'MLBBoxScoreMiscPitchingStatsIntentionalWalk', we add the
511 -- foreign key and copy everything else verbatim.
513 from_xml_fk fk MLBBoxScoreMiscPitchingStatsIntentionalWalkXml{..} =
514 MLBBoxScoreMiscPitchingStatsIntentionalWalk {
515 dbiw_mlb_box_scores_id = fk,
516 dbiw_batter_id = xml_iw_batter_id,
517 dbiw_pitcher_id = xml_iw_pitcher_id,
518 dbiw_number_of_times_walked = xml_iw_number_of_times_walked }
521 -- | This allows us to insert the XML representation
522 -- 'MLBBoxScoreMiscPitchingStatsIntentionalWalkXml' directly.
524 instance XmlImportFk MLBBoxScoreMiscPitchingStatsIntentionalWalkXml
528 -- * MLBBoxScoreMiscPitchingStatsHitByPitchXml
530 data MLBBoxScoreMiscPitchingStatsHitByPitch =
531 MLBBoxScoreMiscPitchingStatsHitByPitch {
532 dbhbp_mlb_box_scores_id :: DefaultKey MLBBoxScore,
533 dbhbp_batter_id :: Int,
534 dbhbp_pitcher_id :: Int,
535 dbhbp_number_of_times_hit :: Int }
538 instance ToDb MLBBoxScoreMiscPitchingStatsHitByPitchXml where
539 -- | The database analogue of a
540 -- 'MLBBoxScoreMiscPitchingStatsHitByPitchXml' is a
541 -- 'MLBBoxScoreMiscPitchingStatsHitByPitch'.
543 type Db MLBBoxScoreMiscPitchingStatsHitByPitchXml =
544 MLBBoxScoreMiscPitchingStatsHitByPitch
547 instance Child MLBBoxScoreMiscPitchingStatsHitByPitchXml where
548 -- | Each 'MLBBoxScoreMiscPitchingStatsHitByPitchXml' is
549 -- contained in (i.e. has a foreign key to) a 'MLBBoxScore'.
551 type Parent MLBBoxScoreMiscPitchingStatsHitByPitchXml =
555 instance FromXmlFk MLBBoxScoreMiscPitchingStatsHitByPitchXml where
556 -- | To convert an 'MLBBoxScoreMiscPitchingStatsHitByPitchXml'
557 -- to an 'MLBBoxScoreMiscPitchingStatsHitByPitch', we add the
558 -- foreign key and copy everything else verbatim.
560 from_xml_fk fk MLBBoxScoreMiscPitchingStatsHitByPitchXml{..} =
561 MLBBoxScoreMiscPitchingStatsHitByPitch {
562 dbhbp_mlb_box_scores_id = fk,
563 dbhbp_batter_id = xml_hbp_batter_id,
564 dbhbp_pitcher_id = xml_hbp_pitcher_id,
565 dbhbp_number_of_times_hit = xml_hbp_number_of_times_hit }
568 -- | This allows us to insert the XML representation
569 -- 'MLBBoxScoreMiscPitchingStatsHitByPitchXml' directly.
571 instance XmlImportFk MLBBoxScoreMiscPitchingStatsHitByPitchXml
574 data MLBBoxScoreMiscPitchingStatsHitByPitchXml =
575 MLBBoxScoreMiscPitchingStatsHitByPitchXml {
576 xml_hbp_batter_id :: Int,
577 xml_hbp_pitcher_id :: Int,
578 xml_hbp_number_of_times_hit :: Int }
579 deriving (Eq, GHC.Generic, Show)
582 -- | For 'H.convert'.
584 instance H.HVector MLBBoxScoreMiscPitchingStatsHitByPitchXml
591 instance DbImport Message where
594 migrate (undefined :: MLBBoxScore)
596 -- | We insert the message.
598 -- First, get the vteam/hteam out of the XML message.
599 let vteam = Team (xml_vteam_id m) Nothing (Just $ xml_vteam m)
600 let hteam = Team (xml_hteam_id m) Nothing (Just $ xml_hteam m)
603 vteam_fk <- insert vteam
604 hteam_fk <- insert hteam
606 -- Now we can key the message to the teams/breakdowns we just
608 let db_msg = from_xml_fk_teams undefined vteam_fk hteam_fk m
609 msg_id <- insert db_msg
611 -- Next, the vteam/hteam breakdowns, also needed to construct the
612 -- main message record
613 let vteam_bd = xml_away_team $ xml_game_breakdown m
614 let hteam_bd = xml_home_team $ xml_game_breakdown m
616 vteam_bd_fk <- insert_xml vteam_bd
617 hteam_bd_fk <- insert_xml hteam_bd
619 -- Insert the runs-by-innings associated with the vteam/hteam
621 forM_ (xml_runs_by_innings vteam_bd) $ insert_xml_fk_ vteam_bd_fk
622 forM_ (xml_runs_by_innings hteam_bd) $ insert_xml_fk_ hteam_bd_fk
624 -- Now the join table record that ties the message to its two team
626 let msg__breakdown = MLBBoxScore_MLBBoxScoreTeamBreakdown
631 insert_ msg__breakdown
633 -- Now insert the homerun stats listings, keyed to the message.
634 -- They need not be present, but we're going to loop through them
635 -- all anyway, so if we have 'Nothing', we convert that to an
636 -- empty list instead. This simplifies the `forM_` code.
637 let listings = fromMaybe [] (xml_homerun_stats_listings m)
638 forM_ listings $ \listing -> do
639 -- Insert the listing itself.
640 listing_id <- insert_xml_fk msg_id listing
641 -- And all of its pitchers
642 forM_ (xml_pitchers listing) $ insert_xml_fk listing_id
644 -- We have two tables of pitching stats that need to be keyed to
646 let iws = xml_intentional_walks (xml_misc_pitching_stats m)
647 forM_ iws $ insert_xml_fk_ msg_id
649 let hbps = xml_hits_by_pitch (xml_misc_pitching_stats m)
650 forM_ hbps $ insert_xml_fk_ msg_id
652 return ImportSucceeded
656 mkPersist tsn_codegen_config [groundhog|
657 - entity: MLBBoxScore
658 dbName: mlb_box_scores
662 - name: unique_mlb_box_scores
664 # Prevent multiple imports of the same message.
665 fields: [db_xml_file_id]
669 - entity: MLBBoxScoreMiscPitchingStatsIntentionalWalk
670 dbName: mlb_box_scores_misc_pitching_stats_intentional_walks
672 - name: MLBBoxScoreMiscPitchingStatsIntentionalWalk
674 - name: dbiw_mlb_box_scores_id
679 - entity: MLBBoxScoreMiscPitchingStatsHitByPitch
680 dbName: mlb_box_scores_misc_pitching_stats_hits_by_pitch
682 - name: MLBBoxScoreMiscPitchingStatsHitByPitch
684 - name: dbhbp_mlb_box_scores_id
689 - embedded: MLBBoxScoreHomerunStatsListingBatter
691 - name: db_batter_first_name
692 dbName: batter_first_name
693 - name: db_batter_last_name
694 dbName: batter_last_name
695 - name: db_batter_rbis
700 - entity: MLBBoxScoreHomerunStatsListing
701 dbName: mlb_box_score_homerun_stats_listings
703 - name: MLBBoxScoreHomerunStatsListing
707 - {name: batter_first_name, dbName: batter_first_name}
708 - {name: batter_last_name, dbName: batter_last_name}
709 - {name: batter_rbis, dbName: batter_rbis}
710 - {name: batter_id, dbName: batter_id}
712 - entity: MLBBoxScoreHomerunStatsListingPitcher
713 dbName: mlb_box_score_homerun_stats_listing_pitchers
715 - name: MLBBoxScoreHomerunStatsListingPitcher
717 - name: db_mlb_box_score_homerun_stats_listings_id
721 - entity: MLBBoxScoreTeamBreakdown
722 dbName: mlb_box_scores_team_breakdowns
724 - name: MLBBoxScoreTeamBreakdown
726 - entity: MLBBoxScoreRunsByInnings
727 dbName: mlb_box_scores_team_breakdowns_runs_by_innings
729 - name: MLBBoxScoreRunsByInnings
731 - name: db_mlb_box_scores_team_breakdowns_id
736 - entity: MLBBoxScore_MLBBoxScoreTeamBreakdown
737 dbName: mlb_box_scores__mlb_box_scores_team_breakdowns
739 - name: MLBBoxScore_MLBBoxScoreTeamBreakdown
741 - name: mLBBoxScore_MLBBoxScoreTeamBreakdown0
742 dbName: mlb_box_scores_id
745 - name: mLBBoxScore_MLBBoxScoreTeamBreakdown1
746 dbName: mlb_box_scores_team_breakdowns_away_team_id
749 - name: mLBBoxScore_MLBBoxScoreTeamBreakdown2
750 dbName: db_mlb_box_scores_team_breakdowns_home_team_id
761 pickle_message :: PU Message
764 xpWrap (from_tuple, H.convert) $
765 xp23Tuple (xpElem "XML_File_ID" xpInt)
766 (xpElem "heading" xpText)
767 (xpElem "category" xpText)
768 (xpElem "sport" xpText)
769 (xpElem "game_id" xpInt)
770 (xpElem "schedule_id" xpInt)
771 (xpElem "vteam" xpText)
772 (xpElem "hteam" xpText)
773 (xpElem "vteam_id" xpText)
774 (xpElem "hteam_id" xpText)
775 (xpElem "Season" xpText)
776 (xpElem "SeasonType" xpText)
777 (xpElem "title" xpText)
778 (xpElem "Game_Date" xp_date)
779 (xpElem "Game_Time" xp_time)
780 (xpElem "GameNumber" xpInt)
781 (xpElem "Capacity" xpInt)
782 pickle_game_breakdown
783 (xpList pickle_team_summary)
784 pickle_misc_pitching_stats
785 (xpOption pickle_homerun_stats_listings)
786 pickle_miscellaneous_game_info
787 (xpElem "time_stamp" xp_time_stamp)
789 from_tuple = uncurryN Message
792 pickle_team_summary :: PU MLBBoxScoreTeamSummaryXml
793 pickle_team_summary =
794 xpElem "Team_Summary" $ xpWrap (from_tuple, to_tuple') $ xpUnit
796 from_tuple _ = MLBBoxScoreTeamSummaryXml
799 pickle_game_breakdown :: PU MLBBoxScoreGameBreakdownXml
800 pickle_game_breakdown =
801 xpElem "Game_Breakdown" $
802 xpWrap (from_tuple, H.convert) $
803 xpPair pickle_away_team
806 from_tuple = uncurry MLBBoxScoreGameBreakdownXml
809 pickle_runs_by_innings :: PU MLBBoxScoreRunsByInningsXml
810 pickle_runs_by_innings =
811 xpElem "Runs_By_Innings" $
812 xpWrap (from_tuple, H.convert) $
813 xpPair (xpAttr "Inning" xpInt)
816 from_tuple = uncurry MLBBoxScoreRunsByInningsXml
819 pickle_team :: PU MLBBoxScoreTeamBreakdownXml
821 xpWrap (from_tuple, H.convert) $
822 xp4Tuple (xpList pickle_runs_by_innings)
823 (xpElem "Runs" xpInt)
824 (xpElem "Hits" xpInt)
825 (xpElem "Errors" xpInt)
827 from_tuple = uncurryN MLBBoxScoreTeamBreakdownXml
830 pickle_away_team :: PU MLBBoxScoreTeamBreakdownXml
832 xpElem "AwayTeam" pickle_team
834 pickle_home_team :: PU MLBBoxScoreTeamBreakdownXml
836 xpElem "HomeTeam" pickle_team
839 pickle_batter :: PU MLBBoxScoreHomerunStatsListingBatter
841 xpElem "HRS_Batter_ID" $
842 xpWrap (from_tuple, H.convert) $
843 xp4Tuple (xpAttr "HRS_Batter_FirstName" $ xpText)
844 (xpAttr "HRS_Batter_LastName" $ xpText)
845 (xpAttr "RBIs" $ xpInt)
848 from_tuple = uncurryN MLBBoxScoreHomerunStatsListingBatter
851 pickle_pitcher :: PU MLBBoxScoreHomerunStatsListingPitcherXml
853 xpElem "HRS_Pitcher_ID" $
854 xpWrap (from_tuple, H.convert) $
855 xp4Tuple (xpAttr "HRS_Homeruns_Off_Pitcher" $ xpInt)
856 (xpAttr "HRS_Pitcher_FirstName" $ xpText)
857 (xpAttr "HRS_Pitcher_LastName" $ xpText)
860 from_tuple = uncurryN MLBBoxScoreHomerunStatsListingPitcherXml
863 pickle_homerun_stats_listing :: PU MLBBoxScoreHomerunStatsListingXml
864 pickle_homerun_stats_listing =
865 xpElem "HRS_Listing" $
866 xpWrap (from_tuple, H.convert) $
867 xpTriple pickle_batter
868 (xpElem "Season_Homeruns" xpInt)
869 (xpList pickle_pitcher)
871 from_tuple = uncurryN MLBBoxScoreHomerunStatsListingXml
874 pickle_homerun_stats_listings :: PU [MLBBoxScoreHomerunStatsListingXml]
875 pickle_homerun_stats_listings =
876 xpElem "Homerun_Stats" $ xpList pickle_homerun_stats_listing
879 pickle_misc_pitching_stats :: PU MLBBoxScoreMiscPitchingStatsXml
880 pickle_misc_pitching_stats =
881 xpElem "Misc_Pitching_Stats" $
882 xpWrap (from_tuple, H.convert) $
883 xpTriple (xpOption $ xpElem "Wild_Pitches" xpInt)
884 pickle_intentional_walks
887 from_tuple = uncurryN MLBBoxScoreMiscPitchingStatsXml
891 pickle_intentional_walks :: PU [MLBBoxScoreMiscPitchingStatsIntentionalWalkXml]
892 pickle_intentional_walks =
893 xpElem "Intentional_Walks" $ xpList $ xpElem "IW_Listing" $
894 xpWrap (from_tuple, H.convert) $
895 xpTriple (xpElem "IW_Batter_ID" xpInt)
896 (xpElem "IW_Pitcher_ID" xpInt)
897 (xpElem "IW_Number_Of_Times_Walked" xpInt)
899 from_tuple = uncurryN MLBBoxScoreMiscPitchingStatsIntentionalWalkXml
903 pickle_hits_by_pitch :: PU [MLBBoxScoreMiscPitchingStatsHitByPitchXml]
904 pickle_hits_by_pitch =
905 xpElem "Hit_By_Pitch" $ xpList $ xpElem "HBP_Listing" $
906 xpWrap (from_tuple, H.convert) $
907 xpTriple (xpElem "HBP_Batter_ID" xpInt)
908 (xpElem "HBP_Pitcher_ID" xpInt)
909 (xpElem "HBP_Number_Of_Times_Hit" xpInt)
911 from_tuple = uncurryN MLBBoxScoreMiscPitchingStatsHitByPitchXml
915 pickle_miscellaneous_game_info :: PU MLBBoxScoreMiscellaneousGameInfoXml
916 pickle_miscellaneous_game_info =
917 xpElem "Miscelaneous_Game_Info" $ xpWrap (from_tuple, to_tuple') $ xpUnit
919 from_tuple _ = MLBBoxScoreMiscellaneousGameInfoXml