Добавить серверную логику таймера экранов

This commit is contained in:
2026-09-21 18:17:15 +07:00
parent 458bf320d4
commit 002c4b26b4
4 changed files with 181 additions and 24 deletions
+54 -10
View File
@@ -7,6 +7,7 @@ import (
"errors"
"fmt"
"strconv"
"strings"
"time"
"evening_detective_server/internal/modules/processor_jwt"
@@ -153,15 +154,29 @@ func hashScreenToken(token string) string {
}
func screenState(session *screen_sessions_repo.ScreenSession) *proto.ScreenState {
timerState := proto.ScreenTimerState(session.TimerState)
timerRemaining := session.TimerRemainingSeconds
if timerState == proto.ScreenTimerState_SCREEN_TIMER_STATE_RUNNING {
if session.TimerEndsAt == nil || !session.TimerEndsAt.After(time.Now()) {
timerRemaining = 0
timerState = proto.ScreenTimerState_SCREEN_TIMER_STATE_FINISHED
} else {
timerRemaining = int64(time.Until(*session.TimerEndsAt) / time.Second)
}
}
state := &proto.ScreenState{
Id: fmt.Sprint(session.ID),
Status: "disconnected",
SoundEnabled: session.Sound,
Mode: proto.ScreenMode(session.Mode),
StateVersion: session.Version,
PositionMs: session.Position,
Command: proto.ScreenCommand(session.Command),
Volume: session.Volume,
Id: fmt.Sprint(session.ID),
Status: "disconnected",
SoundEnabled: session.Sound,
Mode: proto.ScreenMode(session.Mode),
StateVersion: session.Version,
PositionMs: session.Position,
Command: proto.ScreenCommand(session.Command),
Volume: session.Volume,
TimerLabel: session.TimerLabel,
TimerDurationSeconds: session.TimerDurationSeconds,
TimerRemainingSeconds: timerRemaining,
TimerState: timerState,
}
if time.Since(session.LastSeen) <= 5*time.Second {
state.Status = "connected"
@@ -218,8 +233,27 @@ func (s *server) SetScreenMode(ctx context.Context, req *proto.SetScreenModeReq)
return &proto.SetScreenModeRsp{}, nil
}
func (s *server) SetScreenTimer(context.Context, *proto.SetScreenTimerReq) (*proto.SetScreenTimerRsp, error) {
return nil, status.Error(codes.Unimplemented, "таймер экранов ещё не реализован")
func (s *server) SetScreenTimer(ctx context.Context, req *proto.SetScreenTimerReq) (*proto.SetScreenTimerRsp, error) {
if !canManageScreens(ctx) {
return nil, status.Error(codes.PermissionDenied, "permission denied")
}
if req == nil || req.GameId <= 0 || req.DurationSeconds <= 0 || req.DurationSeconds > 24*60*60 {
return nil, status.Error(codes.InvalidArgument, "некорректные параметры таймера")
}
label := strings.TrimSpace(req.Label)
if label == "" {
label = "Перерыв"
}
if len(label) > 200 {
return nil, status.Error(codes.InvalidArgument, "слишком длинная надпись таймера")
}
if _, err := s.gameService.GetGame(ctx, int(req.GameId)); err != nil {
return nil, status.Error(codes.NotFound, "игра не найдена")
}
if err := s.screenRepo.SetTimer(ctx, int(req.GameId), req.DurationSeconds, label); err != nil {
return nil, status.Error(codes.Internal, "не удалось настроить таймер экранов")
}
return &proto.SetScreenTimerRsp{}, nil
}
func (s *server) SendScreenCommand(ctx context.Context, req *proto.SendScreenCommandReq) (*proto.SendScreenCommandRsp, error) {
@@ -232,6 +266,12 @@ func (s *server) SendScreenCommand(ctx context.Context, req *proto.SendScreenCom
if _, err := s.gameService.GetGame(ctx, int(req.GameId)); err != nil {
return nil, status.Error(codes.NotFound, "игра не найдена")
}
if isTimerCommand(req.Command) {
if err := s.screenRepo.SetTimerCommand(ctx, int(req.GameId), int32(req.Command)); err != nil {
return nil, status.Error(codes.Internal, "не удалось выполнить команду таймера")
}
return &proto.SendScreenCommandRsp{}, nil
}
if req.PositionMs < 0 {
return nil, status.Error(codes.InvalidArgument, "некорректная позиция")
}
@@ -244,6 +284,10 @@ func (s *server) SendScreenCommand(ctx context.Context, req *proto.SendScreenCom
return &proto.SendScreenCommandRsp{}, nil
}
func isTimerCommand(command proto.ScreenCommand) bool {
return command >= proto.ScreenCommand_SCREEN_COMMAND_TIMER_START && command <= proto.ScreenCommand_SCREEN_COMMAND_TIMER_RESET
}
func (s *server) GetScreenResults(ctx context.Context, req *proto.GetScreenResultsReq) (*proto.GetScreenResultsRsp, error) {
if req == nil || req.ScreenId == "" || req.AccessToken == "" {
return nil, status.Error(codes.InvalidArgument, "некорректные данные экрана")