Adjust rating refund logic

Cap refunds to 50 above best rating, and adjust
logic when current rating is higher than rating
during unfair game.

This closes #4073.
pull/4076/head
Isaac Levy 2018-02-28 15:07:01 -05:00
parent 5631c71d26
commit d2cb085bf6
4 changed files with 31 additions and 9 deletions

View File

@ -171,7 +171,7 @@ lazy val event = module("event", Seq(common, db, memo, i18n)).settings(
)
lazy val mod = module("mod", Seq(common, db, user, hub, security, tournament, simul, game, analyse, evaluation,
report, notifyModule, history)).settings(
report, notifyModule, history, perfStat)).settings(
libraryDependencies ++= provided(play.api, play.test, reactivemongo.driver)
)

View File

@ -31,6 +31,8 @@ final class PimpedLong(private val self: Long) extends AnyVal {
def atMost(topValue: Long): Long = min(self, topValue)
def squeeze(bottom: Long, top: Long): Long = max(min(self, top), bottom)
def truncInt: Int =
if (self.toInt == self) self.toInt
else if (self > 0) Integer.MAX_VALUE
@ -42,6 +44,8 @@ final class PimpedInt(private val self: Int) extends AnyVal {
def atLeast(bottomValue: Int): Int = max(self, bottomValue)
def atMost(topValue: Int): Int = min(self, topValue)
def squeeze(bottom: Int, top: Int): Int = max(min(self, top), bottom)
}
final class PimpedFloat(private val self: Float) extends AnyVal {
@ -49,6 +53,8 @@ final class PimpedFloat(private val self: Float) extends AnyVal {
def atLeast(bottomValue: Float): Float = max(self, bottomValue)
def atMost(topValue: Float): Float = min(self, topValue)
def squeeze(bottom: Float, top: Float): Float = max(min(self, top), bottom)
}
final class PimpedDouble(private val self: Double) extends AnyVal {
@ -56,4 +62,6 @@ final class PimpedDouble(private val self: Double) extends AnyVal {
def atLeast(bottomValue: Double): Double = max(self, bottomValue)
def atMost(topValue: Double): Double = min(self, topValue)
def squeeze(bottom: Double, top: Double): Double = max(min(self, top), bottom)
}

View File

@ -10,6 +10,7 @@ final class Env(
config: Config,
db: lila.db.Env,
hub: lila.hub.Env,
perfStat: lila.perfStat.Env,
system: ActorSystem,
scheduler: lila.common.Scheduler,
firewall: Firewall,
@ -54,7 +55,8 @@ final class Env(
notifier = notifier,
historyApi = historyApi,
rankingApi = rankingApi,
wasUnengined = logApi.wasUnengined
wasUnengined = logApi.wasUnengined,
perfStatter = perfStat.get _
)
lazy val publicChat = new PublicChat(chatApi, tournamentApi, simulEnv)
@ -134,6 +136,7 @@ object Env {
config = lila.common.PlayApp loadConfig "mod",
db = lila.db.Env.current,
hub = lila.hub.Env.current,
perfStat = lila.perfStat.Env.current,
system = lila.common.PlayApp.system,
scheduler = lila.common.PlayApp.scheduler,
firewall = lila.security.Env.current.firewall,

View File

@ -10,13 +10,15 @@ import lila.game.{ Game, GameRepo, Query }
import lila.rating.PerfType
import lila.user.{ User, UserRepo }
import lila.report.{ Suspect, Victim }
import lila.perfStat.PerfStat
private final class RatingRefund(
scheduler: lila.common.Scheduler,
notifier: ModNotifier,
historyApi: lila.history.HistoryApi,
rankingApi: lila.user.RankingApi,
wasUnengined: Suspect => Fu[Boolean]
wasUnengined: Suspect => Fu[Boolean],
perfStatter: (User, PerfType) => Fu[PerfStat]
) {
import RatingRefund._
@ -47,9 +49,10 @@ private final class RatingRefund(
} yield refs.add(victim, perf, -diff, rating)) | refs
}
def pointsToRefund(ref: Refund, user: User): Int = {
ref.diff - user.perfs(ref.perf).intRating + 100 + ref.topRating
} min ref.diff min 200 max 0
def pointsToRefund(ref: Refund, curRating: Int, perfs: PerfStat): Int = {
ref.diff - (ref.diff + curRating - ref.topRating atLeast 0) / 2 atMost
perfs.highest.fold(100) { _.int - curRating + 50 }
} squeeze (0, 150)
def refundPoints(victim: Victim, pt: PerfType, points: Int): Funit = {
val newPerf = victim.user.perfs(pt) refund points
@ -62,9 +65,17 @@ private final class RatingRefund(
def applyRefund(ref: Refund) =
UserRepo byId ref.victim flatMap {
_ ?? { user =>
val points = pointsToRefund(ref, user)
logger.info(s"Refunding $ref -> $points")
(points > 0) ?? refundPoints(Victim(user), ref.perf, points)
perfStatter(user, ref.perf) flatMap { perfs =>
val points = pointsToRefund(
ref,
curRating = user.perfs(ref.perf).intRating,
perfs = perfs
)
(points > 0) ?? {
logger.info(s"Refunding $ref -> $points")
refundPoints(Victim(user), ref.perf, points)
}
}
}
}