Files
cmr-mini/backend/internal/service/event_play_service.go

132 lines
4.3 KiB
Go

package service
import (
"context"
"net/http"
"strings"
"cmr-backend/internal/apperr"
"cmr-backend/internal/store/postgres"
)
type EventPlayService struct {
store *postgres.Store
}
type EventPlayInput struct {
EventPublicID string
UserID string
}
type EventPlayResult struct {
Event struct {
ID string `json:"id"`
Slug string `json:"slug"`
DisplayName string `json:"displayName"`
Summary *string `json:"summary,omitempty"`
Status string `json:"status"`
} `json:"event"`
Release *struct {
ID string `json:"id"`
ConfigLabel string `json:"configLabel"`
ManifestURL string `json:"manifestUrl"`
ManifestChecksumSha256 *string `json:"manifestChecksumSha256,omitempty"`
RouteCode *string `json:"routeCode,omitempty"`
} `json:"release,omitempty"`
ResolvedRelease *ResolvedReleaseView `json:"resolvedRelease,omitempty"`
Play struct {
CanLaunch bool `json:"canLaunch"`
PrimaryAction string `json:"primaryAction"`
Reason string `json:"reason"`
LaunchSource string `json:"launchSource,omitempty"`
OngoingSession *EntrySessionSummary `json:"ongoingSession,omitempty"`
RecentSession *EntrySessionSummary `json:"recentSession,omitempty"`
} `json:"play"`
}
func NewEventPlayService(store *postgres.Store) *EventPlayService {
return &EventPlayService{store: store}
}
func (s *EventPlayService) GetEventPlay(ctx context.Context, input EventPlayInput) (*EventPlayResult, error) {
input.EventPublicID = strings.TrimSpace(input.EventPublicID)
input.UserID = strings.TrimSpace(input.UserID)
if input.EventPublicID == "" {
return nil, apperr.New(http.StatusBadRequest, "invalid_params", "event id is required")
}
if input.UserID == "" {
return nil, apperr.New(http.StatusUnauthorized, "unauthorized", "user is required")
}
event, err := s.store.GetEventByPublicID(ctx, input.EventPublicID)
if err != nil {
return nil, err
}
if event == nil {
return nil, apperr.New(http.StatusNotFound, "event_not_found", "event not found")
}
sessions, err := s.store.ListSessionsByUserAndEvent(ctx, input.UserID, event.ID, 10)
if err != nil {
return nil, err
}
result := &EventPlayResult{}
result.Event.ID = event.PublicID
result.Event.Slug = event.Slug
result.Event.DisplayName = event.DisplayName
result.Event.Summary = event.Summary
result.Event.Status = event.Status
if event.CurrentReleasePubID != nil && event.ConfigLabel != nil && event.ManifestURL != nil {
result.Release = &struct {
ID string `json:"id"`
ConfigLabel string `json:"configLabel"`
ManifestURL string `json:"manifestUrl"`
ManifestChecksumSha256 *string `json:"manifestChecksumSha256,omitempty"`
RouteCode *string `json:"routeCode,omitempty"`
}{
ID: *event.CurrentReleasePubID,
ConfigLabel: *event.ConfigLabel,
ManifestURL: *event.ManifestURL,
ManifestChecksumSha256: event.ManifestChecksum,
RouteCode: event.RouteCode,
}
}
result.ResolvedRelease = buildResolvedReleaseFromEvent(event, LaunchSourceEventCurrentRelease)
if len(sessions) > 0 {
recent := buildEntrySessionSummary(&sessions[0])
result.Play.RecentSession = &recent
}
for i := range sessions {
if sessions[i].Status == "launched" || sessions[i].Status == "running" {
ongoing := buildEntrySessionSummary(&sessions[i])
result.Play.OngoingSession = &ongoing
break
}
}
canLaunch := event.Status == "active" && event.CurrentReleaseID != nil && event.ManifestURL != nil
result.Play.CanLaunch = canLaunch
if canLaunch {
result.Play.LaunchSource = LaunchSourceEventCurrentRelease
}
switch {
case result.Play.OngoingSession != nil:
result.Play.PrimaryAction = "continue"
result.Play.Reason = "user has an ongoing session for this event"
case canLaunch:
result.Play.PrimaryAction = "start"
result.Play.Reason = "event is active and launchable"
case result.Play.RecentSession != nil:
result.Play.PrimaryAction = "review_last_result"
result.Play.Reason = "event is not launchable, but user has previous session history"
default:
result.Play.PrimaryAction = "unavailable"
result.Play.Reason = "event is not launchable"
}
return result, nil
}