event_play_service.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package service
  2. import (
  3. "context"
  4. "net/http"
  5. "strings"
  6. "cmr-backend/internal/apperr"
  7. "cmr-backend/internal/store/postgres"
  8. )
  9. type EventPlayService struct {
  10. store *postgres.Store
  11. }
  12. type EventPlayInput struct {
  13. EventPublicID string
  14. UserID string
  15. }
  16. type EventPlayResult struct {
  17. Event struct {
  18. ID string `json:"id"`
  19. Slug string `json:"slug"`
  20. DisplayName string `json:"displayName"`
  21. Summary *string `json:"summary,omitempty"`
  22. Status string `json:"status"`
  23. } `json:"event"`
  24. Release *struct {
  25. ID string `json:"id"`
  26. ConfigLabel string `json:"configLabel"`
  27. ManifestURL string `json:"manifestUrl"`
  28. ManifestChecksumSha256 *string `json:"manifestChecksumSha256,omitempty"`
  29. RouteCode *string `json:"routeCode,omitempty"`
  30. } `json:"release,omitempty"`
  31. ResolvedRelease *ResolvedReleaseView `json:"resolvedRelease,omitempty"`
  32. Play struct {
  33. CanLaunch bool `json:"canLaunch"`
  34. PrimaryAction string `json:"primaryAction"`
  35. Reason string `json:"reason"`
  36. LaunchSource string `json:"launchSource,omitempty"`
  37. OngoingSession *EntrySessionSummary `json:"ongoingSession,omitempty"`
  38. RecentSession *EntrySessionSummary `json:"recentSession,omitempty"`
  39. } `json:"play"`
  40. }
  41. func NewEventPlayService(store *postgres.Store) *EventPlayService {
  42. return &EventPlayService{store: store}
  43. }
  44. func (s *EventPlayService) GetEventPlay(ctx context.Context, input EventPlayInput) (*EventPlayResult, error) {
  45. input.EventPublicID = strings.TrimSpace(input.EventPublicID)
  46. input.UserID = strings.TrimSpace(input.UserID)
  47. if input.EventPublicID == "" {
  48. return nil, apperr.New(http.StatusBadRequest, "invalid_params", "event id is required")
  49. }
  50. if input.UserID == "" {
  51. return nil, apperr.New(http.StatusUnauthorized, "unauthorized", "user is required")
  52. }
  53. event, err := s.store.GetEventByPublicID(ctx, input.EventPublicID)
  54. if err != nil {
  55. return nil, err
  56. }
  57. if event == nil {
  58. return nil, apperr.New(http.StatusNotFound, "event_not_found", "event not found")
  59. }
  60. sessions, err := s.store.ListSessionsByUserAndEvent(ctx, input.UserID, event.ID, 10)
  61. if err != nil {
  62. return nil, err
  63. }
  64. result := &EventPlayResult{}
  65. result.Event.ID = event.PublicID
  66. result.Event.Slug = event.Slug
  67. result.Event.DisplayName = event.DisplayName
  68. result.Event.Summary = event.Summary
  69. result.Event.Status = event.Status
  70. if event.CurrentReleasePubID != nil && event.ConfigLabel != nil && event.ManifestURL != nil {
  71. result.Release = &struct {
  72. ID string `json:"id"`
  73. ConfigLabel string `json:"configLabel"`
  74. ManifestURL string `json:"manifestUrl"`
  75. ManifestChecksumSha256 *string `json:"manifestChecksumSha256,omitempty"`
  76. RouteCode *string `json:"routeCode,omitempty"`
  77. }{
  78. ID: *event.CurrentReleasePubID,
  79. ConfigLabel: *event.ConfigLabel,
  80. ManifestURL: *event.ManifestURL,
  81. ManifestChecksumSha256: event.ManifestChecksum,
  82. RouteCode: event.RouteCode,
  83. }
  84. }
  85. result.ResolvedRelease = buildResolvedReleaseFromEvent(event, LaunchSourceEventCurrentRelease)
  86. if len(sessions) > 0 {
  87. recent := buildEntrySessionSummary(&sessions[0])
  88. result.Play.RecentSession = &recent
  89. }
  90. for i := range sessions {
  91. if isSessionOngoingStatus(sessions[i].Status) {
  92. ongoing := buildEntrySessionSummary(&sessions[i])
  93. result.Play.OngoingSession = &ongoing
  94. break
  95. }
  96. }
  97. canLaunch := event.Status == "active" && event.CurrentReleaseID != nil && event.ManifestURL != nil
  98. result.Play.CanLaunch = canLaunch
  99. if canLaunch {
  100. result.Play.LaunchSource = LaunchSourceEventCurrentRelease
  101. }
  102. switch {
  103. case result.Play.OngoingSession != nil:
  104. result.Play.PrimaryAction = "continue"
  105. result.Play.Reason = "user has an ongoing session for this event"
  106. case canLaunch:
  107. result.Play.PrimaryAction = "start"
  108. result.Play.Reason = "event is active and launchable"
  109. case result.Play.RecentSession != nil:
  110. result.Play.PrimaryAction = "review_last_result"
  111. result.Play.Reason = "event is not launchable, but user has previous session history"
  112. default:
  113. result.Play.PrimaryAction = "unavailable"
  114. result.Play.Reason = "event is not launchable"
  115. }
  116. return result, nil
  117. }