Files
evening_detective_server/internal/app/game_map.go
T
2026-10-11 16:00:18 +07:00

109 lines
4.0 KiB
Go

package app
import (
"context"
"errors"
"strconv"
"evening_detective_server/internal/services/map_service"
proto "evening_detective_server/proto"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func (s *server) GetGameMap(ctx context.Context, req *proto.GetGameMapReq) (*proto.GetGameMapRsp, error) {
if !canManageScreens(ctx) {
return nil, status.Error(codes.PermissionDenied, "permission denied")
}
if req == nil || req.GameID <= 0 {
return nil, status.Error(codes.InvalidArgument, "некорректный идентификатор игры")
}
game, err := s.gameService.GetFullGame(ctx, int(req.GameID))
if err != nil {
return nil, status.Error(codes.NotFound, "игра не найдена")
}
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 {
if team.ParticipationStatus == "cancelled" {
continue
}
if err := s.mapService.Ensure(ctx, int(req.GameID), "team", team.ID); err != nil {
return nil, status.Error(codes.Internal, "не удалось сохранить карту")
}
}
screens, err := s.screenService.ListByGame(ctx, int(req.GameID))
if err != nil {
return nil, status.Error(codes.Internal, "не удалось получить экраны")
}
for _, screen := range screens {
if err := s.mapService.Ensure(ctx, int(req.GameID), "screen", strconv.Itoa(screen.ID)); err != nil {
return nil, status.Error(codes.Internal, "не удалось сохранить карту")
}
}
items, err := s.mapService.List(ctx, int(req.GameID))
if err != nil {
return nil, status.Error(codes.Internal, "не удалось получить карту")
}
teamNames := map[string]string{}
for _, team := range game.Teams {
if team.ParticipationStatus == "cancelled" {
continue
}
teamNames[team.ID] = team.Name
}
screenStates := map[string]*proto.ScreenState{}
for _, screen := range screens {
screenStates[strconv.Itoa(screen.ID)] = screenState(screen)
}
result := make([]*proto.MapItem, 0, len(items))
for _, item := range items {
_, teamExists := teamNames[item.ItemID]
if (item.Kind == "team" && !teamExists) || (item.Kind == "screen" && screenStates[item.ItemID] == nil) {
if err := s.mapService.Delete(ctx, item); err != nil {
return nil, status.Error(codes.Internal, "не удалось обновить карту")
}
continue
}
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]
}
if item.Kind == "organizer_desk" {
mapped.Label = "Стол организаторов"
}
if state := screenStates[item.ItemID]; item.Kind == "screen" && state != nil {
mapped.Label = "Экран " + state.ID
mapped.Status = state.Status
mapped.SoundEnabled = state.SoundEnabled
}
result = append(result, mapped)
}
return &proto.GetGameMapRsp{Items: result}, nil
}
func (s *server) UpdateGameMapItem(ctx context.Context, req *proto.UpdateGameMapItemReq) (*proto.UpdateGameMapItemRsp, error) {
if !canManageScreens(ctx) {
return nil, status.Error(codes.PermissionDenied, "permission denied")
}
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: req.ItemID,
X: int(req.X),
Y: int(req.Y),
Hidden: req.Hidden,
}); err != nil {
if errors.Is(err, map_service.ErrItemNotFound) {
return nil, status.Error(codes.NotFound, "объект карты не найден")
}
return nil, status.Error(codes.Internal, "не удалось изменить карту")
}
return &proto.UpdateGameMapItemRsp{}, nil
}