package utils import ( "InfantrySkillCalculator/models" "encoding/json" "fmt" "io" "log" "math" "net/http" "sort" ) func GetGameMetric(gameTag string) *models.GameMetric { for _, metric := range GameMetrics.GameMetrics { if metric.GameName == gameTag { return &metric } } return nil } func FindWeaponMetric(weaponMetrics []models.WeaponMetric, weaponCategory string) *models.WeaponMetric { for _, metric := range weaponMetrics { if metric.WeaponCategory == weaponCategory { return &metric } } return nil } func CalcPlayerScore(playerName string, gameTag string) float32 { if gameTag != "BF5" && gameTag != "BF2042" { _, _ = fmt.Fprintf(GinWriter, "UNSUPPORTED GAME: "+gameTag+"\n") return -1 } gameMetrics := GetGameMetric(gameTag) if gameMetrics == nil { _, _ = fmt.Fprintf(GinWriter, "No game metrics specified for '"+gameTag+"'\n") return -1 } normalizeFactor := gameMetrics.NormalizeFactor topWeaponCount := gameMetrics.TopWeaponCount c := http.Client{} var reqUri string if gameTag == "BF5" { reqUri = "https://api.gametools.network/bfv/weapons/?raw=false&format_values=false&name=" + playerName + "&platform=pc" } else if gameTag == "BF2042" { reqUri = "https://api.gametools.network/bf2042/stats/?raw=false&format_values=false&name=" + playerName + "&platform=pc" } req, err := http.NewRequest("GET", reqUri, nil) if err != nil { _, _ = fmt.Fprintf(GinWriter, err.Error()+"\n") return -1 } req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36") res, err := c.Do(req) if err != nil { _, _ = fmt.Fprintf(GinWriter, err.Error()+"\n") return -1 } defer func(Body io.ReadCloser) { _ = Body.Close() }(res.Body) if res.StatusCode == 404 { _, _ = fmt.Fprintf(GinWriter, "User '"+playerName+"' does not exist!\n") return -1 } else if res.StatusCode != 200 { log.Fatalf("Status code error: %d %s", res.StatusCode, res.Status) } var data models.TrackerWeaponJSON var body, _ = io.ReadAll(res.Body) if err := json.Unmarshal(body, &data); err != nil { log.Fatalf("Failed to deserialize tracker API response: %s", err) } sort.SliceStable(data.Weapons, func(i, j int) bool { return data.Weapons[i].Kills > data.Weapons[j].Kills }) var top []models.Weapon for _, weapon := range data.Weapons { if len(top) >= topWeaponCount { break } if gameTag == "BF2042" && weapon.Kills < 100 { break } acc := (float64(weapon.ShotsHit) / float64(weapon.ShotsFired)) * 100 kpm := weapon.KPM weaponMetrics := FindWeaponMetric(gameMetrics.WeaponMetrics, weapon.Type) if weaponMetrics == nil { _, _ = fmt.Fprintf(GinWriter, "No weapon metrics specified for '"+gameTag+"', WType '"+weapon.Type+"'\n") continue } accFactor := weaponMetrics.AccuracyFactor kpmFactor := weaponMetrics.KpmFactor acc /= accFactor kpm /= kpmFactor weapon.Accuracy = acc weapon.KPM = kpm top = append(top, weapon) } sumAcc := 0.0 sumKpm := 0.0 for _, w := range top { sumAcc += w.Accuracy sumKpm += w.KPM } accAvg := sumAcc / float64(len(top)) kpmAvg := sumKpm / float64(len(top)) score := math.Round(((accAvg*kpmAvg)/normalizeFactor)*100) / 100 return float32(score) }