This commit is contained in:
2026-10-11 16:00:18 +07:00
parent 504b49f7cc
commit 030ca56900
77 changed files with 793 additions and 638 deletions
+3 -3
View File
@@ -13,7 +13,7 @@ import (
func (s *server) GetTeamAnswers(ctx context.Context, req *proto.GetTeamAnswersReq) (*proto.GetTeamAnswersRsp, error) {
answers, err := s.answerService.GetTeamAnswers(
ctx,
int(req.ID),
req.ID,
req.Password,
)
if err != nil {
@@ -28,7 +28,7 @@ func (s *server) GetTeamAnswers(ctx context.Context, req *proto.GetTeamAnswersRe
func (s *server) SubmitTeamAnswers(ctx context.Context, req *proto.SubmitTeamAnswersReq) (*proto.SubmitTeamAnswersRsp, error) {
err := s.answerService.SubmitTeamAnswers(
ctx,
int(req.ID),
req.ID,
req.Password,
convertAnswers(req.Answers),
)
@@ -56,7 +56,7 @@ func (s *server) SetTeamAnswerScore(ctx context.Context, req *proto.SetTeamAnswe
err := s.answerService.SetTeamAnswerScore(
ctx,
int(req.ID),
req.ID,
req.QuestionCode,
score,
)
+1 -1
View File
@@ -21,7 +21,7 @@ func (s *server) DeviceHeartbeat(ctx context.Context, req *proto.DeviceHeartbeat
DeviceID: req.DeviceID,
ConnectionID: req.ConnectionID,
OrganizerGameID: deviceOptionalID(req.OrganizerGameID),
TeamID: deviceOptionalID(req.TeamID),
TeamID: req.TeamID,
Password: req.Password,
ScreenID: req.ScreenID,
IP: ip,
+1 -1
View File
@@ -37,7 +37,7 @@ func mapVenueDevices(devices []device_presence_service.Device) []*proto.VenueDev
UserAgent: connection.UserAgent,
Connected: connection.Connected,
GameID: devicePublicID(connection.GameID),
TeamID: devicePublicID(connection.TeamID),
TeamID: &connection.TeamID,
ScreenID: devicePublicID(connection.ScreenID),
Kind: connection.Kind,
})
+9 -8
View File
@@ -3,6 +3,7 @@ package app
import (
"context"
"errors"
"strconv"
"evening_detective_server/internal/services/map_service"
proto "evening_detective_server/proto"
@@ -22,7 +23,7 @@ func (s *server) GetGameMap(ctx context.Context, req *proto.GetGameMapReq) (*pro
if err != nil {
return nil, status.Error(codes.NotFound, "игра не найдена")
}
if err := s.mapService.Ensure(ctx, int(req.GameID), "organizer_desk", 1); err != nil {
if err := s.mapService.Ensure(ctx, int(req.GameID), "organizer_desk", "1"); err != nil {
return nil, status.Error(codes.Internal, "не удалось сохранить карту")
}
for _, team := range game.Teams {
@@ -38,7 +39,7 @@ func (s *server) GetGameMap(ctx context.Context, req *proto.GetGameMapReq) (*pro
return nil, status.Error(codes.Internal, "не удалось получить экраны")
}
for _, screen := range screens {
if err := s.mapService.Ensure(ctx, int(req.GameID), "screen", screen.ID); err != nil {
if err := s.mapService.Ensure(ctx, int(req.GameID), "screen", strconv.Itoa(screen.ID)); err != nil {
return nil, status.Error(codes.Internal, "не удалось сохранить карту")
}
}
@@ -46,16 +47,16 @@ func (s *server) GetGameMap(ctx context.Context, req *proto.GetGameMapReq) (*pro
if err != nil {
return nil, status.Error(codes.Internal, "не удалось получить карту")
}
teamNames := map[int]string{}
teamNames := map[string]string{}
for _, team := range game.Teams {
if team.ParticipationStatus == "cancelled" {
continue
}
teamNames[team.ID] = team.Name
}
screenStates := map[int]*proto.ScreenState{}
screenStates := map[string]*proto.ScreenState{}
for _, screen := range screens {
screenStates[screen.ID] = screenState(screen)
screenStates[strconv.Itoa(screen.ID)] = screenState(screen)
}
result := make([]*proto.MapItem, 0, len(items))
for _, item := range items {
@@ -66,7 +67,7 @@ func (s *server) GetGameMap(ctx context.Context, req *proto.GetGameMapReq) (*pro
}
continue
}
mapped := &proto.MapItem{Kind: item.Kind, ItemID: int32(item.ItemID), X: int32(item.X), Y: int32(item.Y), Hidden: item.Hidden}
mapped := &proto.MapItem{Kind: item.Kind, ItemID: item.ItemID, X: int32(item.X), Y: int32(item.Y), Hidden: item.Hidden}
if item.Kind == "team" {
mapped.Label = teamNames[item.ItemID]
}
@@ -87,13 +88,13 @@ func (s *server) UpdateGameMapItem(ctx context.Context, req *proto.UpdateGameMap
if !canManageScreens(ctx) {
return nil, status.Error(codes.PermissionDenied, "permission denied")
}
if req == nil || req.GameID <= 0 || req.ItemID <= 0 || (req.Kind != "team" && req.Kind != "screen" && req.Kind != "organizer_desk") {
if req == nil || req.GameID <= 0 || req.ItemID == "" || (req.Kind != "team" && req.Kind != "screen" && req.Kind != "organizer_desk") {
return nil, status.Error(codes.InvalidArgument, "некорректный объект карты")
}
if err := s.mapService.Update(ctx, &map_service.MapItem{
GameID: int(req.GameID),
Kind: req.Kind,
ItemID: int(req.ItemID),
ItemID: req.ItemID,
X: int(req.X),
Y: int(req.Y),
Hidden: req.Hidden,
+2 -2
View File
@@ -15,7 +15,7 @@ func mapGameReview(r *game_review_service.Review) *proto.GameReview {
return &proto.GameReview{
ID: int32(r.ID),
GameID: int32(r.GameID),
TeamID: int32(r.TeamID),
TeamID: r.TeamID,
TeamName: r.TeamName,
Rating: r.Rating,
Difficulty: r.Difficulty,
@@ -35,7 +35,7 @@ func mapGameReviews(reviews []*game_review_service.Review) []*proto.GameReview {
}
func (s *server) CreateGameReview(ctx context.Context, req *proto.CreateGameReviewReq) (*proto.CreateGameReviewRsp, error) {
review, err := s.reviewService.Create(ctx, int(req.GameID), int(req.TeamID), req.Password, req.Rating, req.Difficulty, req.Text)
review, err := s.reviewService.Create(ctx, int(req.GameID), req.TeamID, req.Password, req.Rating, req.Difficulty, req.Text)
if err != nil {
return nil, reviewErrorStatus(err, "не удалось создать отзыв")
}
+2 -2
View File
@@ -12,7 +12,7 @@ func TestMapTeamResults(t *testing.T) {
results := []answer_service.TeamResult{
{
Team: &game_model.Team{
ID: 1,
ID: "019a1234-5678-7abc-8def-000000000001",
Name: "Команда А",
Status: "play",
ActionsCount: 7,
@@ -30,7 +30,7 @@ func TestMapTeamResults(t *testing.T) {
t.Fatalf("len(mapTeamResults) = %d, want 1", len(got))
}
row := got[0]
if row.Team == nil || row.Team.ID != 1 || row.Team.Name != "Команда А" {
if row.Team == nil || row.Team.ID != "019a1234-5678-7abc-8def-000000000001" || row.Team.Name != "Команда А" {
t.Fatalf("row.Team = %+v, want id 1, name Команда А", row.Team)
}
if row.ActionsCount != 7 {
+1 -1
View File
@@ -9,7 +9,7 @@ func mapTeam(
o *game_model.Team,
) *proto.Team {
return &proto.Team{
ID: int32(o.ID),
ID: o.ID,
Name: o.Name,
Status: o.Status,
Password: o.Password,
+3 -3
View File
@@ -14,7 +14,7 @@ import (
"time"
)
func TeamRegistrationHandler(token string, register func(context.Context, int, string, team_service.Registration) (int, error)) http.Handler {
func TeamRegistrationHandler(token string, register func(context.Context, int, string, team_service.Registration) (string, error)) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Cache-Control", "no-store")
@@ -68,9 +68,9 @@ func TeamRegistrationHandler(token string, register func(context.Context, int, s
fail(http.StatusInternalServerError, "Не удалось зарегистрировать команду")
default:
if isRPC {
_ = json.NewEncoder(w).Encode(map[string]any{"jsonrpc": "2.0", "result": map[string]int{"id": id}, "id": rpcID})
_ = json.NewEncoder(w).Encode(map[string]any{"jsonrpc": "2.0", "result": map[string]string{"id": id}, "id": rpcID})
} else {
_ = json.NewEncoder(w).Encode(map[string]int{"id": id})
_ = json.NewEncoder(w).Encode(map[string]string{"id": id})
}
}
})
+4 -4
View File
@@ -38,7 +38,7 @@ func TestTeamRegistrationHandler(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
called := false
mux := http.NewServeMux()
mux.Handle("POST /api/games/{id}/registrations", TeamRegistrationHandler(tc.token, func(ctx context.Context, gameID int, deliveryID string, registration team_service.Registration) (int, error) {
mux.Handle("POST /api/games/{id}/registrations", TeamRegistrationHandler(tc.token, func(ctx context.Context, gameID int, deliveryID string, registration team_service.Registration) (string, error) {
called = true
if gameID != 42 || deliveryID != "delivery" || registration.Name != "Команда" || registration.Email != "captain@example.org" || registration.ParticipantsCount != 5 {
t.Fatal("incorrect registration passed to service")
@@ -46,7 +46,7 @@ func TestTeamRegistrationHandler(t *testing.T) {
if _, ok := ctx.Deadline(); !ok {
t.Fatal("missing deadline")
}
return 7, tc.serviceErr
return "019a1234-5678-7abc-8def-000000000007", tc.serviceErr
}))
req := httptest.NewRequest(http.MethodPost, "/api/games/"+tc.gameID+"/registrations", strings.NewReader(tc.body))
req.Header.Set("Authorization", tc.auth)
@@ -56,7 +56,7 @@ func TestTeamRegistrationHandler(t *testing.T) {
if res.Code != tc.want || called != tc.called {
t.Fatalf("status=%d called=%v body=%s", res.Code, called, res.Body.String())
}
if tc.name == "success" && res.Body.String() != "{\"id\":7}\n" {
if tc.name == "success" && res.Body.String() != "{\"id\":\"019a1234-5678-7abc-8def-000000000007\"}\n" {
t.Fatal(res.Body.String())
}
if strings.Contains(res.Body.String(), "private database detail") {
@@ -85,7 +85,7 @@ func TestTeamRegistrationHandler(t *testing.T) {
}
func TestCaptainContactOnlyInGameDetails(t *testing.T) {
team := &game_model.Team{ID: 1, CaptainEmail: "captain@example.org", ParticipantsCount: 5}
team := &game_model.Team{ID: "019a1234-5678-7abc-8def-000000000001", CaptainEmail: "captain@example.org", ParticipantsCount: 5}
details := mapGame(&game_model.Game{Teams: []*game_model.Team{team}})
if details.Teams[0].CaptainEmail != team.CaptainEmail || details.Teams[0].ParticipantsCount != 5 {
t.Fatal("registration details missing from organizer view")
+7 -7
View File
@@ -34,7 +34,7 @@ func (s *server) AddTeam(ctx context.Context, req *proto.AddTeamReq) (*proto.Add
}
return &proto.AddTeamRsp{
ID: int32(team.ID),
ID: team.ID,
Password: team.Password,
}, nil
}
@@ -50,7 +50,7 @@ func (s *server) UpdateTeam(ctx context.Context, req *proto.UpdateTeamReq) (*pro
err := s.teamService.UpdateTeam(
ctx,
int(req.ID),
req.ID,
req.Name,
)
if err != nil {
@@ -71,7 +71,7 @@ func (s *server) DeleteTeam(ctx context.Context, req *proto.DeleteTeamReq) (*pro
err := s.teamService.DeleteTeam(
ctx,
int(req.ID),
req.ID,
)
if err != nil {
return nil, teamErrorStatus(err, "не удалось удалить команду")
@@ -104,7 +104,7 @@ func (s *server) GiveTeamApplications(ctx context.Context, req *proto.GiveTeamAp
err := s.gameplayService.GiveTeamApplications(
ctx,
int(req.ID),
req.ID,
req.Name,
)
if err != nil {
@@ -117,7 +117,7 @@ func (s *server) GiveTeamApplications(ctx context.Context, req *proto.GiveTeamAp
func (s *server) GetTeamStory(ctx context.Context, req *proto.GetTeamStoryReq) (*proto.GetTeamStoryRsp, error) {
story, game, actions, err := s.gameplayService.GetTeamActions(
ctx,
int(req.ID),
req.ID,
req.Password,
)
if err != nil {
@@ -138,7 +138,7 @@ func (s *server) GetTeamStory(ctx context.Context, req *proto.GetTeamStoryReq) (
func (s *server) AddTeamAction(ctx context.Context, req *proto.AddTeamActionReq) (*proto.AddTeamActionRsp, error) {
err := s.gameplayService.AddTeamAction(
ctx,
int(req.ID),
req.ID,
req.Password,
req.Code,
false,
@@ -161,7 +161,7 @@ func (s *server) DeleteLastTeamAction(ctx context.Context, req *proto.DeleteLast
err := s.gameplayService.DeleteLastTeamAction(
ctx,
int(req.ID),
req.ID,
)
if err != nil {
return nil, gameplayErrorStatus(err, "не удалось удалить последнее действие команды")