// internal/utils/matching.go package utils // CalculateMatchScore calculates match score between two items func CalculateMatchScore(item1, item2 map[string]interface{}) float64 { nameScore := 0.0 descScore := 0.0 // 1. Name Matching (Bobot 50%) if name1, ok1 := item1["name"].(string); ok1 { if name2, ok2 := item2["name"].(string); ok2 { nameScore = CalculateStringSimilarity(name1, name2) * 100 } } // 2. Description/Secret Matching (Bobot 50%) // Cek apakah ada secret_details, jika tidak pakai description text1 := "" if val, ok := item1["secret_details"].(string); ok && val != "" { text1 = val } else if val, ok := item1["description"].(string); ok { text1 = val } text2 := "" if val, ok := item2["secret_details"].(string); ok && val != "" { text2 = val } else if val, ok := item2["description"].(string); ok { text2 = val } if text1 != "" && text2 != "" { descScore = CalculateStringSimilarity(text1, text2) * 100 } // Total Score = Rata-rata dari keduanya totalScore := (nameScore * 0.5) + (descScore * 0.5) return totalScore } // MatchItems matches items based on criteria func MatchItems(lostItem, foundItems []map[string]interface{}, threshold float64) []map[string]interface{} { var matches []map[string]interface{} if len(lostItem) == 0 || len(foundItems) == 0 { return matches } lost := lostItem[0] for _, found := range foundItems { score := CalculateMatchScore(lost, found) if score >= threshold { match := make(map[string]interface{}) match["item"] = found match["score"] = score match["level"] = getMatchLevel(score) matches = append(matches, match) } } return matches } // getMatchLevel returns match level based on score func getMatchLevel(score float64) string { if score >= 70 { return "high" } else if score >= 50 { return "medium" } return "low" }