@@ -2,35 +2,25 @@ package com.gu.mobile.notifications.client.models.liveActitivites
22
33import play .api .libs .json ._
44
5-
6-
75/**
86 * These are the Live Activity Content models used for sending live activity
97 * updates to Apple APNS service.
108 **/
119
12-
13-
1410// GENERIC CONTENT STATE //////////////////////////////////////////////////
1511sealed trait ContentState
1612object ContentState {
1713 import FootballContentJsonFormats ._
1814
19- implicit val format : OFormat [ContentState ] = new OFormat [ContentState ] {
15+ implicit val contentStateFormat : OFormat [ContentState ] = new OFormat [ContentState ] {
2016 def writes (cs : ContentState ): JsObject = cs match {
21- case f : FootballMatchContentState =>
22- footballMatchContentStateFormat
23- .writes(f)
24- .as[JsObject ] + (" type" -> JsString (" football" ))
25- // Add cases for other ContentState subtypes here
17+ case f : FootballMatchContentState => footballMatchContentStateFormat.writes(f)
2618 }
27-
2819 def reads (json : JsValue ): JsResult [ContentState ] = {
29- (json \ " type" ).validate[String ].flatMap {
30- case " football" => footballMatchContentStateFormat.reads(json)
31- // Add cases for other ContentState subtypes here
32- case other => JsError (s " Unknown ContentState type: $other" )
33- }
20+ // todo - if we add more content states for other live activity types
21+ // todo - check adding a _type field to the json?
22+ // Try FootballMatchContentState - could check a distinguishing field if needed
23+ footballMatchContentStateFormat.reads(json)
3424 }
3525 }
3626}
@@ -43,44 +33,78 @@ case object PreMatch extends MatchStatus { val status = "PRE_MATCH" }
4333case object FirstHalf extends MatchStatus { val status = " FIRST_HALF" }
4434case object HalfTime extends MatchStatus { val status = " HALF_TIME" }
4535case object SecondHalf extends MatchStatus { val status = " SECOND_HALF" }
36+ case object ExtraTimeToBePlayed extends MatchStatus { val status = " EXTRA_TIME_TO_BE_PLAYED" }
4637case object ExtraTimeFirstHalf extends MatchStatus { val status = " EXTRA_TIME_FIRST_HALF" }
4738case object ExtraTimeHalfTime extends MatchStatus { val status = " EXTRA_TIME_HALF_TIME" }
4839case object ExtraTimeSecondHalf extends MatchStatus { val status = " EXTRA_TIME_SECOND_HALF" }
40+ case object PenaltiesToBePlayed extends MatchStatus { val status = " PENALTIES_TO_BE_PLAYED" }
4941case object Penalties extends MatchStatus { val status = " PENALTIES" }
5042case object FullTime extends MatchStatus { val status = " FULL_TIME" }
5143case object Postponed extends MatchStatus { val status = " POSTPONED" }
44+ case object Suspended extends MatchStatus { val status = " SUSPENDED" }
5245case object Abandoned extends MatchStatus { val status = " ABANDONED" }
46+ case object Resumed extends MatchStatus { val status = " RESUMED" }
47+ case object Cancelled extends MatchStatus { val status = " CANCELLED" }
5348// @formatter:on
5449
5550object MatchStatus {
56- def fromString (s : String ): MatchStatus = s match {
57- case " Pre-match" | " prematch" => PreMatch
58- case " MatchInProgress" | " 1st Half" | " first_half" => FirstHalf
59- case " HalfTime" | " Half Time" | " half_time" => HalfTime
60- case " 2nd Half" | " second_half" => SecondHalf
61- case " Extra Time" | " ET 1st Half" => ExtraTimeFirstHalf
62- case " ET Half Time" => ExtraTimeHalfTime
63- case " ET 2nd Half" => ExtraTimeSecondHalf
64- case " Penalties" => Penalties
65- case " MatchComplete" | " MC" | " Full Time" | " Result" => FullTime
66- case " Postponed" => Postponed
67- case " Abandoned" => Abandoned
68- case _ => Scheduled
69- }
51+ def fromString (s : String ): MatchStatus = statuses.getOrElse(s, Scheduled )
52+
53+ // How PA match status are handled here differs from push notification mappings
54+ private val statuses : Map [String , MatchStatus ] = Map (
55+ (" Fixture" , PreMatch ), //
56+ (" -" , PreMatch ), // seen in the wild
57+ (" New" , PreMatch ), //
58+
59+ (" KO" , FirstHalf ), // The Match has started (Kicked Off).
60+
61+ (" HT" , HalfTime ), // The Referee has blown the whistle for Half Time.
62+
63+ (" SHS" , SecondHalf ), // The Second Half of the Match has Started.
64+
65+ (" FT" , FullTime ), // The Referee has blown the whistle for Full Time.
66+ (" Result" , FullTime ), // The Result is official.
67+ (" MC" , FullTime ), // Match has been Completed.
68+
69+ (" FTET" , ExtraTimeToBePlayed ), // Full Time, Extra Time it to be played.
70+ (" ETS" , ExtraTimeFirstHalf ), // Extra Time has Started.
71+ (" ETHT" , ExtraTimeHalfTime ), // Extra Time Half Time has been called.
72+ (" ETSHS" , ExtraTimeSecondHalf ), // Extra Time, Second Half has Started.
73+ (" ETFT" , ExtraTimeSecondHalf ), // Extra Time, Full Time has been blown.
74+
75+ (" FTPT" , PenaltiesToBePlayed ), // Full Time, Penalties are To be played.
76+ (" ETFTPT" , PenaltiesToBePlayed ), // Extra Time, Full Time, Penalties are To be played.
77+ (" PT" , Penalties ), // Penalty ShooT Out has started.
78+ (" PTFT" , Penalties ), // Penalty ShooT Full Time.
79+
80+ // edge cases
81+ (" Suspended" , Suspended ), // Match has been Suspended.
82+ (" Resumed" , Resumed ), // Match has been Resumed. // todo can match phase be determined by match minute?
83+ (" Abandoned" , Abandoned ), // Match has been Abandoned.
84+ (" Postponed" , Postponed ), // A Match has been Postponed.
85+ (" Cancelled" , Cancelled ) // A Match has been Cancelled.
86+ )
7087}
7188
7289case class Competition (
90+ id : String ,
7391 name : String ,
74- round : Option [String ] = None
92+ round : Option [String ] = None // World Cup Group name
93+ )
94+
95+ case class PenaltyShootoutState (
96+ scored : Int = 0 ,
97+ missed : Int = 0 ,
98+ saved : Int = 0 ,
7599)
76100
77101case class TeamState (
78102 name : String ,
79- score : Int = 0 ,
80103 logoAssetName : Option [String ] = None ,
81104 teamUrl : Option [String ] = None ,
82- penaltyScore : Option [Int ] = None ,
83- redCards : Int = 0
105+ score : Int = 0 ,
106+ redCards : Int = 0 ,
107+ penaltyScore : Option [PenaltyShootoutState ] = None
84108)
85109
86110case class FootballMatchContentState (
@@ -108,24 +132,27 @@ object FootballContentJsonFormats {
108132 case " FIRST_HALF" => JsSuccess (FirstHalf )
109133 case " HALF_TIME" => JsSuccess (HalfTime )
110134 case " SECOND_HALF" => JsSuccess (SecondHalf )
135+ case " EXTRA_TIME_TO_BE_PLAYED" => JsSuccess (ExtraTimeToBePlayed )
111136 case " EXTRA_TIME_FIRST_HALF" => JsSuccess (ExtraTimeFirstHalf )
112137 case " EXTRA_TIME_HALF_TIME" => JsSuccess (ExtraTimeHalfTime )
113138 case " EXTRA_TIME_SECOND_HALF" => JsSuccess (ExtraTimeSecondHalf )
139+ case " PENALTIES_TO_BE_PLAYED" => JsSuccess (PenaltiesToBePlayed )
114140 case " PENALTIES" => JsSuccess (Penalties )
115141 case " FULL_TIME" => JsSuccess (FullTime )
142+ case " SUSPENDED" => JsSuccess (Suspended )
143+ case " RESUMED" => JsSuccess (Resumed )
116144 case " POSTPONED" => JsSuccess (Postponed )
117145 case " ABANDONED" => JsSuccess (Abandoned )
146+ case " CANCELLED" => JsSuccess (Cancelled )
118147 case other => JsError (s " Unknown match status: $other" )
119148 }
120149 case _ => JsError (" Expected a JSON string for MatchStatus" )
121150 },
122151 Writes (ms => JsString (ms.status))
123152 )
124153
125- implicit val competitionFormat : OFormat [Competition ] =
126- Json .format[Competition ]
154+ implicit val competitionFormat : OFormat [Competition ] = Json .format[ Competition ]
155+ implicit val penaltyShootoutStateFormat : OFormat [ PenaltyShootoutState ] = Json .format[PenaltyShootoutState ]
127156 implicit val teamStateFormat : OFormat [TeamState ] = Json .format[TeamState ]
128- implicit val footballMatchContentStateFormat
129- : OFormat [FootballMatchContentState ] =
130- Json .format[FootballMatchContentState ]
157+ implicit val footballMatchContentStateFormat : OFormat [FootballMatchContentState ] = Json .format[FootballMatchContentState ]
131158}
0 commit comments