139 lines
4.6 KiB
Go
139 lines
4.6 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 {
|
|
AssignmentMode *string `json:"assignmentMode,omitempty"`
|
|
CourseVariants []CourseVariantView `json:"courseVariants,omitempty"`
|
|
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
|
|
variantPlan := resolveVariantPlan(event.ReleasePayloadJSON)
|
|
result.Play.AssignmentMode = variantPlan.AssignmentMode
|
|
if len(variantPlan.CourseVariants) > 0 {
|
|
result.Play.CourseVariants = variantPlan.CourseVariants
|
|
}
|
|
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 isSessionOngoingStatus(sessions[i].Status) {
|
|
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
|
|
}
|