浏览代码

Finally making some improvements to scoring

Kirk Trombley 5 年之前
父节点
当前提交
510e81cbca
共有 1 个文件被更改,包括 49 次插入15 次删除
  1. 49 15
      server/lib.py

+ 49 - 15
server/lib.py

@@ -32,14 +32,40 @@ def generate_coord(max_retries=100000):
 
 
 mean_earth_radius_km = (6378 + 6357) / 2
-# the farthest you can be from another point on Earth
-antipode_dist_km = math.pi * mean_earth_radius_km
-min_dist_km = 0.15  # if you're within 150m, you get a perfect score
-# if you're more than 1/4 of the Earth away, you get 0
-max_dist_km = antipode_dist_km / 2
-# this has been tuned by hand based on the max dist to get a nice Gaussian
-exp_denom = max_dist_km * max_dist_km / 4
-perfect_score = 5000
+
+# if you're more than 1/4 of the Earth's circumfrence away, you get 0
+max_dist_km = (math.pi * mean_earth_radius_km) / 2 # this is about 10,000 km
+
+# if you're within 1/16 of the Earth's circumfrence away, you get at least 1000 points
+quarter_of_max_km = max_dist_km / 4 # this is about 2,500 km
+
+# https://www.wolframalpha.com/input/?i=sqrt%28%28%28land+mass+of+earth%29+%2F+7%29%29+%2F+pi%29+in+kilometers
+# this is the average "radius" of a continent
+# within this radius, you get at least 2000 points
+avg_continental_rad_km = 1468.0
+
+# somewhat arbitrarily, if you're within 1000 km, you get at least 3000 points
+one_thousand = 1000.0
+
+# https://www.wolframalpha.com/input/?i=sqrt%28%28%28land+mass+of+earth%29+%2F+%28number+of+countries+on+earth%29%29+%2F+pi%29+in+kilometers
+# this is the average "radius" of a country
+# within this radius, you get at least 4000 points
+avg_country_rad_km = 479.7
+
+# if you're within 150m, you get a perfect score of 5000
+min_dist_km = 0.15  
+
+
+def score_within(raw_dist, min_dist, max_dist):
+    """
+    Gives a score between 0 and 1000, with 1000 for the min_dist and 0 for the max_dist
+    """
+    # scale the distance down to [0.0, 1.0], then multiply it by 2 for easing
+    pd2 = 2 * (raw_dist - min_dist) / (max_dist - min_dist)
+    # perform a quadratic ease-in-out on pd2
+    r = (pd2 ** 2) / 2 if pd2 < 1 else 1 - (((2 - pd2) ** 2) / 2)
+    # use this to ease between 1000 and 0
+    return int(1000 * (1 - r))
 
 
 def score(target, guess):
@@ -51,12 +77,20 @@ def score(target, guess):
     Returns (score, distance in km)
     """
     dist_km = haversine.haversine(target, guess)
-    if dist_km <= min_dist_km:
-        return perfect_score, dist_km
 
-    if dist_km >= max_dist_km:
-        return 0, dist_km
+    if dist_km <= min_dist_km:
+        point_score = 5000
+    elif dist_km <= avg_country_rad_km:
+        point_score = 4000 + score_within(dist_km, min_dist_km, avg_country_rad_km)
+    elif dist_km <= one_thousand:
+        point_score = 3000 + score_within(dist_km, avg_country_rad_km, one_thousand)
+    elif dist_km <= avg_continental_rad_km:
+        point_score = 2000 + score_within(dist_km, one_thousand, avg_continental_rad_km)
+    elif dist_km <= quarter_of_max_km:
+        point_score = 1000 + score_within(dist_km, avg_continental_rad_km, quarter_of_max_km)
+    elif dist_km <= max_dist_km:
+        point_score = score_within(dist_km, quarter_of_max_km, max_dist_km)
+    else: # dist_km > max_dist_km
+        point_score = 0
 
-    # Gaussian, with some manual tuning to get good fall off
-    exponent = -((dist_km - min_dist_km) ** 2) / exp_denom
-    return int(perfect_score * math.exp(exponent)), dist_km
+    return point_score, dist_km