Skip to content
Draft
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
22 changes: 17 additions & 5 deletions cmd/mcp/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,14 @@ func (m *MCPServer) AddTools() []server.ServerTool {
"type": "string",
"description": "Filter by monster name (optional, supports partial matches)",
},
"usage_element": map[string]interface{}{
"type": "string",
"description": "Filter by monster's usage element (optional, e.g., 'Fire', 'Water', 'Lightning', 'Ice', 'Dragon')",
},
"weakness_element": map[string]interface{}{
"type": "string",
"description": "Filter by monster's weakness element (optional, e.g., 'Fire', 'Water', 'Lightning', 'Ice', 'Dragon')",
},
"sort": map[string]interface{}{
"type": "string",
"description": "Sort order for the results (optional, 'asc' for ascending, 'desc' for descending, default is 'asc')",
Expand Down Expand Up @@ -252,14 +260,18 @@ func (m *MCPServer) getMonsters(ctx context.Context, args mcp.CallToolRequest) (
}
monsterIDs := args.GetString("monster_ids", "")
name := args.GetString("name", "")
usageElement := args.GetString("usage_element", "")
weaknessElement := args.GetString("weakness_element", "")
sort := args.GetString("sort", "asc")

param := request.RequestParam{
MonsterIds: monsterIDs,
MonsterName: name,
Sort: sort,
Limit: limit,
Offset: (offset - 1) * limit,
MonsterIds: monsterIDs,
MonsterName: name,
UsageElement: usageElement,
WeaknessElement: weaknessElement,
Sort: sort,
Limit: limit,
Offset: (offset - 1) * limit,
}
ctx = context.WithValue(ctx, "param", param)

Expand Down
12 changes: 7 additions & 5 deletions internal/controller/monster/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ type Json struct {
}

type RequestParam struct {
MonsterIds string `form:"MonsterIds" json:"MonsterIds,omitempty"`
MonsterName string `form:"MonsterName" json:"MonsterName,omitempty"`
Limit int `form:"limit" json:"limit,omitempty" validate:"omitempty,min=0"`
Offset int `form:"offset" json:"offset,omitempty" validate:"omitempty,min=0"`
Sort string `form:"sort" json:"sort,omitempty" validate:"omitempty,oneof=asc desc"`
MonsterIds string `form:"MonsterIds" json:"MonsterIds,omitempty"`
MonsterName string `form:"MonsterName" json:"MonsterName,omitempty"`
UsageElement string `form:"UsageElement" json:"UsageElement,omitempty"`
WeaknessElement string `form:"WeaknessElement" json:"WeaknessElement,omitempty"`
Limit int `form:"limit" json:"limit,omitempty" validate:"omitempty,min=0"`
Offset int `form:"offset" json:"offset,omitempty" validate:"omitempty,min=0"`
Sort string `form:"sort" json:"sort,omitempty" validate:"omitempty,oneof=asc desc"`
}

type RequestRankingParam struct {
Expand Down
53 changes: 44 additions & 9 deletions internal/database/mysql/monsterQueryService.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ func (s *monsterQueryService) FetchList(ctx context.Context, id string) ([]*mons
var err error

where_clade := ""
whereArgs := []interface{}{}
sort := ""

if id == "" {
Expand All @@ -116,12 +117,48 @@ func (s *monsterQueryService) FetchList(ctx context.Context, id string) ([]*mons
if p.MonsterIds != "" {
monsterIds = strings.Split(p.MonsterIds, ",")
where_clade = "monster_id IN (?)"
}

if p.MonsterName != "" && p.MonsterIds != "" {
where_clade += " and name LIKE '%" + p.MonsterName + "%' "
} else if p.MonsterName != "" {
where_clade += " name LIKE '%" + p.MonsterName + "%' "
whereArgs = append(whereArgs, monsterIds)
}

if p.MonsterName != "" {
if where_clade != "" {
where_clade += " and name LIKE ?"
} else {
where_clade = "name LIKE ?"
}
whereArgs = append(whereArgs, "%"+p.MonsterName+"%")
}

// Add usage element search
if p.UsageElement != "" {
if where_clade != "" {
where_clade += " and element = ?"
} else {
where_clade = "element = ?"
}
whereArgs = append(whereArgs, p.UsageElement)
}

// Add weakness element search - need to join with Weakness table
if p.WeaknessElement != "" {
weaknessJoin := " EXISTS (SELECT 1 FROM weakness w WHERE w.monster_id = monster.monster_id AND " +
"(w.first_weak_element = ? OR " +
"w.second_weak_element = ? OR " +
"w.fire = ? OR " +
"w.water = ? OR " +
"w.lightning = ? OR " +
"w.ice = ? OR " +
"w.dragon = ?))"

if where_clade != "" {
where_clade += " and " + weaknessJoin
} else {
where_clade = weaknessJoin
}
// Add the same value 7 times for the 7 placeholders
for i := 0; i < 7; i++ {
whereArgs = append(whereArgs, p.WeaknessElement)
}
}

if p.Sort == "1" {
Expand All @@ -132,10 +169,8 @@ func (s *monsterQueryService) FetchList(ctx context.Context, id string) ([]*mons

if id != "" {
result = CtxFromDB(ctx).WithContext(ctx).Model(&monster).Preload("Weakness").Preload("Field").Preload("Tribe").Preload("Product").Preload("Ranking").Preload("BGM").Where("monster_id = ? ", id).Find(&monster)
} else if where_clade != "" && p.MonsterIds != "" {
result = CtxFromDB(ctx).WithContext(ctx).Model(&monster).Preload("Weakness").Preload("Field").Preload("Tribe").Preload("Product").Preload("Ranking").Preload("BGM").Where(where_clade, monsterIds).Limit(limit).Offset(offset).Order(sort).Find(&monster)
} else if where_clade != "" {
result = CtxFromDB(ctx).WithContext(ctx).Model(&monster).Preload("Weakness").Preload("Field").Preload("Tribe").Preload("Product").Preload("Ranking").Preload("BGM").Where(where_clade).Limit(limit).Offset(offset).Order(sort).Find(&monster)
result = CtxFromDB(ctx).WithContext(ctx).Model(&monster).Preload("Weakness").Preload("Field").Preload("Tribe").Preload("Product").Preload("Ranking").Preload("BGM").Where(where_clade, whereArgs...).Limit(limit).Offset(offset).Order(sort).Find(&monster)
} else {
result = CtxFromDB(ctx).WithContext(ctx).Model(&monster).Preload("Weakness").Preload("Field").Preload("Tribe").Preload("Product").Preload("Ranking").Preload("BGM").Limit(limit).Offset(offset).Order(sort).Find(&monster)
}
Expand Down
47 changes: 41 additions & 6 deletions internal/database/mysql/monsterQueryService_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,23 @@ func Test_monsterQueryService_FetchList(t *testing.T) {
bgm3 := music.NewMusic("0000000003", "0000000003", "ティガレックスのテーマ", "https://www.youtube.com/watch?v=3")

// ID順に並んでいるデータを適応
monster1 := &monsters.FetchMonsterListDto{Id: "0000000001", Name: "リオレウス", Description: "空の王者。", Location: []string{"古代樹の森"}, Category: "飛竜種", Title: []string{"MH"}, FirstWeak_Attack: "頭部", SecondWeak_Attack: "翼", FirstWeak_Element: "龍", SecondWeak_Element: "雷", Weakness_attack: weak_A, Weakness_element: weak_E, Ranking: ranking1, BGM: []music.Music{*bgm1}}
monster2 := &monsters.FetchMonsterListDto{Id: "0000000002", Name: "リオレイア", Description: "陸の女王", Location: []string{"古代樹の森"}, Category: "飛竜種", Title: []string{"MH"}, FirstWeak_Attack: "頭部", SecondWeak_Attack: "翼", FirstWeak_Element: "龍", SecondWeak_Element: "雷", Weakness_attack: weak_A, Weakness_element: weak_E, Ranking: ranking2, BGM: []music.Music{*bgm2}}
monster3 := &monsters.FetchMonsterListDto{Id: "0000000003", Name: "ティガレックス", Description: "絶対強者", Location: []string{"古代樹の森"}, Category: "飛竜種", Title: []string{"MH"}, FirstWeak_Attack: "頭部", SecondWeak_Attack: "翼", FirstWeak_Element: "雷", SecondWeak_Element: "水", Weakness_attack: weak_A, Weakness_element: weak_E, Ranking: ranking3, BGM: []music.Music{*bgm3}}
fireElement := "Fire"
waterElement := "Water"
dragonElement := "Dragon"
monster1 := &monsters.FetchMonsterListDto{Id: "0000000001", Name: "リオレウス", Description: "空の王者。", Element: &fireElement, Location: []string{"古代樹の森"}, Category: "飛竜種", Title: []string{"MH"}, FirstWeak_Attack: "頭部", SecondWeak_Attack: "翼", FirstWeak_Element: "龍", SecondWeak_Element: "雷", Weakness_attack: weak_A, Weakness_element: weak_E, Ranking: ranking1, BGM: []music.Music{*bgm1}}
monster2 := &monsters.FetchMonsterListDto{Id: "0000000002", Name: "リオレイア", Description: "陸の女王", Element: &waterElement, Location: []string{"古代樹の森"}, Category: "飛竜種", Title: []string{"MH"}, FirstWeak_Attack: "頭部", SecondWeak_Attack: "翼", FirstWeak_Element: "龍", SecondWeak_Element: "雷", Weakness_attack: weak_A, Weakness_element: weak_E, Ranking: ranking2, BGM: []music.Music{*bgm2}}
monster3 := &monsters.FetchMonsterListDto{Id: "0000000003", Name: "ティガレックス", Description: "絶対強者", Element: &dragonElement, Location: []string{"古代樹の森"}, Category: "飛竜種", Title: []string{"MH"}, FirstWeak_Attack: "頭部", SecondWeak_Attack: "翼", FirstWeak_Element: "雷", SecondWeak_Element: "水", Weakness_attack: weak_A, Weakness_element: weak_E, Ranking: ranking3, BGM: []music.Music{*bgm3}}

param1 := param.RequestParam{MonsterIds: "", MonsterName: "", Limit: 100, Offset: 0, Sort: "1"}
param2 := param.RequestParam{MonsterIds: "0000000001,0000000002", MonsterName: "", Limit: 100, Offset: 0, Sort: "1"}
param3 := param.RequestParam{MonsterIds: "", MonsterName: "リオレウス", Limit: 100, Offset: 0, Sort: "1"}
param4 := param.RequestParam{MonsterIds: "", MonsterName: "", Limit: 100, Offset: 0, Sort: "1"}
param5 := param.RequestParam{MonsterIds: "", MonsterName: "", Limit: 100, Offset: 0, Sort: "2"}
param6 := param.RequestParam{MonsterIds: "0000000001", MonsterName: "リオレウス", Limit: 100, Offset: 0, Sort: "1"}
param7 := param.RequestParam{MonsterIds: "", MonsterName: "", UsageElement: "Fire", Limit: 100, Offset: 0, Sort: "1"}
param8 := param.RequestParam{MonsterIds: "", MonsterName: "", WeaknessElement: "龍", Limit: 100, Offset: 0, Sort: "1"}
param9 := param.RequestParam{MonsterIds: "", MonsterName: "", WeaknessElement: "雷", Limit: 100, Offset: 0, Sort: "1"}
param10 := param.RequestParam{MonsterIds: "", MonsterName: "", UsageElement: "Water", WeaknessElement: "龍", Limit: 100, Offset: 0, Sort: "1"}

type args struct {
id string
Expand Down Expand Up @@ -112,6 +119,30 @@ func Test_monsterQueryService_FetchList(t *testing.T) {
want: []*monsters.FetchMonsterListDto{monster1},
wantErr: false,
},
{
name: "DBからモンスターデータを使用属性(Fire)で検索して取得できる",
args: args{id: "", param: param7},
want: []*monsters.FetchMonsterListDto{monster1},
wantErr: false,
},
{
name: "DBからモンスターデータを弱点属性(龍)で検索して取得できる",
args: args{id: "", param: param8},
want: []*monsters.FetchMonsterListDto{monster2, monster1},
wantErr: false,
},
{
name: "DBからモンスターデータを弱点属性(雷)で検索して取得できる",
args: args{id: "", param: param9},
want: []*monsters.FetchMonsterListDto{monster3, monster2, monster1},
wantErr: false,
},
{
name: "DBからモンスターデータを使用属性(Water)と弱点属性(龍)の組み合わせで検索して取得できる",
args: args{id: "", param: param10},
want: []*monsters.FetchMonsterListDto{monster2},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down Expand Up @@ -139,10 +170,14 @@ func createMonsterData(t *testing.T, ctx context.Context) []*monsters.FetchMonst
weak3 := []*Weakness{
{MonsterId: "0000000003", PartId: "0001", Fire: "45", Water: "45", Lightning: "45", Ice: "45", Dragon: "45", Slashing: "45", Blow: "45", Bullet: "45", FirstWeakAttack: "頭部", SecondWeakAttack: "翼", FirstWeakElement: "雷", SecondWeakElement: "水"},
}
fireElement := "Fire"
waterElement := "Water"
dragonElement := "Dragon"

monster := []Monster{
{MonsterId: "0000000001", Name: "リオレウス", Description: "空の王者。", Field: []*Field{{FieldId: "0001", MonsterId: "0000000001", Name: "古代樹の森", ImageUrl: "images/kodaizyu.png"}}, Tribe: &Tribe{TribeId: "0001", MonsterId: "0000000001", Name_ja: "飛竜種", Name_en: "wibarn", Description: "飛竜種"}, Product: []*Product{{ProductId: "0001", MonsterId: "0000000001", Name: "MH", PublishYear: "2004", TotalSales: "200万本"}}, Weakness: weak1, Ranking: []*Ranking{{MonsterId: "0000000001", Ranking: "1", VoteYear: "2024/3/12"}}},
{MonsterId: "0000000002", Name: "リオレイア", Description: "陸の女王", Field: []*Field{{FieldId: "0001", MonsterId: "0000000002", Name: "古代樹の森", ImageUrl: "images/kodaizyu.png"}}, Tribe: &Tribe{TribeId: "0001", MonsterId: "0000000002", Name_ja: "飛竜種", Name_en: "wibarn", Description: "飛竜種"}, Product: []*Product{{ProductId: "0001", MonsterId: "0000000002", Name: "MH", PublishYear: "2004", TotalSales: "200万本"}}, Weakness: weak2, Ranking: []*Ranking{{MonsterId: "0000000002", Ranking: "2", VoteYear: "2024/3/12"}}},
{MonsterId: "0000000003", Name: "ティガレックス", Description: "絶対強者", Field: []*Field{{FieldId: "0001", MonsterId: "0000000003", Name: "古代樹の森", ImageUrl: "images/kodaizyu.png"}}, Tribe: &Tribe{TribeId: "0001", MonsterId: "0000000003", Name_ja: "飛竜種", Name_en: "wibarn", Description: "飛竜種"}, Product: []*Product{{ProductId: "0001", MonsterId: "0000000003", Name: "MH", PublishYear: "2004", TotalSales: "200万本"}}, Weakness: weak3, Ranking: []*Ranking{{MonsterId: "0000000003", Ranking: "3", VoteYear: "2024/3/12"}}},
{MonsterId: "0000000001", Name: "リオレウス", Description: "空の王者。", Element: &fireElement, Field: []*Field{{FieldId: "0001", MonsterId: "0000000001", Name: "古代樹の森", ImageUrl: "images/kodaizyu.png"}}, Tribe: &Tribe{TribeId: "0001", MonsterId: "0000000001", Name_ja: "飛竜種", Name_en: "wibarn", Description: "飛竜種"}, Product: []*Product{{ProductId: "0001", MonsterId: "0000000001", Name: "MH", PublishYear: "2004", TotalSales: "200万本"}}, Weakness: weak1, Ranking: []*Ranking{{MonsterId: "0000000001", Ranking: "1", VoteYear: "2024/3/12"}}},
{MonsterId: "0000000002", Name: "リオレイア", Description: "陸の女王", Element: &waterElement, Field: []*Field{{FieldId: "0001", MonsterId: "0000000002", Name: "古代樹の森", ImageUrl: "images/kodaizyu.png"}}, Tribe: &Tribe{TribeId: "0001", MonsterId: "0000000002", Name_ja: "飛竜種", Name_en: "wibarn", Description: "飛竜種"}, Product: []*Product{{ProductId: "0001", MonsterId: "0000000002", Name: "MH", PublishYear: "2004", TotalSales: "200万本"}}, Weakness: weak2, Ranking: []*Ranking{{MonsterId: "0000000002", Ranking: "2", VoteYear: "2024/3/12"}}},
{MonsterId: "0000000003", Name: "ティガレックス", Description: "絶対強者", Element: &dragonElement, Field: []*Field{{FieldId: "0001", MonsterId: "0000000003", Name: "古代樹の森", ImageUrl: "images/kodaizyu.png"}}, Tribe: &Tribe{TribeId: "0001", MonsterId: "0000000003", Name_ja: "飛竜種", Name_en: "wibarn", Description: "飛竜種"}, Product: []*Product{{ProductId: "0001", MonsterId: "0000000003", Name: "MH", PublishYear: "2004", TotalSales: "200万本"}}, Weakness: weak3, Ranking: []*Ranking{{MonsterId: "0000000003", Ranking: "3", VoteYear: "2024/3/12"}}},
}

bgms := []Music{
Expand Down