From 23e9b5960b6183206ba95c908978bb409f4e19e1 Mon Sep 17 00:00:00 2001 From: Marjan Kalanaki Date: Tue, 17 Dec 2024 12:37:09 +0000 Subject: [PATCH] refactor the data model and summerise the competion in response --- .../controllers/MatchListController.scala | 45 ++++++++--------- ...=> DotcomRenderingFootballDataModel.scala} | 50 ++++++++++++++----- sport/app/football/model/model.scala | 10 +++- 3 files changed, 67 insertions(+), 38 deletions(-) rename sport/app/football/model/{LiveScores.scala => DotcomRenderingFootballDataModel.scala} (61%) diff --git a/sport/app/football/controllers/MatchListController.scala b/sport/app/football/controllers/MatchListController.scala index 4ef86441361a..a4e1eeb76f59 100644 --- a/sport/app/football/controllers/MatchListController.scala +++ b/sport/app/football/controllers/MatchListController.scala @@ -2,10 +2,11 @@ package football.controllers import common.{Edition, JsonComponent} import feed.Competitions -import football.model.{CompetitionMatches, DateCompetitionMatches, MatchesList, LiveScores} +import football.model.{DotcomRenderingFootballDataModel, MatchesList} +import football.model.DotcomRenderingFootballDataModelImplicits._ import implicits.Requests import model.Cached.RevalidatableResult -import model.{ApplicationContext, CacheTime, Cached, Competition, TeamMap} +import model.{ApplicationContext, Cached, Competition, TeamMap} import java.time.LocalDate import pa.FootballTeam @@ -28,31 +29,25 @@ trait MatchListController extends BaseController with Requests { filters: Map[String, Seq[CompetitionFilter]], atom: Option[InteractiveAtom] = None, )(implicit request: RequestHeader, context: ApplicationContext) = { + Cached(10) { + if (request.isJson && request.forceDCR) { + val model = DotcomRenderingFootballDataModel( + pageTitle = matchesList.getPageTitle(Edition(request)), + pageType = matchesList.pageType, + matchesList = DotcomRenderingFootballDataModel.getMatchesList(matchesList.matchesGroupedByDateAndCompetition), + ) - if (request.isJson && request.forceDCR) { - val model = LiveScores( - pageTitle = matchesList.getPageTitle(Edition(request)), - pageType = matchesList.pageType, - matchesGroupedByDateAndCompetition = matchesList.matchesGroupedByDateAndCompetition.map { item => - DateCompetitionMatches(date = item._1, competitions = item._2.map(a => CompetitionMatches(a._1, a._2))) - }, - nextPage = None, - ) - Cached(CacheTime.Default)(RevalidatableResult.Ok(LiveScores.toJson(model))).as("application/json") - } else { - Cached(10) { - if (request.isJson) - JsonComponent( - "html" -> football.views.html.matchList.matchesComponent(matchesList), - "next" -> Html(matchesList.nextPage.getOrElse("")), - "previous" -> Html(matchesList.previousPage.getOrElse("")), - "atom" -> atom.isDefined, - ) - else - RevalidatableResult.Ok(football.views.html.matchList.matchesPage(page, matchesList, filters, atom)) - } + JsonComponent.fromWritable(model) + } else if (request.isJson) { + JsonComponent( + "html" -> football.views.html.matchList.matchesComponent(matchesList), + "next" -> Html(matchesList.nextPage.getOrElse("")), + "previous" -> Html(matchesList.previousPage.getOrElse("")), + "atom" -> atom.isDefined, + ) + } else + RevalidatableResult.Ok(football.views.html.matchList.matchesPage(page, matchesList, filters, atom)) } - } protected def renderMoreMatches( diff --git a/sport/app/football/model/LiveScores.scala b/sport/app/football/model/DotcomRenderingFootballDataModel.scala similarity index 61% rename from sport/app/football/model/LiveScores.scala rename to sport/app/football/model/DotcomRenderingFootballDataModel.scala index 38f344366b96..02dcd1f47a6d 100644 --- a/sport/app/football/model/LiveScores.scala +++ b/sport/app/football/model/DotcomRenderingFootballDataModel.scala @@ -1,6 +1,6 @@ package football.model -import model.Competition +import model.{Competition, CompetitionSummary} import model.dotcomrendering.DotcomRenderingUtils.withoutNull import pa.{ Fixture, @@ -18,22 +18,39 @@ import pa.{ Venue, Competition => PaCompetition, } -import play.api.libs.json.{JsObject, JsString, Json, Writes} +import play.api.libs.json.{JsObject, JsString, JsValue, Json, Writes} import java.time.LocalDate import java.time.format.DateTimeFormatter -case class CompetitionMatches(competition: Competition, matches: List[FootballMatch]) -case class DateCompetitionMatches(date: LocalDate, competitions: List[CompetitionMatches]) +case class CompetitionMatches(competitionSummary: CompetitionSummary, matches: List[FootballMatch]) +case class MatchesByDateAndCompetition(date: LocalDate, competitionMatches: List[CompetitionMatches]) -case class LiveScores( +case class DotcomRenderingFootballDataModel( pageTitle: String, pageType: String, - matchesGroupedByDateAndCompetition: Seq[DateCompetitionMatches], - nextPage: Option[String], + matchesList: Seq[MatchesByDateAndCompetition], ) -object LiveScores { +object DotcomRenderingFootballDataModel { + def getMatchesList( + matches: Seq[(LocalDate, List[(Competition, List[FootballMatch])])], + ): Seq[MatchesByDateAndCompetition] = { + matches.map { case (date, competitionMatches) => + MatchesByDateAndCompetition( + date = date, + competitionMatches = competitionMatches.map { case (competition, matches) => + CompetitionMatches( + competitionSummary = competition, + matches = matches, + ) + }, + ) + } + } +} + +object DotcomRenderingFootballDataModelImplicits { implicit val localDateWrites: Writes[LocalDate] = Writes[LocalDate] { date => JsString(date.format(DateTimeFormatter.ISO_LOCAL_DATE)) } @@ -78,12 +95,21 @@ object LiveScores { implicit val leagueTeamWrites: Writes[LeagueTeam] = Json.writes[LeagueTeam] implicit val leagueTableEntryWrites: Writes[LeagueTableEntry] = Json.writes[LeagueTableEntry] - implicit val competitionFormat: Writes[Competition] = Json.writes[Competition] + implicit val competitionFormat: Writes[CompetitionSummary] = new Writes[CompetitionSummary] { + def writes(competition: CompetitionSummary): JsValue = Json.obj( + "id" -> competition.id, + "url" -> competition.url, + "fullName" -> competition.fullName, + "shortName" -> competition.shortName, + ) + } implicit val competitionMatchesFormat: Writes[CompetitionMatches] = Json.writes[CompetitionMatches] - implicit val dateCompetitionMatchesFormat: Writes[DateCompetitionMatches] = Json.writes[DateCompetitionMatches] - implicit val SportsFormat: Writes[LiveScores] = Json.writes[LiveScores] + implicit val dateCompetitionMatchesFormat: Writes[MatchesByDateAndCompetition] = + Json.writes[MatchesByDateAndCompetition] + + implicit val SportsFormat: Writes[DotcomRenderingFootballDataModel] = Json.writes[DotcomRenderingFootballDataModel] - def toJson(model: LiveScores): String = { + def toJson(model: DotcomRenderingFootballDataModel): String = { val jsValue = Json.toJson(model) Json.stringify(withoutNull(jsValue)) } diff --git a/sport/app/football/model/model.scala b/sport/app/football/model/model.scala index f17b20b24717..45057f235448 100644 --- a/sport/app/football/model/model.scala +++ b/sport/app/football/model/model.scala @@ -6,6 +6,13 @@ import pa.MatchDayTeam import java.awt.Color import java.time.LocalDate +trait CompetitionSummary { + def id: String + def url: String + def fullName: String + def shortName: String +} + /** @param tableDividers * divides the league table into zones for promotion/relegation, or for qualification to another competition. Only * add a table divider where the boundaries for progression are clear, e.g do not add a divider in Euro group stages @@ -23,7 +30,8 @@ case class Competition( showInTeamsList: Boolean = false, tableDividers: List[Int] = Nil, finalMatchSVG: Option[String] = None, -) extends implicits.Football { +) extends implicits.Football + with CompetitionSummary { lazy val hasMatches = matches.nonEmpty lazy val hasLiveMatches = matches.exists(_.isLive)