@@ -15,13 +15,17 @@ import (
1515 "google.golang.org/genai"
1616)
1717
18- const MinRoundAnswerRevealDuration = 90 * time .Second
18+ const (
19+ MinRoundAnswerRevealDuration = 90 * time .Second
20+ RecentAnswersLimit = 30
21+ )
1922
2023var (
21- ErrRoundNotFound = errors .New ("round not found" )
22- ErrRoundNotFinished = errors .New ("round is not finished yet" )
23- ErrRoundTooEarly = errors .New ("game has not been played long enough" )
24- ErrBookmarkNotFound = errors .New ("bookmark not found" )
24+ ErrRoundNotFound = errors .New ("round not found" )
25+ ErrRoundNotFinished = errors .New ("round is not finished yet" )
26+ ErrRoundTooEarly = errors .New ("game has not been played long enough" )
27+ ErrBookmarkNotFound = errors .New ("bookmark not found" )
28+ ErrNoAnswersAvailable = errors .New ("no answers available" )
2529)
2630
2731type IHintService interface {
@@ -53,7 +57,23 @@ func (s *HintService) StartGame() (*dto.StartGameResult, error) {
5357 return nil , fmt .Errorf ("failed to create Gemini client: %w" , err )
5458 }
5559
56- const prompt = `
60+ // 過去の出題済みお題を取得(直近30件)
61+ pastAnswers , err := s .repository .GetRecentAnswers (RecentAnswersLimit )
62+ if err != nil {
63+ return nil , fmt .Errorf ("failed to get recent answers: %w" , err )
64+ }
65+
66+ excludeSection := ""
67+ if len (pastAnswers ) > 0 {
68+ excludeSection = fmt .Sprintf (`
69+
70+ # 禁止お題
71+ 以下のお題は過去に出題済みなので、絶対に使わないでください:
72+ %s
73+ ` , strings .Join (pastAnswers , "、" ))
74+ }
75+
76+ const basePrompt = `
5777 # Role
5878 あなたは京都(上品・皮肉)と大阪(効率・本音)の個性を完璧に描き分ける脚本家であり、厳密なJSONデータを出力するシステムです。
5979
@@ -169,10 +189,12 @@ func (s *HintService) StartGame() (*dto.StartGameResult, error) {
169189 },
170190 }
171191
192+ fullPrompt := basePrompt + excludeSection
193+
172194 res , err := client .Models .GenerateContent (
173195 ctx ,
174196 "gemini-2.5-flash" ,
175- genai .Text (prompt ),
197+ genai .Text (fullPrompt ),
176198 config ,
177199 )
178200 if err != nil {
@@ -186,8 +208,6 @@ func (s *HintService) StartGame() (*dto.StartGameResult, error) {
186208
187209 text := res .Text ()
188210
189- fmt .Println (text )
190-
191211 if err := json .Unmarshal ([]byte (text ), & geminiData ); err != nil {
192212 return nil , fmt .Errorf ("JSONパースに失敗しました: %w (raw: %s)" , err , text )
193213 }
@@ -221,6 +241,9 @@ func (s *HintService) GetAnswer(id uint) (string, error) {
221241 if err != nil {
222242 return "" , err
223243 }
244+ if len (round .Answers ) == 0 {
245+ return "" , fmt .Errorf ("%w: id=%d" , ErrNoAnswersAvailable , id )
246+ }
224247 if ! round .IsFinished {
225248 if time .Since (round .CreatedAt ) < MinRoundAnswerRevealDuration {
226249 return "" , fmt .Errorf ("%w" , ErrRoundTooEarly )
@@ -257,6 +280,9 @@ func (s *HintService) GetFinishedRoundByID(id uint) (*dto.RoundResponse, error)
257280 if ! round .IsFinished {
258281 return nil , fmt .Errorf ("%w: id=%d" , ErrRoundNotFinished , id )
259282 }
283+ if len (round .Answers ) == 0 {
284+ return nil , fmt .Errorf ("%w: id=%d" , ErrNoAnswersAvailable , id )
285+ }
260286 result := & dto.RoundResponse {
261287 ID : round .ID ,
262288 Answer : round .Answers [0 ],
@@ -274,6 +300,9 @@ func (s *HintService) BookmarkRound(id uint) (*dto.RoundResponse, error) {
274300 if ! round .IsFinished {
275301 return nil , fmt .Errorf ("%w: id=%d" , ErrRoundNotFinished , id )
276302 }
303+ if len (round .Answers ) == 0 {
304+ return nil , fmt .Errorf ("%w: id=%d" , ErrNoAnswersAvailable , id )
305+ }
277306 if err := s .repository .BookmarkRound (id ); err != nil {
278307 return nil , fmt .Errorf ("failed to bookmark round: %w" , err )
279308 }
@@ -295,6 +324,9 @@ func (s *HintService) GetRandomBookmark() (*dto.RoundResponse, error) {
295324 return nil , ErrBookmarkNotFound
296325 }
297326
327+ if len (round .Answers ) == 0 {
328+ return nil , ErrNoAnswersAvailable
329+ }
298330 return & dto.RoundResponse {
299331 ID : round .ID ,
300332 Answer : round .Answers [0 ],
@@ -312,6 +344,9 @@ func (s *HintService) GetBookmarkedList() ([]dto.RoundResponse, error) {
312344 response := []dto.RoundResponse {}
313345
314346 for _ , r := range rounds {
347+ if len (r .Answers ) == 0 {
348+ continue
349+ }
315350 limit := 4
316351 if len (r .Hints ) < limit {
317352 limit = len (r .Hints )
0 commit comments