Remove previous cheat evaluator. Farewell, good cop, you did a great job
parent
49d3f497ca
commit
fb85cd0207
|
@ -16,9 +16,6 @@
|
|||
[submodule "submodules/boardcreator"]
|
||||
path = submodules/boardcreator
|
||||
url = https://github.com/clarkerubber/board-creator
|
||||
[submodule "submodules/evaluator"]
|
||||
path = submodules/evaluator
|
||||
url = https://github.com/ornicar/engine-evaluator
|
||||
[submodule "ui/chessli"]
|
||||
path = ui/chessli
|
||||
url = https://github.com/ornicar/chess.js
|
||||
|
|
|
@ -65,7 +65,6 @@ final class Env(
|
|||
Env.notification,
|
||||
Env.bookmark,
|
||||
Env.pref,
|
||||
Env.evaluation,
|
||||
Env.chat,
|
||||
Env.puzzle,
|
||||
Env.tv,
|
||||
|
@ -119,7 +118,6 @@ object Env {
|
|||
def relation = lila.relation.Env.current
|
||||
def report = lila.report.Env.current
|
||||
def pref = lila.pref.Env.current
|
||||
def evaluation = lila.evaluation.Env.current
|
||||
def chat = lila.chat.Env.current
|
||||
def puzzle = lila.puzzle.Env.current
|
||||
def coordinate = lila.coordinate.Env.current
|
||||
|
|
|
@ -147,18 +147,12 @@ object User extends LilaController {
|
|||
|
||||
def mod(username: String) = Secure(_.UserSpy) { implicit ctx =>
|
||||
me => OptionFuOk(UserRepo named username) { user =>
|
||||
(Env.evaluation.evaluator find user) zip (Env.security userSpy user.id) zip (Env.mod.assessApi.getPlayerAggregateAssessment(user.id)) map {
|
||||
case ((eval, spy), playerAggregateAssessment) => html.user.mod(user, spy, eval, playerAggregateAssessment)
|
||||
(Env.security userSpy user.id) zip (Env.mod.assessApi.getPlayerAggregateAssessment(user.id)) map {
|
||||
case (spy, playerAggregateAssessment) => html.user.mod(user, spy, playerAggregateAssessment)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def evaluate(username: String) = Secure(_.UserEvaluate) { implicit ctx =>
|
||||
me => OptionFuResult(UserRepo named username) { user =>
|
||||
Env.evaluation.evaluator.generate(user.id, true) inject Redirect(routes.User.show(username).url + "?mod")
|
||||
}
|
||||
}
|
||||
|
||||
def writeNote(username: String) = AuthBody { implicit ctx =>
|
||||
me => OptionFuResult(UserRepo named username) { user =>
|
||||
implicit val req = ctx.body
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
@(u: User, spy: lila.security.UserSpy, eval: Option[lila.evaluation.Evaluation], optionAggregateAssessment: Option[lila.evaluation.PlayerAggregateAssessment])(implicit ctx: Context)
|
||||
@(u: User, spy: lila.security.UserSpy, optionAggregateAssessment: Option[lila.evaluation.PlayerAggregateAssessment])(implicit ctx: Context)
|
||||
|
||||
@import lila.evaluation.Display
|
||||
|
||||
<div class="actions clearfix">
|
||||
@if(isGranted(_.UserEvaluate)) {
|
||||
<form method="post" action="@routes.User.evaluate(u.username)">
|
||||
<input class="button" type="submit" value="@{eval.isDefined.??("(Re)")}Evaluate (old)" />
|
||||
</form>
|
||||
<form method="post" action="@routes.Mod.refreshUserAssess(u.username)">
|
||||
<input class="button" type="submit" value="Evaluate (new)" />
|
||||
<input class="button" type="submit" value="Evaluate" />
|
||||
</form>
|
||||
}
|
||||
@if(isGranted(_.MarkEngine)) {
|
||||
|
@ -52,39 +49,6 @@
|
|||
</div>
|
||||
|
||||
<div class="user_spy">
|
||||
@eval.map { e =>
|
||||
<div class="evaluation">
|
||||
<p>
|
||||
<strong>@e.verdict(u.perfs)</strong> @e.isDeep.fold("Thoroughly", "Quickly") evaluated @momentFromNow(e.date) as @e.percent%
|
||||
<br />
|
||||
<br />
|
||||
</p>
|
||||
@if(e.games.nonEmpty) {
|
||||
<table class="slist">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Most suspicious games found</th>
|
||||
<th>Move time</th>
|
||||
<th>Blur</th>
|
||||
<th>Analysis</th>
|
||||
<th>Bot</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@e.games.map { g =>
|
||||
<tr>
|
||||
<td><a href="@g.path">@g.path</a></td>
|
||||
<td>@g.moveTime.map(_ + "%")</td>
|
||||
<td>@g.blur.map(_ + "%")</td>
|
||||
<td>@g.error.map(_ + "%")</td>
|
||||
<td>@g.hold.map(_ + "%")</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@optionAggregateAssessment.fold{
|
||||
<div class="evaluation">
|
||||
<p>
|
||||
|
|
|
@ -30,7 +30,6 @@ GET /rel/blocks controllers.Relation.blocks
|
|||
# User
|
||||
GET /@/:username/opponents controllers.User.opponents(username: String)
|
||||
GET /@/:username/mod controllers.User.mod(username: String)
|
||||
POST /@/:username/evaluate controllers.User.evaluate(username: String)
|
||||
POST /@/:username/note controllers.User.writeNote(username: String)
|
||||
GET /@/:username/mini controllers.User.showMini(username: String)
|
||||
GET /@/:username/tv controllers.User.tv(username: String)
|
||||
|
|
|
@ -20,7 +20,6 @@ case class ConcurrentAnalysisException(userId: String, progressId: String, gameI
|
|||
final class Analyser(
|
||||
ai: ActorSelection,
|
||||
indexer: ActorSelection,
|
||||
evaluator: ActorSelection,
|
||||
modActor: ActorSelection) {
|
||||
|
||||
def get(id: String): Fu[Option[Analysis]] = AnalysisRepo byId id flatMap evictStalled
|
||||
|
@ -77,9 +76,6 @@ final class Analyser(
|
|||
if (analysis.valid) {
|
||||
indexer ! InsertGame(game)
|
||||
AnalysisRepo.done(id, analysis) >>- {
|
||||
game.userIds foreach { userId =>
|
||||
evaluator ! lila.hub.actorApi.evaluation.Refresh(userId)
|
||||
}
|
||||
modActor ! actorApi.AnalysisReady(game, analysis)
|
||||
} >>- GameRepo.setAnalysed(game.id) inject analysis
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ final class Env(
|
|||
ai: ActorSelection,
|
||||
system: ActorSystem,
|
||||
indexer: ActorSelection,
|
||||
evaluator: ActorSelection,
|
||||
modActor: ActorSelection) {
|
||||
|
||||
private val CollectionAnalysis = config getString "collection.analysis"
|
||||
|
@ -28,7 +27,6 @@ final class Env(
|
|||
lazy val analyser = new Analyser(
|
||||
ai = ai,
|
||||
indexer = indexer,
|
||||
evaluator = evaluator,
|
||||
modActor = modActor)
|
||||
|
||||
lazy val paginator = new PaginatorBuilder(
|
||||
|
@ -66,6 +64,5 @@ object Env {
|
|||
ai = lila.hub.Env.current.actor.ai,
|
||||
system = lila.common.PlayApp.system,
|
||||
indexer = lila.hub.Env.current.actor.gameIndexer,
|
||||
evaluator = lila.hub.Env.current.actor.evaluator,
|
||||
modActor = lila.hub.Env.current.actor.mod)
|
||||
}
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
package lila.evaluation
|
||||
|
||||
import akka.actor._
|
||||
import com.typesafe.config.Config
|
||||
|
||||
final class Env(
|
||||
config: Config,
|
||||
db: lila.db.Env,
|
||||
hub: lila.hub.Env,
|
||||
system: ActorSystem) {
|
||||
|
||||
private val CollectionEvaluation = config getString "collection.evaluation"
|
||||
private val EvaluatorExecPath = config getString "evaluator.exec_path"
|
||||
private val ActorName = config getString "actor.name"
|
||||
private val ApiToken = config getString "api.token"
|
||||
private val ApiUrl = config getString "api.url"
|
||||
|
||||
lazy val evaluator = new Evaluator(
|
||||
coll = db(CollectionEvaluation),
|
||||
execPath = EvaluatorExecPath,
|
||||
reporter = hub.actor.report,
|
||||
analyser = hub.actor.analyser,
|
||||
marker = hub.actor.mod,
|
||||
token = ApiToken,
|
||||
apiUrl = ApiUrl)
|
||||
|
||||
system.actorOf(Props(new Listener(evaluator)), name = ActorName)
|
||||
}
|
||||
|
||||
object Env {
|
||||
|
||||
lazy val current = "[boot] evaluation" describes new Env(
|
||||
config = lila.common.PlayApp loadConfig "evaluation",
|
||||
db = lila.db.Env.current,
|
||||
hub = lila.hub.Env.current,
|
||||
system = lila.common.PlayApp.system)
|
||||
}
|
|
@ -1,142 +0,0 @@
|
|||
package lila.evaluation
|
||||
|
||||
import scala.util.{ Try, Success, Failure }
|
||||
|
||||
import akka.actor.ActorSelection
|
||||
import akka.pattern.ask
|
||||
import org.joda.time.DateTime
|
||||
import play.api.libs.json._
|
||||
import play.api.libs.json.Json
|
||||
import play.modules.reactivemongo.json.ImplicitBSONHandlers._
|
||||
import reactivemongo.bson._
|
||||
|
||||
import lila.db.api._
|
||||
import lila.db.BSON.BSONJodaDateTimeHandler
|
||||
import lila.db.JsTube.Helpers.{ rename, writeDate, readDate }
|
||||
import lila.db.Types._
|
||||
import lila.rating.{ Perf, PerfType }
|
||||
import lila.user.{ User, UserRepo, Perfs }
|
||||
|
||||
final class Evaluator(
|
||||
coll: Coll,
|
||||
execPath: String,
|
||||
reporter: ActorSelection,
|
||||
analyser: ActorSelection,
|
||||
marker: ActorSelection,
|
||||
token: String,
|
||||
apiUrl: String) {
|
||||
|
||||
import Evaluation._, heuristics._
|
||||
|
||||
def find(user: User): Fu[Option[Evaluation]] =
|
||||
coll.find(BSONDocument("_id" -> user.id)).one[JsObject] map { _ map readEvaluation }
|
||||
|
||||
def evaluatedAt(user: User): Fu[Option[DateTime]] =
|
||||
coll.find(
|
||||
BSONDocument("_id" -> user.id),
|
||||
BSONDocument("date" -> true)
|
||||
).one[BSONDocument] map { _ flatMap (_.getAs[DateTime]("date")) }
|
||||
|
||||
def generate(userId: String, deep: Boolean): Fu[Option[Evaluation]] =
|
||||
UserRepo byId userId flatMap {
|
||||
_ ?? { user =>
|
||||
(run(userId, deep) match {
|
||||
case Failure(e: Exception) if e.getMessage.contains("exit value: 1") => fuccess(none)
|
||||
case Failure(e: Exception) if e.getMessage.contains("exit value: 2") => fuccess(none)
|
||||
case Failure(e: Exception) => fufail(e)
|
||||
case Success(output) => for {
|
||||
evalJs ← (Json parse output).transform(evaluationTransformer) match {
|
||||
case JsSuccess(v, _) => fuccess(v)
|
||||
case JsError(e) => fufail(lila.common.LilaException(s"Can't parse evaluator output: $e on $output"))
|
||||
}
|
||||
eval = readEvaluation(evalJs)
|
||||
_ ← coll.update(Json.obj("_id" -> userId), evalJs, upsert = true)
|
||||
} yield eval.some
|
||||
}) andThen {
|
||||
case Success(Some(eval)) if Evaluation.watchPerfs(user.perfs) exists eval.mark =>
|
||||
UserRepo byId userId foreach {
|
||||
_ filterNot (_.engine) foreach { user =>
|
||||
marker ! lila.hub.actorApi.mod.MarkCheater(user.id)
|
||||
reporter ! lila.hub.actorApi.report.Check(user.id)
|
||||
}
|
||||
}
|
||||
case Failure(e) => logger.warn(s"generate: $e")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private[evaluation] def autoGenerate(
|
||||
user: User,
|
||||
perfType: PerfType,
|
||||
important: Boolean,
|
||||
forceRefresh: Boolean,
|
||||
suspiciousHold: Boolean) {
|
||||
val perf = user.perfs(perfType)
|
||||
if (!user.engine && (
|
||||
important || suspiciousHold ||
|
||||
(deviationIsLow(perf) && (progressIsHigh(perf) || ratingIsHigh(perf)))
|
||||
)) {
|
||||
evaluatedAt(user) foreach { date =>
|
||||
def freshness = if (progressIsVeryHigh(perf)) DateTime.now minusMinutes 20
|
||||
else if (progressIsHigh(perf)) DateTime.now minusHours 1
|
||||
else DateTime.now minusDays 2
|
||||
if (suspiciousHold || forceRefresh || date.fold(true)(_ isBefore freshness)) {
|
||||
generate(user.id, true) foreach {
|
||||
_ foreach { eval =>
|
||||
eval.gameIdsToAnalyse foreach { gameId =>
|
||||
analyser ! lila.hub.actorApi.ai.AutoAnalyse(gameId)
|
||||
if (eval report perf)
|
||||
reporter ! lila.hub.actorApi.report.Cheater(user.id, eval reportText 3)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private[evaluation] def autoGenerate(
|
||||
user: User,
|
||||
important: Boolean,
|
||||
forceRefresh: Boolean,
|
||||
suspiciousHold: Boolean) {
|
||||
user.perfs.bestPerf foreach {
|
||||
case (pt, _) => autoGenerate(user, pt, important, forceRefresh, suspiciousHold)
|
||||
}
|
||||
}
|
||||
private[evaluation] def autoGenerate(userId: String, important: Boolean, forceRefresh: Boolean) {
|
||||
UserRepo byId userId foreach {
|
||||
_ foreach { autoGenerate(_, important, forceRefresh, false) }
|
||||
}
|
||||
}
|
||||
|
||||
private def readEvaluation(js: JsValue): Evaluation =
|
||||
(readDate('date) andThen Evaluation.reader) reads js match {
|
||||
case JsSuccess(v, _) => v
|
||||
case JsError(e) => throw lila.common.LilaException(s"Can't parse evaluator json: $e on $js")
|
||||
}
|
||||
|
||||
private def run(userId: String, deep: Boolean): Try[String] = {
|
||||
import scala.sys.process._
|
||||
import java.io.File
|
||||
val exec = Process(Seq("php", "engine-evaluator.php", userId, deep.fold("true", "false"), token, s"$apiUrl/"), new File(execPath))
|
||||
Try {
|
||||
exec.!!
|
||||
} match {
|
||||
case Failure(e) => Failure(new Exception(s"$exec $e"))
|
||||
case x => x
|
||||
}
|
||||
}
|
||||
|
||||
private def evaluationTransformer =
|
||||
rename('userId, '_id) andThen
|
||||
rename('cheatIndex, 'shallow) andThen
|
||||
rename('deepIndex, 'deep) andThen
|
||||
rename('computerAnalysis, 'analysis) andThen
|
||||
rename('knownEngineIP, 'sharedIP) andThen
|
||||
__.json.update(
|
||||
__.read[JsObject].map { o => o ++ Json.obj("date" -> $date(DateTime.now)) }
|
||||
) andThen
|
||||
(__ \ 'Error).json.prune
|
||||
|
||||
private val logger = play.api.Logger("evaluator")
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package lila.evaluation
|
||||
|
||||
import akka.actor._
|
||||
import lila.game.PerfPicker
|
||||
import chess.{ Speed, White, Black }
|
||||
import lila.hub.actorApi.evaluation._
|
||||
import lila.user.User
|
||||
import lila.rating.PerfType
|
||||
|
||||
private[evaluation] final class Listener(evaluator: Evaluator) extends Actor {
|
||||
|
||||
context.system.lilaBus.subscribe(self, 'finishGame)
|
||||
|
||||
def receive = {
|
||||
|
||||
case lila.game.actorApi.FinishGame(game, white, black) =>
|
||||
PerfType(PerfPicker key game) ifTrue game.rated map { perfType =>
|
||||
List(
|
||||
game.whitePlayer -> white,
|
||||
game.blackPlayer -> black
|
||||
) foreach {
|
||||
case (p, Some(u)) => evaluator.autoGenerate(
|
||||
user = u,
|
||||
perfType = perfType,
|
||||
important = p.wins && game.isTournament && game.speed != Speed.Bullet,
|
||||
forceRefresh = false,
|
||||
suspiciousHold = p.hasSuspiciousHoldAlert)
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
|
||||
case user: User => evaluator.generate(user.id, true)
|
||||
|
||||
case AutoCheck(userId) => evaluator.autoGenerate(userId, true, false)
|
||||
|
||||
case Refresh(userId) => evaluator.autoGenerate(userId, false, true)
|
||||
}
|
||||
}
|
|
@ -27,7 +27,6 @@ final class Env(config: Config, system: ActorSystem) {
|
|||
val challenger = select("actor.challenger")
|
||||
val report = select("actor.report")
|
||||
val mod = select("actor.mod")
|
||||
val evaluator = select("actor.evaluator")
|
||||
val chat = select("actor.chat")
|
||||
val analyser = select("actor.analyser")
|
||||
val moveBroadcast = select("actor.move_broadcast")
|
||||
|
|
|
@ -16,7 +16,7 @@ final class Env(
|
|||
|
||||
lazy val forms = new DataForm(hub.actor.captcher)
|
||||
|
||||
lazy val api = new ReportApi(hub.actor.evaluator)
|
||||
lazy val api = new ReportApi
|
||||
|
||||
// api actor
|
||||
system.actorOf(Props(new Actor {
|
||||
|
|
|
@ -10,7 +10,7 @@ import lila.db.Implicits._
|
|||
import lila.user.{ User, UserRepo }
|
||||
import tube.reportTube
|
||||
|
||||
private[report] final class ReportApi(evaluator: ActorSelection) {
|
||||
private[report] final class ReportApi {
|
||||
|
||||
def create(setup: ReportSetup, by: User): Funit =
|
||||
Reason(setup.reason).fold[Funit](fufail("Invalid report reason " + setup.reason)) { reason =>
|
||||
|
@ -25,15 +25,9 @@ private[report] final class ReportApi(evaluator: ActorSelection) {
|
|||
selectRecent(user, reason),
|
||||
Json.obj("$set" -> (reportTube.toMongo(report).get - "processedBy" - "_id"))
|
||||
) flatMap { res =>
|
||||
(!res.updatedExisting) ?? {
|
||||
if (report.isCheat) evaluator ! user
|
||||
$insert(report)
|
||||
}
|
||||
(!res.updatedExisting) ?? $insert(report)
|
||||
}
|
||||
else {
|
||||
if (report.isCheat) evaluator ! user
|
||||
$insert(report)
|
||||
}
|
||||
else $insert(report)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -91,8 +91,7 @@ final class Env(
|
|||
renderer = hub.actor.renderer
|
||||
)), name = ReminderName),
|
||||
isOnline = isOnline,
|
||||
socketHub = socketHub,
|
||||
evaluator = hub.actor.evaluator
|
||||
socketHub = socketHub
|
||||
)), name = OrganizerName)
|
||||
|
||||
private val tournamentScheduler = system.actorOf(Props(new Scheduler(api)))
|
||||
|
@ -123,10 +122,6 @@ final class Env(
|
|||
organizer -> actorApi.StartedTournaments
|
||||
}
|
||||
|
||||
scheduler.message(6 minutes) {
|
||||
organizer -> actorApi.CheckLeaders
|
||||
}
|
||||
|
||||
scheduler.message(5 minutes) {
|
||||
tournamentScheduler -> actorApi.ScheduleNow
|
||||
}
|
||||
|
|
|
@ -13,8 +13,7 @@ private[tournament] final class Organizer(
|
|||
api: TournamentApi,
|
||||
reminder: ActorRef,
|
||||
isOnline: String => Boolean,
|
||||
socketHub: ActorRef,
|
||||
evaluator: ActorSelection) extends Actor {
|
||||
socketHub: ActorRef) extends Actor {
|
||||
|
||||
context.system.lilaBus.subscribe(self, 'finishGame, 'adjustCheater)
|
||||
|
||||
|
@ -42,12 +41,6 @@ private[tournament] final class Organizer(
|
|||
reminder ! RemindTournaments(tours)
|
||||
}
|
||||
|
||||
case CheckLeaders => TournamentRepo.started foreach {
|
||||
_.flatMap(_.leaders).map(_.id).distinct foreach { id =>
|
||||
evaluator ! lila.hub.actorApi.evaluation.AutoCheck(id)
|
||||
}
|
||||
}
|
||||
|
||||
case FinishGame(game, _, _) => api finishGame game
|
||||
|
||||
case lila.hub.actorApi.mod.MarkCheater(userId) => api ejectCheater userId
|
||||
|
|
|
@ -32,7 +32,6 @@ private[tournament] case class Connected(enumerator: JsEnumerator, member: Membe
|
|||
// organizer
|
||||
private[tournament] case object AllCreatedTournaments
|
||||
private[tournament] case object StartedTournaments
|
||||
private[tournament] case object CheckLeaders
|
||||
case class RemindTournaments(tours: List[Started])
|
||||
case class RemindTournament(tour: Started)
|
||||
case class TournamentTable(tours: List[Enterable])
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 16586282ce3d6cf67459582a612aa17571ffc9d0
|
Loading…
Reference in New Issue