Double playban times: don't add field to Player

pull/5240/head
ProgramFOX 2019-06-30 17:00:01 -04:00
parent 5c8707cf44
commit dbe9b4476c
3 changed files with 32 additions and 34 deletions

View File

@ -24,8 +24,7 @@ case class Player(
blurs: Blurs = Blurs.blursZero.zero,
holdAlert: Option[Player.HoldAlert] = None,
berserk: Boolean = false,
name: Option[String] = None,
accountCreationDate: Option[DateTime] = None
name: Option[String] = None
) {
def playerUser = userId flatMap { uid =>
@ -149,7 +148,6 @@ object Player {
val holdAlert = "h"
val berserk = "be"
val name = "na"
val accountCreationDate = "cd"
}
import reactivemongo.bson._
@ -192,8 +190,7 @@ object Player {
blurs = r.getO[Blurs.Bits](blursBits) orElse r.getO[Blurs.Nb](blursNb) getOrElse blursZero.zero,
holdAlert = r.getO[HoldAlert](holdAlert),
berserk = r boolD berserk,
name = r strO name,
accountCreationDate = r dateO accountCreationDate
name = r strO name
)
def writes(w: BSON.Writer, o: Builder) =
@ -209,8 +206,7 @@ object Player {
provisional -> w.boolO(p.provisional),
blursBits -> (!p.blurs.isEmpty).option(BlursBSONWriter write p.blurs),
holdAlert -> p.holdAlert,
name -> p.name,
accountCreationDate -> p.accountCreationDate
name -> p.name
)
}
}

View File

@ -44,20 +44,20 @@ final class PlaybanApi(
def abort(pov: Pov, isOnGame: Set[Color]): Funit = IfBlameable(pov.game) {
pov.player.userId.ifTrue(isOnGame(pov.opponent.color)) ?? { userId =>
save(Outcome.Abort, userId, pov.player.accountCreationDate) >>- feedback.abort(pov)
save(Outcome.Abort, userId) >>- feedback.abort(pov)
}
}
def noStart(pov: Pov): Funit = IfBlameable(pov.game) {
pov.player.userId ?? { userId =>
save(Outcome.NoPlay, userId, pov.player.accountCreationDate) >>- feedback.noStart(pov)
save(Outcome.NoPlay, userId) >>- feedback.noStart(pov)
}
}
def rageQuit(game: Game, quitterColor: Color): Funit =
sandbag(game, quitterColor) >> IfBlameable(game) {
game.player(quitterColor).userId ?? { userId =>
save(Outcome.RageQuit, userId, game.player(quitterColor).accountCreationDate) >>- feedback.rageQuit(Pov(game, quitterColor))
save(Outcome.RageQuit, userId) >>- feedback.rageQuit(Pov(game, quitterColor))
}
}
@ -70,23 +70,21 @@ final class PlaybanApi(
// flagged after waiting a long time
def sitting = for {
userId <- game.player(flaggerColor).userId
accountCreationDate <- game.player(flaggerColor).accountCreationDate
seconds = nowSeconds - game.movedAt.getSeconds
limit <- unreasonableTime
if seconds >= limit
} yield save(Outcome.Sitting, userId, Some(accountCreationDate)) >>- feedback.sitting(Pov(game, flaggerColor))
} yield save(Outcome.Sitting, userId) >>- feedback.sitting(Pov(game, flaggerColor))
// flagged after waiting a short time;
// but the previous move used a long time.
// assumes game was already checked for sitting
def sitMoving = for {
userId <- game.player(flaggerColor).userId
accountCreationDate <- game.player(flaggerColor).accountCreationDate
movetimes <- game moveTimes flaggerColor
lastMovetime <- movetimes.lastOption
limit <- unreasonableTime
if lastMovetime.toSeconds >= limit
} yield save(Outcome.SitMoving, userId, Some(accountCreationDate)) >>- feedback.sitting(Pov(game, flaggerColor))
} yield save(Outcome.SitMoving, userId) >>- feedback.sitting(Pov(game, flaggerColor))
sandbag(game, flaggerColor) flatMap { isSandbag =>
IfBlameable(game) {
@ -103,9 +101,8 @@ final class PlaybanApi(
~(for {
w <- winner
loserId <- game.player(!w).userId
accountCreationDate <- game.player(!w).accountCreationDate
} yield {
if (Status.NoStart is status) save(Outcome.NoPlay, loserId, Some(accountCreationDate)) >>- feedback.noStart(Pov(game, !w))
if (Status.NoStart is status) save(Outcome.NoPlay, loserId) >>- feedback.noStart(Pov(game, !w))
else goodOrSandbag(game, !w, isSandbag)
})
}
@ -114,7 +111,7 @@ final class PlaybanApi(
private def goodOrSandbag(game: Game, color: Color, isSandbag: Boolean): Funit =
game.player(color).userId ?? { userId =>
if (isSandbag) feedback.sandbag(Pov(game, color))
save(if (isSandbag) Outcome.Sandbag else Outcome.Good, userId, game.player(color).accountCreationDate)
save(if (isSandbag) Outcome.Sandbag else Outcome.Good, userId)
}
def currentBan(userId: User.ID): Fu[Option[TempBan]] = coll.find(
@ -151,24 +148,26 @@ final class PlaybanApi(
}(scala.collection.breakOut)
}
private def save(outcome: Outcome, userId: User.ID, accountCreationDate: Option[DateTime]): Funit = {
private def save(outcome: Outcome, userId: User.ID): Funit = {
lila.mon.playban.outcome(outcome.key)()
coll.findAndUpdate(
selector = $id(userId),
update = $doc("$push" -> $doc(
"o" -> $doc(
"$each" -> List(outcome),
"$slice" -> -30
)
), "$set" -> $doc("c" -> accountCreationDate.getOrElse(DateTime.now))),
fetchNewObject = true,
upsert = true
).map(_.value)
} map2 UserRecordBSONHandler.read flatMap {
case None => fufail(s"can't find record for user $userId")
case _ if outcome == Outcome.Good => funit
case Some(record) => legiferate(record)
} logFailure lila.log("playban")
UserRepo.createdAtById(userId) map2 { (accCreatedAt: DateTime) =>
coll.findAndUpdate(
selector = $id(userId),
update = $doc("$push" -> $doc(
"o" -> $doc(
"$each" -> List(outcome),
"$slice" -> -30
)
), "$set" -> $doc("c" -> accCreatedAt)),
fetchNewObject = true,
upsert = true
).map(_.value) map2 UserRecordBSONHandler.read flatMap {
case None => fufail(s"can't find record for user $userId")
case _ if outcome == Outcome.Good => funit
case Some(record) => legiferate(record)
}
}
}.void logFailure lila.log("playban")
private def legiferate(record: UserRecord): Funit = record.bannable ?? { ban =>
(!record.banInEffect) ?? {

View File

@ -113,6 +113,9 @@ object UserRepo {
def usernamesByIds(ids: List[ID]) =
coll.distinct[String, List](F.username, $inIds(ids).some)
def createdAtById(id: ID) =
coll.primitiveOne[DateTime]($id(id), F.createdAt)
def orderByGameCount(u1: User.ID, u2: User.ID): Fu[Option[(User.ID, User.ID)]] = {
coll.find(
$inIds(List(u1, u2)),