package gameplay_service import ( "context" "evening_detective_server/internal/modules/cleaner" "evening_detective_server/internal/modules/game_model" "evening_detective_server/internal/modules/storytelling" "evening_detective_server/internal/repos/actions_repo" "evening_detective_server/internal/repos/applications_repo" "evening_detective_server/internal/repos/games_repo" "evening_detective_server/internal/repos/teams_repo" "evening_detective_server/internal/services/scenarios_service" ) type GameplayService struct { gamesRepo *games_repo.GamesRepo teamsRepo *teams_repo.TeamsRepo scenarioService *scenarios_service.ScenarioService storyteller storytelling.IStory actionsRepo *actions_repo.ActionsRepo applicationsRepo *applications_repo.ApplicationsRepo cleaner cleaner.ICleaner domain string } func NewGameplayService( gamesRepo *games_repo.GamesRepo, teamsRepo *teams_repo.TeamsRepo, scenarioService *scenarios_service.ScenarioService, storyteller storytelling.IStory, actionsRepo *actions_repo.ActionsRepo, applicationsRepo *applications_repo.ApplicationsRepo, cleaner cleaner.ICleaner, domain string, ) *GameplayService { return &GameplayService{ gamesRepo: gamesRepo, teamsRepo: teamsRepo, scenarioService: scenarioService, storyteller: storyteller, actionsRepo: actionsRepo, applicationsRepo: applicationsRepo, cleaner: cleaner, domain: domain, } } func (s *GameplayService) GiveTeamApplications(ctx context.Context, teamId int, name string) error { return s.applicationsRepo.UpdateApplicationStatus(ctx, teamId, name, "done") } func (s *GameplayService) GetTeamActions(ctx context.Context, teamId int, password string) (*storytelling.Story, *game_model.Game, []actions_repo.Action, error) { team, err := s.teamsRepo.GetTeamByID(ctx, teamId) if err != nil { return nil, nil, nil, err } if team.Password != password || team.ParticipationStatus == "cancelled" { return nil, nil, nil, teams_repo.ErrTeamNotFound } game, err := s.gamesRepo.GetGameByID(ctx, team.GameId) if err != nil { return nil, nil, nil, err } if game.Status == "finish" { return &storytelling.Story{}, game_model.MapGame(game, s.domain), nil, nil } actions, err := s.actionsRepo.GetActionsByTeamID(ctx, teamId) if err != nil { return nil, nil, nil, err } scenario, err := s.scenarioService.GetFullScenarioByID(ctx, game.ScenarioId) if err != nil { return nil, nil, nil, err } codes := make([]string, len(actions)) for i, action := range actions { codes[i] = action.Code } story := s.storyteller.GetStory(scenario.Story, codes) filterTeamStory(story, game.Format) return story, game_model.MapGame(game, s.domain), actions, nil } func (s *GameplayService) AddTeamAction(ctx context.Context, teamId int, password string, actionCode string, viaMCP bool) error { team, err := s.teamsRepo.GetTeamByID(ctx, teamId) if err != nil { return err } if team.Password != password || team.ParticipationStatus == "cancelled" { return teams_repo.ErrTeamNotFound } _, err = s.actionsRepo.AddAction(ctx, teamId, actionCode, viaMCP) if err != nil { return err } if team.ParticipationStatus == "pending" { if err := s.teamsRepo.ConfirmParticipationByFirstAction(ctx, teamId); err != nil { return err } } game, err := s.gamesRepo.GetGameByID(ctx, team.GameId) if err != nil { return err } actionDetails, err := s.actionsRepo.GetActionsByTeamID(ctx, teamId) if err != nil { return err } scenario, err := s.scenarioService.GetFullScenarioByID(ctx, game.ScenarioId) if err != nil { return err } actions := make([]string, len(actionDetails)) for i, action := range actionDetails { actions[i] = action.Code } teamStory := s.storyteller.GetStory(scenario.Story, actions) lastPlace := teamStory.Places[len(teamStory.Places)-1] for _, application := range lastPlace.Applications { app := newApplication(application, s.domain) app.Name = s.cleaner.ClearText(app.Name) if _, err := s.applicationsRepo.AddApplication(ctx, teamId, app.Name, app.Image, app.FileType); err != nil { return err } } return nil } func (s *GameplayService) DeleteLastTeamAction(ctx context.Context, teamId int) error { team, err := s.teamsRepo.GetTeamByID(ctx, teamId) if err != nil { return err } game, err := s.gamesRepo.GetGameByID(ctx, team.GameId) if err != nil { return err } actionDetails, err := s.actionsRepo.GetActionsByTeamID(ctx, teamId) if err != nil { return err } scenario, err := s.scenarioService.GetFullScenarioByID(ctx, game.ScenarioId) if err != nil { return err } actions := make([]string, len(actionDetails)) for i, action := range actionDetails { actions[i] = action.Code } teamStory := s.storyteller.GetStory(scenario.Story, actions) lastPlace := teamStory.Places[len(teamStory.Places)-1] for _, application := range lastPlace.Applications { if err := s.applicationsRepo.DeleteApplicationByTeamIdAndName(ctx, teamId, application.Name); err != nil { return err } } return s.actionsRepo.DeleteLastActionByTeamId(ctx, teamId) }