Feat: turn timer
This commit is contained in:
		| @@ -25,6 +25,7 @@ | |||||||
|   <hr /> |   <hr /> | ||||||
|   {{if .Room.IsRunning}} |   {{if .Room.IsRunning}} | ||||||
|     <p>Turn of the <span class="text-{{.Room.TeamTurn}}-500">{{.Room.TeamTurn}}</span> team</p> |     <p>Turn of the <span class="text-{{.Room.TeamTurn}}-500">{{.Room.TeamTurn}}</span> team</p> | ||||||
|  | {{template "turntimer" .Room}} | ||||||
|     {{if .Room.MimeDone}} |     {{if .Room.MimeDone}} | ||||||
|     <p class="text-{{.Room.TeamTurn}}-500 text-xl">Waiting for guessers</p> |     <p class="text-{{.Room.TeamTurn}}-500 text-xl">Waiting for guessers</p> | ||||||
|     <p class="text-{{.Room.TeamTurn}}-500 text-xl">Given Clue: "{{.Room.FetchLastClueWord}}"</p> |     <p class="text-{{.Room.TeamTurn}}-500 text-xl">Given Clue: "{{.Room.FetchLastClueWord}}"</p> | ||||||
|   | |||||||
							
								
								
									
										5
									
								
								components/turntimer.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								components/turntimer.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | {{define "turntimer"}} | ||||||
|  | <div> | ||||||
|  |   Timer: <span sse-swap="turntimer_{{.ID}}">{{.Settings.TurnSecondsLeft}}</span> | ||||||
|  | </div> | ||||||
|  | {{end}} | ||||||
| @@ -84,8 +84,8 @@ func saveFullInfo(fi *models.FullInfo) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func notifyBotIfNeeded(fi *models.FullInfo) { | func notifyBotIfNeeded(room *models.Room) { | ||||||
| 	if botName := fi.Room.WhichBotToMove(); botName != "" { | 	if botName := room.WhichBotToMove(); botName != "" { | ||||||
| 		log.Debug("got botname", "name", botName, "channel_len", len(llmapi.SignalChanMap[botName])) | 		log.Debug("got botname", "name", botName, "channel_len", len(llmapi.SignalChanMap[botName])) | ||||||
| 		llmapi.SignalChanMap[botName] <- true | 		llmapi.SignalChanMap[botName] <- true | ||||||
| 		log.Debug("after sending signal", "name", botName) | 		log.Debug("after sending signal", "name", botName) | ||||||
|   | |||||||
| @@ -159,7 +159,7 @@ func HandleShowColor(w http.ResponseWriter, r *http.Request) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	// get mime bot for opp team and notify it | 	// get mime bot for opp team and notify it | ||||||
| 	notifyBotIfNeeded(fi) | 	notifyBotIfNeeded(fi.Room) | ||||||
| 	notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "") | 	notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "") | ||||||
| 	if err := tmpl.ExecuteTemplate(w, "cardword", cardword); err != nil { | 	if err := tmpl.ExecuteTemplate(w, "cardword", cardword); err != nil { | ||||||
| 		log.Error("failed to execute cardword template", "error", err) | 		log.Error("failed to execute cardword template", "error", err) | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ import ( | |||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
|  | 	"time" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func HandleCreateRoom(w http.ResponseWriter, r *http.Request) { | func HandleCreateRoom(w http.ResponseWriter, r *http.Request) { | ||||||
| @@ -122,6 +123,7 @@ func HandleEndTurn(w http.ResponseWriter, r *http.Request) { | |||||||
| 	} | 	} | ||||||
| 	fi.Room.ChangeTurn() | 	fi.Room.ChangeTurn() | ||||||
| 	fi.Room.MimeDone = false | 	fi.Room.MimeDone = false | ||||||
|  | 	StopTurnTimer(fi.Room.ID) | ||||||
| 	if err := saveFullInfo(fi); err != nil { | 	if err := saveFullInfo(fi); err != nil { | ||||||
| 		abortWithError(w, err.Error()) | 		abortWithError(w, err.Error()) | ||||||
| 		return | 		return | ||||||
| @@ -132,7 +134,7 @@ func HandleEndTurn(w http.ResponseWriter, r *http.Request) { | |||||||
| 		abortWithError(w, err.Error()) | 		abortWithError(w, err.Error()) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	notifyBotIfNeeded(fi) | 	notifyBotIfNeeded(fi.Room) | ||||||
| 	notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "") | 	notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "") | ||||||
| 	if err := tmpl.ExecuteTemplate(w, "base", fi); err != nil { | 	if err := tmpl.ExecuteTemplate(w, "base", fi); err != nil { | ||||||
| 		log.Error("failed to execute base template", "error", err) | 		log.Error("failed to execute base template", "error", err) | ||||||
| @@ -181,7 +183,7 @@ func HandleStartGame(w http.ResponseWriter, r *http.Request) { | |||||||
| 		abortWithError(w, err.Error()) | 		abortWithError(w, err.Error()) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	notifyBotIfNeeded(fi) | 	notifyBotIfNeeded(fi.Room) | ||||||
| 	// to update only the room that should be updated | 	// to update only the room that should be updated | ||||||
| 	notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "") | 	notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "") | ||||||
| 	// notify(models.NotifyBacklogPrefix+fi.Room.ID, "game started") | 	// notify(models.NotifyBacklogPrefix+fi.Room.ID, "game started") | ||||||
| @@ -283,9 +285,11 @@ func HandleGiveClue(w http.ResponseWriter, r *http.Request) { | |||||||
| 		fi.Room.ThisTurnLimit = 9 | 		fi.Room.ThisTurnLimit = 9 | ||||||
| 	} | 	} | ||||||
| 	fi.Room.OpenedThisTurn = 0 | 	fi.Room.OpenedThisTurn = 0 | ||||||
|  | 	fi.Room.Settings.TurnSecondsLeft = fi.Room.Settings.RoundTime | ||||||
|  | 	StartTurnTimer(fi.Room.ID, time.Duration(fi.Room.Settings.RoundTime)*time.Second) | ||||||
| 	log.Debug("given clue", "clue", clue, "limit", fi.Room.ThisTurnLimit) | 	log.Debug("given clue", "clue", clue, "limit", fi.Room.ThisTurnLimit) | ||||||
| 	notify(models.NotifyBacklogPrefix+fi.Room.ID, clue+num) | 	notify(models.NotifyBacklogPrefix+fi.Room.ID, clue+num) | ||||||
| 	notifyBotIfNeeded(fi) | 	notifyBotIfNeeded(fi.Room) | ||||||
| 	if err := saveFullInfo(fi); err != nil { | 	if err := saveFullInfo(fi); err != nil { | ||||||
| 		abortWithError(w, err.Error()) | 		abortWithError(w, err.Error()) | ||||||
| 		return | 		return | ||||||
| @@ -298,5 +302,5 @@ func HandleRenotifyBot(w http.ResponseWriter, r *http.Request) { | |||||||
| 		abortWithError(w, err.Error()) | 		abortWithError(w, err.Error()) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	notifyBotIfNeeded(fi) | 	notifyBotIfNeeded(fi.Room) | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										60
									
								
								handlers/timer.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								handlers/timer.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | |||||||
|  | package handlers | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"gralias/models" | ||||||
|  | 	"sync" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	timers = make(map[string]*time.Ticker) | ||||||
|  | 	mu     sync.Mutex | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func StartTurnTimer(roomID string, duration time.Duration) { | ||||||
|  | 	mu.Lock() | ||||||
|  | 	defer mu.Unlock() | ||||||
|  |  | ||||||
|  | 	if _, exists := timers[roomID]; exists { | ||||||
|  | 		return // Timer already running | ||||||
|  | 	} | ||||||
|  | 	ticker := time.NewTicker(1 * time.Second) | ||||||
|  | 	timers[roomID] = ticker | ||||||
|  | 	go func() { | ||||||
|  | 		for range ticker.C { | ||||||
|  | 			room, err := getRoomByID(roomID) | ||||||
|  | 			if err != nil { | ||||||
|  | 				log.Error("failed to get room by id", "error", err) | ||||||
|  | 				StopTurnTimer(roomID) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			if room.Settings.TurnSecondsLeft == 0 { | ||||||
|  | 				log.Info("turn time is over", "room_id", roomID) | ||||||
|  | 				room.ChangeTurn() | ||||||
|  | 				room.MimeDone = false | ||||||
|  | 				if err := saveRoom(room); err != nil { | ||||||
|  | 					log.Error("failed to save room", "error", err) | ||||||
|  | 				} | ||||||
|  | 				notify(models.NotifyRoomUpdatePrefix+room.ID, "") | ||||||
|  | 				notifyBotIfNeeded(room) | ||||||
|  | 				StopTurnTimer(roomID) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			room.Settings.TurnSecondsLeft-- | ||||||
|  | 			if err := saveRoom(room); err != nil { | ||||||
|  | 				log.Error("failed to save room", "error", err) | ||||||
|  | 			} | ||||||
|  | 			notify(models.NotifyRoomUpdatePrefix+room.ID, "") | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func StopTurnTimer(roomID string) { | ||||||
|  | 	mu.Lock() | ||||||
|  | 	defer mu.Unlock() | ||||||
|  |  | ||||||
|  | 	if ticker, exists := timers[roomID]; exists { | ||||||
|  | 		ticker.Stop() | ||||||
|  | 		delete(timers, roomID) | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -325,10 +325,10 @@ type WordCard struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| type GameSettings struct { | type GameSettings struct { | ||||||
| 	Language    string `json:"language" example:"en" form:"language"` | 	Language        string `json:"language" example:"en" form:"language"` | ||||||
| 	RoomPass    string `json:"room_pass"` | 	RoomPass        string `json:"room_pass"` | ||||||
| 	TurnSeconds uint32 | 	TurnSecondsLeft uint32 | ||||||
| 	RoundTime   uint32 | 	RoundTime       uint32 | ||||||
| } | } | ||||||
|  |  | ||||||
| // ===== | // ===== | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Grail Finder
					Grail Finder