Skip to content

Commit

Permalink
swiss: no longer store player pairing
Browse files Browse the repository at this point in the history
this is all completely nonsensical. I hate swiss.
  • Loading branch information
ornicar committed May 15, 2020
1 parent 54f95af commit 095caad
Show file tree
Hide file tree
Showing 18 changed files with 131 additions and 140 deletions.
19 changes: 19 additions & 0 deletions bin/mongodb/swiss-remove-number.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
db.swiss_pairing.dropIndex('s_1_u_1');
db.swiss_pairing.dropIndex('s_1_n_1');

db.swiss.find().forEach(swiss => {

let index = {};
db.swiss_player.find({s:swiss._id}).forEach(p => {
index[p.n] = p.u;
});

db.swiss_pairing.find({s:swiss._id}).forEach(p => {
db.swiss_pairing.update({_id:p._id},{$set:{
p:[index[p.p[0]],index[p.p[1]]],
t: p.t == p.p[0] ? NumberInt(0) : (p.t == p.p[1] ? NumberInt(1) : p.t)
}});
});

db.swiss_player.update({s:swiss._id},{$unset:{n:1}},{multi:1});
});
24 changes: 11 additions & 13 deletions modules/swiss/src/main/BsonHandlers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import scala.concurrent.duration._

import chess.Clock.{ Config => ClockConfig }
import chess.variant.Variant
import chess.StartingPosition
import chess.{ Color, StartingPosition }
import lila.db.BSON
import lila.db.dsl._
import lila.user.User
import reactivemongo.api.bson._

private object BsonHandlers {
Expand Down Expand Up @@ -46,19 +47,17 @@ private object BsonHandlers {
implicit val swissTieBreakHandler = doubleAnyValHandler[Swiss.TieBreak](_.value, Swiss.TieBreak.apply)
implicit val swissPerformanceHandler =
floatAnyValHandler[Swiss.Performance](_.value, Swiss.Performance.apply)
implicit val swissScoreHandler = intAnyValHandler[Swiss.Score](_.value, Swiss.Score.apply)
implicit val playerNumberHandler = intAnyValHandler[SwissPlayer.Number](_.value, SwissPlayer.Number.apply)
implicit val roundNumberHandler = intAnyValHandler[SwissRound.Number](_.value, SwissRound.Number.apply)
implicit val swissIdHandler = stringAnyValHandler[Swiss.Id](_.value, Swiss.Id.apply)
implicit val playerIdHandler = stringAnyValHandler[SwissPlayer.Id](_.value, SwissPlayer.Id.apply)
implicit val swissScoreHandler = intAnyValHandler[Swiss.Score](_.value, Swiss.Score.apply)
implicit val roundNumberHandler = intAnyValHandler[SwissRound.Number](_.value, SwissRound.Number.apply)
implicit val swissIdHandler = stringAnyValHandler[Swiss.Id](_.value, Swiss.Id.apply)
implicit val playerIdHandler = stringAnyValHandler[SwissPlayer.Id](_.value, SwissPlayer.Id.apply)

implicit val playerHandler = new BSON[SwissPlayer] {
import SwissPlayer.Fields._
def reads(r: BSON.Reader) =
SwissPlayer(
id = r.get[SwissPlayer.Id](id),
swissId = r.get[Swiss.Id](swissId),
number = r.get[SwissPlayer.Number](number),
userId = r str userId,
rating = r int rating,
provisional = r boolD provisional,
Expand All @@ -73,7 +72,6 @@ private object BsonHandlers {
$doc(
id -> o.id,
swissId -> o.swissId,
number -> o.number,
userId -> o.userId,
rating -> o.rating,
provisional -> w.boolO(o.provisional),
Expand All @@ -88,20 +86,20 @@ private object BsonHandlers {

implicit val pairingStatusHandler = lila.db.dsl.quickHandler[SwissPairing.Status](
{
case BSONInteger(n) => Right(SwissPlayer.Number(n).some)
case BSONBoolean(true) => Left(SwissPairing.Ongoing)
case _ => Right(none)
case BSONBoolean(true) => Left(SwissPairing.Ongoing)
case BSONInteger(index) => Right(Color(index == 0).some)
case _ => Right(none)
},
{
case Left(_) => BSONBoolean(true)
case Right(Some(n)) => BSONInteger(n.value)
case Right(Some(c)) => BSONInteger(c.fold(0, 1))
case _ => BSONNull
}
)
implicit val pairingHandler = new BSON[SwissPairing] {
import SwissPairing.Fields._
def reads(r: BSON.Reader) =
r.get[List[SwissPlayer.Number]](players) match {
r.get[List[User.ID]](players) match {
case List(w, b) =>
SwissPairing(
id = r str id,
Expand Down
6 changes: 3 additions & 3 deletions modules/swiss/src/main/Env.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@ final class Env(

private val sheetApi = wire[SwissSheetApi]

private lazy val rankingApi: SwissRankingApi = wire[SwissRankingApi]

val trf: SwissTrf = wire[SwissTrf]

private val pairingSystem = new PairingSystem(trf, appConfig.get[String]("swiss.bbpairing"))
private val pairingSystem = new PairingSystem(trf, rankingApi, appConfig.get[String]("swiss.bbpairing"))

private val scoring = wire[SwissScoring]

Expand All @@ -56,8 +58,6 @@ final class Env(

lazy val standingApi = wire[SwissStandingApi]

private lazy val rankingApi = wire[SwissRankingApi]

lazy val json = wire[SwissJson]

lazy val forms = wire[SwissForm]
Expand Down
20 changes: 12 additions & 8 deletions modules/swiss/src/main/PairingSystem.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@ import java.io.File
import scala.concurrent.blocking
import scala.sys.process._

final private class PairingSystem(trf: SwissTrf, executable: String)(implicit
import lila.user.User

final private class PairingSystem(trf: SwissTrf, rankingApi: SwissRankingApi, executable: String)(implicit
ec: scala.concurrent.ExecutionContext,
mat: akka.stream.Materializer
) {

def apply(swiss: Swiss): Fu[List[SwissPairing.ByeOrPending]] =
invoke(swiss, trf(swiss)) map reader
rankingApi(swiss) flatMap { ranking =>
invoke(swiss, trf(swiss, ranking)) map reader(ranking.map(_.swap))
}

private def invoke(swiss: Swiss, input: Source[String, _]): Fu[List[String]] =
withTempFile(input) { file =>
Expand All @@ -31,20 +35,20 @@ final private class PairingSystem(trf: SwissTrf, executable: String)(implicit
} else stdout.toList
}

private def reader(output: List[String]): List[SwissPairing.ByeOrPending] =
private def reader(rankingSwap: Map[Int, User.ID])(output: List[String]): List[SwissPairing.ByeOrPending] =
output
.drop(1) // first line is the number of pairings
.map(_ split ' ')
.collect {
case Array(p, "0") =>
p.toIntOption map { p =>
Left(SwissPairing.Bye(SwissPlayer.Number(p)))
p.toIntOption flatMap rankingSwap.get map { userId =>
Left(SwissPairing.Bye(userId))
}
case Array(w, b) =>
for {
white <- w.toIntOption
black <- b.toIntOption
} yield Right(SwissPairing.Pending(SwissPlayer.Number(white), SwissPlayer.Number(black)))
white <- w.toIntOption flatMap rankingSwap.get
black <- b.toIntOption flatMap rankingSwap.get
} yield Right(SwissPairing.Pending(white, black))
}
.flatten

Expand Down
47 changes: 18 additions & 29 deletions modules/swiss/src/main/SwissApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,7 @@ final class SwissApi(
.flatMap { rejoin =>
fuccess(rejoin.n == 1) >>| { // if the match failed (not the update!), try a join
(swiss.isEnterable && isInTeam(swiss.teamId)) ?? {
val number = SwissPlayer.Number(swiss.nbPlayers + 1)
colls.player.insert.one(SwissPlayer.make(swiss.id, number, me, swiss.perfLens)) zip
colls.player.insert.one(SwissPlayer.make(swiss.id, me, swiss.perfLens)) zip
colls.swiss.update.one($id(swiss.id), $inc("nbPlayers" -> 1)) inject true
}
}
Expand All @@ -150,16 +149,8 @@ final class SwissApi(
if (swiss.isStarted)
colls.player.updateField($id(SwissPlayer.makeId(swiss.id, me.id)), f.absent, true)
else
colls.player.ext.findAndRemove[SwissPlayer]($id(SwissPlayer.makeId(swiss.id, me.id))) flatMap {
_ ?? { player =>
colls.player.update
.one(
$doc(f.swissId -> id, f.number $gt player.number),
$inc(f.number -> -1),
multi = true
) zip
colls.swiss.update.one($id(swiss.id), $inc("nbPlayers" -> -1)) void
}
colls.player.delete.one($id(SwissPlayer.makeId(swiss.id, me.id))) flatMap { res =>
(res.n == 1) ?? colls.swiss.update.one($id(swiss.id), $inc("nbPlayers" -> -1)).void
}
}.void >>- recomputeAndUpdateAll(id)
}
Expand Down Expand Up @@ -194,7 +185,7 @@ final class SwissApi(
_ ?? { player =>
SwissPairing.fields { f =>
colls.pairing.ext
.find($doc(f.swissId -> swiss.id, f.players -> player.number))
.find($doc(f.swissId -> swiss.id, f.players -> player.userId))
.sort($sort asc f.round)
.list[SwissPairing]()
} flatMap {
Expand Down Expand Up @@ -226,7 +217,7 @@ final class SwissApi(
pairings.headOption ?? { first =>
SwissPlayer.fields { f =>
colls.player.ext
.find($doc(f.swissId -> first.swissId, f.number $in pairings.map(_ opponentOf player.number)))
.find($inIds(pairings.map(_ opponentOf player.userId).map { SwissPlayer.makeId(first.swissId, _) }))
.list[SwissPlayer]()
} flatMap { opponents =>
lightUserApi asyncMany opponents.map(_.userId) map { users =>
Expand All @@ -235,7 +226,7 @@ final class SwissApi(
}
} map { opponents =>
pairings flatMap { pairing =>
opponents.find(_.player.number == pairing.opponentOf(player.number)) map {
opponents.find(_.player.userId == pairing.opponentOf(player.userId)) map {
SwissPairing.View(pairing, _)
}
}
Expand All @@ -257,16 +248,9 @@ final class SwissApi(
}

def pageOf(swiss: Swiss, userId: User.ID): Fu[Option[Int]] =
colls.player.primitiveOne[SwissPlayer.Number](
$id(SwissPlayer.makeId(swiss.id, userId)),
SwissPlayer.Fields.number
) flatMap {
_ ?? { number =>
rankingApi(swiss) map {
_ get number map { rank =>
(Math.floor(rank / 10) + 1).toInt
}
}
rankingApi(swiss) map {
_ get userId map { rank =>
(Math.floor(rank / 10) + 1).toInt
}
}

Expand All @@ -279,10 +263,15 @@ final class SwissApi(
} else
colls.pairing.byId[SwissPairing](game.id).dmap(_.filter(_.isOngoing)) flatMap {
_ ?? { pairing =>
val winner = game.winnerColor
.map(_.fold(pairing.white, pairing.black))
.flatMap(playerNumberHandler.writeOpt)
colls.pairing.updateField($id(game.id), SwissPairing.Fields.status, winner | BSONNull).void >> {
colls.pairing
.updateField(
$id(game.id),
SwissPairing.Fields.status,
game.winnerColor
.map(_.fold(pairing.white, pairing.black))
.fold[BSONValue](BSONNull)(BSONString.apply)
)
.void >> {
if (swiss.nbOngoing > 0)
colls.swiss.update.one($id(swiss.id), $inc("nbOngoing" -> -1))
else
Expand Down
6 changes: 3 additions & 3 deletions modules/swiss/src/main/SwissBoard.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ final private class SwissBoardApi(
case (player, _) if player.present => player
}
.flatMap { player =>
pairings get player.number flatMap {
pairings get player.userId flatMap {
_ get swiss.round
}
}
Expand All @@ -65,8 +65,8 @@ final private class SwissBoardApi(
p2 <- playerMap get pairing.black
u1 <- lightUserApi sync p1.userId
u2 <- lightUserApi sync p2.userId
r1 <- ranks get p1.number
r2 <- ranks get p2.number
r1 <- ranks get p1.userId
r2 <- ranks get p2.userId
} yield SwissBoard(
pairing.gameId,
white = SwissBoard.Player(u1, r1 + 1, p1.rating),
Expand Down
6 changes: 3 additions & 3 deletions modules/swiss/src/main/SwissDirector.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import scala.util.chaining._

import lila.db.dsl._
import lila.game.Game
import lila.user.User

final private class SwissDirector(
colls: SwissColls,
Expand All @@ -30,7 +31,6 @@ final private class SwissDirector(
players <- SwissPlayer.fields { f =>
colls.player.ext
.find($doc(f.swissId -> swiss.id))
.sort($sort asc f.number)
.list[SwissPlayer]()
}
ids <- idGenerator.games(pendingPairings.size)
Expand Down Expand Up @@ -59,7 +59,7 @@ final private class SwissDirector(
byes = pendings.collect { case Left(bye) => bye.player }
_ <- SwissPlayer.fields { f =>
colls.player.update
.one($doc(f.number $in byes, f.swissId -> swiss.id), $addToSet(f.byes -> swiss.round))
.one($doc(f.userId $in byes, f.swissId -> swiss.id), $addToSet(f.byes -> swiss.round))
.void
}
_ <- colls.pairing.insert.many(pairings).void
Expand All @@ -78,7 +78,7 @@ final private class SwissDirector(
}
.monSuccess(_.swiss.startRound)

private def makeGame(swiss: Swiss, players: Map[SwissPlayer.Number, SwissPlayer])(
private def makeGame(swiss: Swiss, players: Map[User.ID, SwissPlayer])(
pairing: SwissPairing
): Game =
Game
Expand Down
10 changes: 5 additions & 5 deletions modules/swiss/src/main/SwissJson.scala
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ final class SwissJson(
.?? {
colls.pairing
.find(
$doc(f.swissId -> swiss.id, f.players -> player.number, f.status -> SwissPairing.ongoing),
$doc(f.swissId -> swiss.id, f.players -> player.userId, f.status -> SwissPairing.ongoing),
$doc(f.id -> true).some
)
.sort($sort desc f.round)
Expand Down Expand Up @@ -110,7 +110,7 @@ final class SwissJson(
// guess its rank based on other players scores in the DB
private def getOrGuessRank(swiss: Swiss, player: SwissPlayer): Fu[Int] =
rankingApi(swiss) flatMap {
_ get player.number match {
_ get player.userId match {
case Some(rank) => fuccess(rank)
case None =>
SwissPlayer.fields { f =>
Expand Down Expand Up @@ -241,7 +241,7 @@ object SwissJson {
private def pairingJsonMin(player: SwissPlayer, pairing: SwissPairing): String = {
val status =
if (pairing.isOngoing) "o"
else pairing.resultFor(player.number).fold("d") { r => if (r) "w" else "l" }
else pairing.resultFor(player.userId).fold("d") { r => if (r) "w" else "l" }
s"${pairing.gameId}$status"
}

Expand All @@ -251,8 +251,8 @@ object SwissJson {
"g" -> pairing.gameId
)
.add("o" -> pairing.isOngoing)
.add("w" -> pairing.resultFor(player.number))
.add("c" -> (pairing.white == player.number))
.add("w" -> pairing.resultFor(player.userId))
.add("c" -> (pairing.white == player.userId))

private def pairingJsonOrOutcome(
player: SwissPlayer
Expand Down
Loading

0 comments on commit 095caad

Please sign in to comment.