Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions backend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,6 @@ tmp/

# OS
.DS_Store

# Serena
.serena
30 changes: 30 additions & 0 deletions backend/controllers/hint_controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package controllers

import (
"net/http"

"github.com/gin-gonic/gin"
"github.com/kc3hack/2026_team10/backend/services"
)

type IHintController interface {
StartGame(ctx *gin.Context)
}
Comment on lines +10 to +12
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

POST /solo のハンドラ名が GetHints になっており、処理内容(ゲーム開始/ラウンド作成)と名前が一致していません。用途が伝わるように StartGame / CreateRound などの名前に揃えることを検討してください。

Copilot uses AI. Check for mistakes.

type HintController struct {
service services.IHintService
}

func NewHintController(service services.IHintService) IHintController {
return &HintController{service: service}
}

func (c *HintController) StartGame(ctx *gin.Context) {
result, err := c.service.StartGame()
if err != nil {
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

エラー発生時に err を一切利用せず固定メッセージだけ返しているため、サーバ側での原因追跡が困難です。少なくともサーバログへ err を出力する(あるいは gin.Context.Error で付与する)など、運用上追える形にしてください。

Suggested change
if err != nil {
if err != nil {
ctx.Error(err)

Copilot uses AI. Check for mistakes.
_ = ctx.Error(err)
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to start game"})
return
}
ctx.JSON(http.StatusOK, gin.H{"result": result})
}
21 changes: 17 additions & 4 deletions backend/main.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
package main

import "github.com/gin-gonic/gin"
import (
"github.com/gin-gonic/gin"
"github.com/kc3hack/2026_team10/backend/controllers"
"github.com/kc3hack/2026_team10/backend/model"
"github.com/kc3hack/2026_team10/backend/repositories"
"github.com/kc3hack/2026_team10/backend/services"
)

func main() {
router := gin.Default()
router.GET("/ping", func(c *gin.Context) {
rounds := []model.Round{}

hintRepository := repositories.NewHintMemoryRepository(rounds)
hintService := services.NewHintService(hintRepository)
hintController := controllers.NewHintController(hintService)

r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
router.Run() // デフォルトで0.0.0.0:8080で待機します
r.POST("/solo", hintController.StartGame)
r.Run() // デフォルトで0.0.0.0:8080で待機します
}
12 changes: 12 additions & 0 deletions backend/model/hint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package model

type Round struct {
ID int
Answer string
Hints []string
}

type StartGameResult struct {
ID int `json:"id"`
Hints []string `json:"hints"`
}
32 changes: 32 additions & 0 deletions backend/repositories/hint_repository.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package repositories

import "github.com/kc3hack/2026_team10/backend/model"

type IHintRepository interface {
CreateRound(answer string, hints []string) (*model.Round, error)
}

type HintMemoryRepository struct {
rounds []model.Round
}

func NewHintMemoryRepository(rounds []model.Round) IHintRepository {
return &HintMemoryRepository{rounds: rounds}
}

func (r *HintMemoryRepository) CreateRound(answer string, hints []string) (*model.Round, error) {
maxID := 0
for _, rd := range r.rounds {
if rd.ID > maxID {
maxID = rd.ID
Comment on lines +17 to +21
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HintMemoryRepository.CreateRound が r.rounds の走査/更新をロック無しで行っています。Gin はリクエストを並列に処理するため、複数の POST /solo が同時に来るとデータレースや slice 破損が起き得ます。mutex 等で CreateRound 全体を保護するか、スレッドセーフなストレージ実装に切り替えてください。

Copilot uses AI. Check for mistakes.
}
}
newID := maxID + 1
round := model.Round{
ID: newID,
Answer: answer,
Hints: hints,
}
r.rounds = append(r.rounds, round)
return &r.rounds[len(r.rounds)-1], nil
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

append 後に slice 要素へのポインタ(&r.rounds[len-1])を返していますが、後続の append で再確保が起きると呼び出し側が保持しているポインタが無効になり得ます。返却用に新しい Round を確保して返すか、ポインタではなく値を返す形にすると安全です。

Suggested change
return &r.rounds[len(r.rounds)-1], nil
retRound := round
return &retRound, nil

Copilot uses AI. Check for mistakes.
}
39 changes: 39 additions & 0 deletions backend/services/hint_service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package services

import (
"fmt"

"github.com/kc3hack/2026_team10/backend/model"
"github.com/kc3hack/2026_team10/backend/repositories"
)

type IHintService interface {
StartGame() (*model.StartGameResult, error)
}

type HintService struct {
repository repositories.IHintRepository
}

func NewHintService(repository repositories.IHintRepository) IHintService {
return &HintService{repository: repository}
}

func (s *HintService) StartGame() (*model.StartGameResult, error) {
// お題、ヒントを作成
answer := "お題"
hints := []string{"ヒント1", "ヒント2", "ヒント3"}

// データを保存
result, err := s.repository.CreateRound(answer, hints)
if err != nil {
return nil, fmt.Errorf("failed to save hint data: %w", err)
}
Comment on lines +28 to +31
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

repository.CreateRound の err を握りつぶして固定文言に置き換えているため、原因追跡が難しくなります。呼び出し元で扱えるように err をラップして返す(%w)など、元のエラー情報を保持してください。

Copilot uses AI. Check for mistakes.

// IDとヒントを返す
response := &model.StartGameResult{
ID: result.ID,
Hints: result.Hints,
}
return response, nil
}