Skip to content

Instantly share code, notes, and snippets.

@neetsdkasu
Created April 14, 2019 21:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save neetsdkasu/c20491f568030481a817969059ee0e05 to your computer and use it in GitHub Desktop.
Save neetsdkasu/c20491f568030481a817969059ee0e05 to your computer and use it in GitHub Desktop.
Calculate Rating for Some Old Topcoder Marathon Match
package main
// author: Leonardone
// Marathon Match Rating Calculation
// community.topcoder.com/longcontest/?module=Static&d1=support&d2=ratings
import (
"fmt"
. "gitlab.com/neetsdkasu/tcutils/tcdatafeed"
"math"
"os"
"strings"
)
var rdList = map[string]int64{
"mm102": 17264,
"mm103": 17309,
"mm105": 17377,
"tco18final": 17338,
}
func calcRatings(coders []*Result) {
if len(coders) < 2 {
return
}
numCoders := float64(len(coders))
aveRating := 0.0
for _, coder := range coders {
aveRating += float64(coder.OldRating)
}
aveRating /= numCoders
cf := 0.0
{
cf1 := 0.0
cf2 := 0.0
for _, coder := range coders {
cf1 += math.Pow(float64(coder.OldVolatility), 2.0)
cf2 += math.Pow(float64(coder.OldRating)-aveRating, 2.0)
}
cf1 /= numCoders
cf2 /= numCoders - 1.0
cf = math.Sqrt(cf1 + cf2)
}
eRanks := make([]float64, len(coders))
ePerfs := make([]float64, len(coders))
for i, coder1 := range coders {
wp := 0.5
for _, coder2 := range coders {
tmp1 := float64(coder2.OldRating - coder1.OldRating)
v1 := math.Pow(float64(coder1.OldVolatility), 2.0)
v2 := math.Pow(float64(coder2.OldVolatility), 2.0)
tmp2 := math.Sqrt(2.0 * (v1 + v2))
wp += 0.5 * (math.Erf(tmp1/tmp2) + 1.0)
}
eRanks[i] = wp
ePerfs[i] = -stdNorminv((eRanks[i] - 0.5) / numCoders)
}
aRanks := make([]float64, len(coders))
aPerfs := make([]float64, len(coders))
{
rankSums := make([]int, coders[len(coders)-1].Placed+1)
rankCounts := make([]int, len(rankSums))
for i, coder := range coders {
rankSums[coder.Placed] += i + 1
rankCounts[coder.Placed]++
}
for i, coder := range coders {
sum := float64(rankSums[coder.Placed])
count := float64(rankCounts[coder.Placed])
aRanks[i] = sum / count
aPerfs[i] = -stdNorminv((aRanks[i] - 0.5) / numCoders)
}
}
newRatings := make([]float64, len(coders))
newVolatilities := make([]float64, len(coders))
for i, coder := range coders {
perfAs := float64(coder.OldRating) + cf*(aPerfs[i]-ePerfs[i])
weight := 1.0/(1.0-(0.42/float64(coder.NumRatings)+0.18)) - 1.0
if coder.OldRating > 2500 {
weight *= 0.8
} else if coder.OldRating >= 2000 {
weight *= 0.9
}
Cap := 150.0 + 1500.0/float64(coder.NumRatings+1)
newRatings[i] = math.Max(
float64(coder.OldRating)-Cap,
math.Min(
float64(coder.OldRating)+Cap,
(float64(coder.OldRating)+weight*perfAs)/(1.0+weight),
))
if coder.Placed == 1 && newRatings[i] <= float64(coder.OldRating) {
newRatings[i] = float64(coder.OldRating + 1)
}
newVolatilities[i] = math.Sqrt(
math.Pow(newRatings[i]-float64(coder.OldRating), 2.0)/weight +
math.Pow(float64(coder.OldVolatility), 2.0)/(weight+1.0))
}
fmt.Println(fmt.Sprintf(
"%-3s %-20s %-4s %-4s %-4s %-4s %-5s %-5s %-7s %-6s",
"Pos", "Handle",
"OldR", "OldV",
"NewR", "NewV",
"ARank", "ERank",
"Rating", "Vol",
))
for i, coder := range coders {
fmt.Println(fmt.Sprintf(
"%3d %-20s %4d %4d %4d %4d %5.1f %5.1f %7.2f %6.2f",
coder.Placed, coder.Handle,
coder.OldRating, coder.OldVolatility,
coder.NewRating, coder.NewVolatility,
aRanks[i], eRanks[i],
newRatings[i], newVolatilities[i],
))
}
}
func stdNorminv(p float64) float64 {
return math.Sqrt2 * math.Erfinv(2.0*p-1.0)
}
func main() {
if len(os.Args) != 2 {
showUsage()
return
}
name := strings.ToLower(os.Args[1])
rd, ok := rdList[name]
if !ok {
fmt.Println("invalid arg:", os.Args[1])
showUsage()
return
}
round, err := GetRoundResults(rd)
if err != nil {
fmt.Println("## ERROR ##")
fmt.Println(err.Error())
os.Exit(1)
return
}
coders := []*Result{}
for _, res := range round.Results {
if res.OldRating > 0 {
coders = append(coders, res)
}
}
calcRatings(coders)
}
func showUsage() {
req := []interface{}{" arg:"}
for k := range rdList {
req = append(req, k)
}
fmt.Println("usage:", os.Args[0], "<arg>")
fmt.Println(req...)
}
Pos Handle OldR OldV NewR NewV ARank ERank Rating Vol
1 wleite 2862 307 2891 291 1.0 1.6 2891.31 291.09
2 H_a_s_h 2189 354 2264 358 2.0 6.2 2262.87 358.53
3 hakomo 2638 503 2643 460 3.0 3.3 2643.05 460.63
4 yowa 2061 264 2100 255 4.0 7.2 2100.04 255.38
5 my316g 1599 268 1727 339 5.0 17.2 1718.95 336.18
6 alpha_virginis 1262 431 1430 509 6.0 26.2 1427.44 508.80
7 sumoru 1718 258 1785 266 7.0 14.0 1783.93 265.78
8 Rustyoldman 1466 227 1566 291 8.0 21.0 1566.06 290.81
9 tashikani 1362 356 1478 393 9.0 23.9 1475.52 392.92
10 ebicochineal 1690 224 1730 214 10.0 14.5 1728.50 214.43
11 EvbCFfp1XB 2093 283 2057 270 11.0 6.8 2056.77 269.92
12 windhunterSB 1772 353 1784 316 12.0 13.4 1783.74 316.61
13 Kriii 1765 557 1784 489 13.0 15.0 1782.48 493.61
14 eris_c 1616 164 1635 149 14.0 16.3 1634.77 149.66
15 bigeye 1330 245 1425 263 15.0 25.0 1424.77 263.09
16 okazaki 1856 277 1817 262 16.0 11.0 1817.42 261.87
17 kruntuid 1319 307 1377 298 17.0 25.1 1375.80 298.11
18 kosakkun 1862 382 1812 355 18.0 11.7 1813.37 355.24
19 BCSEiny 1393 198 1422 187 19.0 23.2 1421.89 187.18
20 tanzaku 1424 412 1439 372 20.0 22.2 1438.56 372.61
21 gasin 1335 394 1366 345 21.0 24.5 1362.74 350.25
22 shamal 1867 281 1774 305 22.0 10.8 1775.08 304.68
23 iwashi31 1728 230 1660 247 23.0 13.6 1660.60 247.26
25 fluffyowl 1225 328 1255 292 24.0 27.5 1252.87 294.78
26 tobari 1254 385 1276 302 25.0 26.5 1267.87 334.28
27 neetsdkasu 1342 215 1333 193 26.0 24.7 1333.23 193.79
28 tamas.kenez 1732 380 1640 384 27.0 14.5 1640.14 384.22
29 kishore_g84 1358 206 1333 193 28.0 24.3 1333.07 193.20
30 Pag2 1207 453 1195 409 29.0 27.3 1195.35 409.05
31 michalkowalski 979 454 1005 386 30.0 32.2 1004.60 386.03
32 pkhomchuk 1066 277 1073 243 31.0 31.8 1073.30 243.96
33 AmAtUrECoDeR 1234 318 1182 281 32.0 27.4 1193.59 290.51
34 PikokoLoko 769 360 811 326 33.0 36.7 810.93 325.92
35 vi002 1487 192 1378 272 34.0 20.3 1380.05 271.57
36 fal_rnd 1237 286 1163 284 35.0 27.4 1165.15 284.38
37 r2d1 586 353 626 326 36.0 39.1 625.84 325.86
38 LLI_E_P_JI_O_K 1392 218 1264 308 37.0 23.2 1263.78 307.56
39 banboooo044 973 454 878 399 38.0 32.3 877.87 399.23
41 mcw1142 1112 168 1035 220 39.0 31.4 1035.48 219.53
42 qiriskiz 799 259 750 245 40.0 37.0 749.66 245.32
44 id 310 272 330 249 41.0 41.8 329.77 248.85
45 cwilkes 791 281 676 341 42.5 37.0 676.42 341.17
45 onigiri 1021 672 814 704 42.5 29.8 821.52 704.02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment