generated from VLADIMIR/template
add online games
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
)
|
||||
|
||||
type Game struct {
|
||||
Format string
|
||||
ID int
|
||||
Name string
|
||||
Description string
|
||||
|
||||
@@ -15,6 +15,7 @@ func mapGame(
|
||||
Description: o.Description,
|
||||
StartAt: o.StartAt,
|
||||
Status: o.Status,
|
||||
Format: o.Format,
|
||||
Scenario: scenarios_service.MapScenarioLight(o.Scenario, domain),
|
||||
Teams: mapTeams(o.Teams),
|
||||
StartedAt: o.StartedAt,
|
||||
|
||||
@@ -72,8 +72,15 @@ func (s *GameService) AddGame(
|
||||
description string,
|
||||
startAt time.Time,
|
||||
scenarioId int32,
|
||||
format string,
|
||||
) (int, error) {
|
||||
id, err := s.gamesRepo.AddGame(ctx, name, description, startAt, scenarioId)
|
||||
if format == "" {
|
||||
format = "online"
|
||||
}
|
||||
if format != "online" && format != "offline" {
|
||||
return 0, errors.New("Формат игры должен быть online или offline")
|
||||
}
|
||||
id, err := s.gamesRepo.AddGame(ctx, name, description, startAt, scenarioId, format)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -170,8 +177,19 @@ func (s *GameService) UpdateGame(
|
||||
description string,
|
||||
startAt time.Time,
|
||||
scenarioId int32,
|
||||
format string,
|
||||
) error {
|
||||
return s.gamesRepo.UpdateGame(ctx, id, name, description, startAt, scenarioId)
|
||||
if format == "" {
|
||||
game, err := s.gamesRepo.GetGameByID(ctx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
format = game.Format
|
||||
}
|
||||
if format != "online" && format != "offline" {
|
||||
return errors.New("Формат игры должен быть online или offline")
|
||||
}
|
||||
return s.gamesRepo.UpdateGame(ctx, id, name, description, startAt, scenarioId, format)
|
||||
}
|
||||
|
||||
func (s *GameService) StartGame(ctx context.Context, id int) error {
|
||||
@@ -255,7 +273,9 @@ func (s *GameService) GetTeamActions(ctx context.Context, teamId int, password s
|
||||
for i, action := range actions {
|
||||
codes[i] = action.Code
|
||||
}
|
||||
return s.storyteller.GetStory(scenario.Story, codes), mapGame(game, s.domain), actions, nil
|
||||
story := s.storyteller.GetStory(scenario.Story, codes)
|
||||
filterTeamStory(story, game.Format)
|
||||
return story, mapGame(game, s.domain), actions, nil
|
||||
}
|
||||
|
||||
func (s *GameService) AddTeamAction(ctx context.Context, teamId int, password string, actionCode string, viaMCP bool) error {
|
||||
@@ -394,6 +414,9 @@ func (s *GameService) GetTeamAnswers(ctx context.Context, teamId int, password s
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if game.Format == "offline" {
|
||||
return nil, nil
|
||||
}
|
||||
_, byCode, err := s.getScenarioQuestionsByCode(ctx, game.ScenarioId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -424,6 +447,9 @@ func (s *GameService) SubmitTeamAnswers(ctx context.Context, teamId int, passwor
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if game.Format == "offline" {
|
||||
return errors.New("В offline-игре ответы через сайт недоступны")
|
||||
}
|
||||
switch game.Status {
|
||||
case "run", "pause":
|
||||
// игра идёт — можно отвечать
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package game_service
|
||||
|
||||
import "evening_detective_server/internal/modules/storytelling"
|
||||
|
||||
// filterTeamStory применяется только к истории команды, общей для сайта и MCP.
|
||||
func filterTeamStory(story *storytelling.Story, format string) {
|
||||
if format != "offline" {
|
||||
return
|
||||
}
|
||||
story.Introduction = nil
|
||||
story.Questions = nil
|
||||
for _, place := range story.Places {
|
||||
for _, application := range place.Applications {
|
||||
application.Image = ""
|
||||
application.FileType = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package game_service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"evening_detective_server/internal/modules/cleaner"
|
||||
"evening_detective_server/internal/modules/storytelling"
|
||||
)
|
||||
|
||||
func TestTeamStoryFormat(t *testing.T) {
|
||||
scenario := &storytelling.Story{
|
||||
Introduction: &storytelling.Introduction{Text: "Введение", Audio: "intro.mp3"},
|
||||
Questions: []*storytelling.Question{{Code: "q", Text: "Вопрос"}},
|
||||
Places: []*storytelling.Place{{Code: "p", Text: "Точка", Image: "place.jpg",
|
||||
Applications: []*storytelling.Application{
|
||||
{Name: "Фото", Image: "clue.jpg", FileType: "image"},
|
||||
{Name: "Документ", Image: "clue.pdf", FileType: "pdf"},
|
||||
{Name: "Запись", Image: "clue.mp3", FileType: "audio"},
|
||||
},
|
||||
}},
|
||||
}
|
||||
for _, format := range []string{"offline", "online"} {
|
||||
t.Run(format, func(t *testing.T) {
|
||||
story := storytelling.NewStory(cleaner.NewCleaner()).GetStory(scenario, []string{"p"})
|
||||
filterTeamStory(story, format)
|
||||
if len(story.Places) != 1 || story.Places[0].Text != "Точка" || story.Places[0].Image != "place.jpg" {
|
||||
t.Fatal("place content changed")
|
||||
}
|
||||
if format == "offline" {
|
||||
if story.Introduction != nil || len(story.Questions) != 0 {
|
||||
t.Fatal("offline story exposes introduction or questions")
|
||||
}
|
||||
} else if story.Introduction == nil || len(story.Questions) != 1 {
|
||||
t.Fatal("online story lost introduction or questions")
|
||||
}
|
||||
if len(story.Places[0].Applications) != 3 {
|
||||
t.Fatal("clue names missing")
|
||||
}
|
||||
for i, application := range story.Places[0].Applications {
|
||||
original := scenario.Places[0].Applications[i]
|
||||
if application.Name != original.Name || original.Image == "" || original.FileType == "" {
|
||||
t.Fatal("clue name or original scenario changed")
|
||||
}
|
||||
if format == "offline" && (application.Image != "" || application.FileType != "") {
|
||||
t.Fatal("offline story exposes a clue file")
|
||||
}
|
||||
if format == "online" && application.Image != original.Image {
|
||||
t.Fatal("online story lost a clue file")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user