more progress on pools
This commit is contained in:
parent
aa158fcc63
commit
a1680d2221
|
@ -56,6 +56,24 @@ trait UserHelper { self: I18nHelper with StringHelper =>
|
|||
}
|
||||
}
|
||||
|
||||
def lightUserLink(
|
||||
user: LightUser,
|
||||
cssClass: Option[String] = None,
|
||||
withOnline: Boolean = true,
|
||||
withTitle: Boolean = true,
|
||||
truncate: Option[Int] = None,
|
||||
params: String = ""): Html = Html {
|
||||
userIdNameLink(
|
||||
userId = user.id,
|
||||
username = user.name,
|
||||
title = user.title,
|
||||
cssClass = cssClass,
|
||||
withOnline = withOnline,
|
||||
withTitle = withTitle,
|
||||
truncate = truncate,
|
||||
params = params)
|
||||
}
|
||||
|
||||
def userIdLink(
|
||||
userId: String,
|
||||
cssClass: Option[String]): Html = userIdLink(userId.some, cssClass)
|
||||
|
|
|
@ -5,18 +5,18 @@ case (p, it) => {
|
|||
<div class="pool_@(it + 1)">
|
||||
<h2>@p.setup.name</h2>
|
||||
<div class="body">
|
||||
@defining(4) { displayedUsers =>
|
||||
<table class="users">
|
||||
@defining(4) { displayedPlayers =>
|
||||
<table class="players">
|
||||
<tbody>
|
||||
@p.sortedUsers.take(displayedUsers).map { user =>
|
||||
@p.playersAround(ctx.me, displayedPlayers).map { player =>
|
||||
<tr>
|
||||
<td>@userLink(user, withRating = false)</td>
|
||||
<td>@p.setup.glickoLens(user).intRating</td>
|
||||
<td>@lightUserLink(player.user)</td>
|
||||
<td>@player.rating</td>
|
||||
</tr>
|
||||
}
|
||||
@defining(p.nbUsers - displayedUsers) { moreUsers =>
|
||||
@if(moreUsers > 0) {
|
||||
<tr><td colspan=2>And 15 more</td></tr>
|
||||
@defining(p.nbPlayers - displayedPlayers) { morePlayers =>
|
||||
@if(morePlayers > 0) {
|
||||
<tr><td colspan=2>And @morePlayers more</td></tr>
|
||||
}
|
||||
}
|
||||
</tbody>
|
||||
|
|
|
@ -4,20 +4,20 @@
|
|||
<table class="slist standing">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="large">@trans.standing() (@p.nbUsers)</th>
|
||||
<th class="large">@trans.standing() (@p.nbPlayers)</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@p.rankedUsers.map {
|
||||
case (user, rank) => {
|
||||
<tr @if(ctx is user) { class="me" }>
|
||||
@p.rankedPlayers.map {
|
||||
case (player, rank) => {
|
||||
<tr @if(ctx.userId ?? (player.user.id==)) { class="me" }>
|
||||
<td class="name">
|
||||
<span class="rank">@rank</span>
|
||||
@userLink(user, withRating = false)
|
||||
@lightUserLink(player.user)
|
||||
</td>
|
||||
<td class="rating">
|
||||
@p.setup.glickoLens(user).intRating
|
||||
@player.rating
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ final class Env(
|
|||
history = new History(ttl = HistoryMessageTtl),
|
||||
uidTimeout = UidTimeout,
|
||||
lightUser = lightUser,
|
||||
isOnline = isOnline,
|
||||
renderer = hub.actor.renderer)
|
||||
}), name = SocketName)
|
||||
|
||||
|
|
6
modules/pool/src/main/Player.scala
Normal file
6
modules/pool/src/main/Player.scala
Normal file
|
@ -0,0 +1,6 @@
|
|||
package lila.pool
|
||||
|
||||
case class Player(user: lila.common.LightUser, rating: Int) {
|
||||
|
||||
def is(p: Player) = user.id == p.user.id
|
||||
}
|
|
@ -1,28 +1,43 @@
|
|||
package lila.pool
|
||||
|
||||
import lila.common.LightUser
|
||||
import lila.user.User
|
||||
|
||||
case class Pool(
|
||||
setup: PoolSetup,
|
||||
users: List[User]) {
|
||||
players: List[Player]) {
|
||||
|
||||
lazy val sortedUsers = users.sortBy(u => -setup.glickoLens(u).intRating)
|
||||
lazy val sortedPlayers = players.sortBy(-_.rating)
|
||||
|
||||
lazy val rankedUsers = sortedUsers.zipWithIndex map {
|
||||
case (user, rank) => user -> (rank + 1)
|
||||
lazy val rankedPlayers = sortedPlayers.zipWithIndex map {
|
||||
case (player, rank) => player -> (rank + 1)
|
||||
}
|
||||
|
||||
lazy val nbUsers = users.size
|
||||
lazy val nbPlayers = players.size
|
||||
|
||||
def contains(u: User) = users contains u
|
||||
def contains(userId: String): Boolean = players exists (_.user.id == userId)
|
||||
def contains(u: User): Boolean = contains(u.id)
|
||||
def contains(p: Player): Boolean = contains(p.user.id)
|
||||
|
||||
def withUser(u: User) = copy(users = u :: users).distinctUsers
|
||||
def withPlayer(p: Player) = copy(players = p :: players).distinctPlayers
|
||||
def withUser(u: User) = withPlayer(Player(
|
||||
LightUser(u.id, u.username, u.title),
|
||||
setup.glickoLens(u).intRating
|
||||
))
|
||||
|
||||
private def distinctUsers = copy(
|
||||
users = users.map { u =>
|
||||
u.id -> u
|
||||
def filterPlayers(cond: Player => Boolean) = copy(players = players filter cond)
|
||||
|
||||
private def distinctPlayers = copy(
|
||||
players = players.map { p =>
|
||||
p.user.id -> p
|
||||
}.toMap.values.toList
|
||||
)
|
||||
|
||||
def withoutUser(u: User) = copy(users = users filter (_.id != u.id))
|
||||
def withoutPlayer(p: Player) = copy(players = players filterNot (_ is p))
|
||||
def withoutUser(u: User) = copy(players = players filterNot (_.user.id == u.id))
|
||||
|
||||
def playersAround(uo: Option[User], nb: Int) = uo.fold(sortedPlayers take nb) { u =>
|
||||
val rating = setup.glickoLens(u).intRating
|
||||
players.sortBy(p => math.abs(rating - p.rating)) take nb sortBy (-_.rating)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,18 +8,26 @@ import play.api.libs.json._
|
|||
|
||||
import actorApi._
|
||||
import lila.common.LightUser
|
||||
import lila.hub.actorApi.SendTos
|
||||
import lila.socket.actorApi.{ Connected => _, _ }
|
||||
import lila.socket.{ SocketActor, History, Historical }
|
||||
import lila.hub.actorApi.SendTos
|
||||
import lila.user.User
|
||||
|
||||
private[pool] final class PoolActor(
|
||||
setup: PoolSetup,
|
||||
val history: History,
|
||||
lightUser: String => Option[LightUser],
|
||||
isOnline: String => Boolean,
|
||||
renderer: ActorSelection,
|
||||
uidTimeout: Duration) extends SocketActor[Member](uidTimeout) with Historical[Member] {
|
||||
|
||||
private var pool = Pool(setup, Nil)
|
||||
lila.user.UserRepo randomDudes scala.util.Random.nextInt(500) foreach { users =>
|
||||
pool = users.foldLeft(pool)(_ withUser _)
|
||||
}
|
||||
|
||||
// last time each user waved to the pool
|
||||
private val wavers = new lila.memo.ExpireSetMemo(10 seconds)
|
||||
|
||||
def receiveSpecific = {
|
||||
|
||||
|
@ -27,12 +35,23 @@ private[pool] final class PoolActor(
|
|||
|
||||
case Enter(user) =>
|
||||
pool = pool withUser user
|
||||
wavers put user.id
|
||||
sender ! true
|
||||
|
||||
case Wave(user) =>
|
||||
wavers put user.id
|
||||
|
||||
case Leave(user) =>
|
||||
pool = pool withoutUser user
|
||||
sender ! true
|
||||
|
||||
case Broom =>
|
||||
broom
|
||||
pool = pool filterPlayers { p =>
|
||||
wavers get p.user.id
|
||||
}
|
||||
pool.players map (_.user.id) filter isOnline foreach wavers.put
|
||||
|
||||
case GetVersion => sender ! history.version
|
||||
|
||||
// case StartGame(game) => game.players foreach { player =>
|
||||
|
@ -49,7 +68,7 @@ private[pool] final class PoolActor(
|
|||
import makeTimeout.short
|
||||
renderer ? RemindPool(pool) foreach {
|
||||
case html: play.twirl.api.Html =>
|
||||
val event = SendTos(pool.users.map(_.id).toSet, Json.obj(
|
||||
val event = SendTos(pool.players.map(_.user.id).toSet, Json.obj(
|
||||
"t" -> "poolReminder",
|
||||
"d" -> Json.obj(
|
||||
"id" -> pool.setup.id,
|
||||
|
@ -58,7 +77,7 @@ private[pool] final class PoolActor(
|
|||
context.system.lilaBus.publish(event, 'users)
|
||||
}
|
||||
|
||||
case Reload => notifyReload
|
||||
case Reload => notifyReload
|
||||
|
||||
case PingVersion(uid, v) =>
|
||||
ping(uid)
|
||||
|
@ -66,8 +85,6 @@ private[pool] final class PoolActor(
|
|||
history.since(v).fold(resync(m))(_ foreach sendMessage(m))
|
||||
}
|
||||
|
||||
case Broom => broom
|
||||
|
||||
case lila.chat.actorApi.ChatLine(_, line) => line match {
|
||||
case line: lila.chat.UserLine =>
|
||||
notifyVersionTrollable("message", lila.chat.Line toJson line, troll = line.troll)
|
||||
|
|
|
@ -30,6 +30,7 @@ private[pool] case object GetPool
|
|||
private[pool] case object Reload
|
||||
private[pool] case class Enter(user: User)
|
||||
private[pool] case class Leave(user: User)
|
||||
private[pool] case class Wave(user: User)
|
||||
private[pool] case object Pairing
|
||||
private[pool] case object CheckLeaders
|
||||
case class RemindPool(pool: Pool)
|
||||
|
|
|
@ -72,6 +72,8 @@ trait UserRepo {
|
|||
|
||||
def usernameById(id: ID) = $primitive.one($select(id), F.username)(_.asOpt[String])
|
||||
|
||||
def randomDudes(nb: Int) = $find($query(stableGoodLadSelect) sort BSONDocument("count.games" -> -1) skip scala.util.Random.nextInt(5000), nb)
|
||||
|
||||
def rank(user: User) = $count(enabledSelect ++ Json.obj(F.rating -> $gt(Glicko.default.rating))) map (1+)
|
||||
|
||||
def orderByGameCount(u1: String, u2: String): Fu[Option[(String, String)]] =
|
||||
|
|
|
@ -14,7 +14,7 @@ object ApplicationBuild extends Build {
|
|||
resolvers ++= Dependencies.Resolvers.commons,
|
||||
scalacOptions := compilerOptions,
|
||||
incOptions := incOptions.value.withNameHashing(true),
|
||||
offline := false,
|
||||
offline := true,
|
||||
libraryDependencies ++= Seq(
|
||||
scalaz, scalalib, hasher, config, apache, scalaTime,
|
||||
csv, jgit, actuarius, elastic4s, findbugs, RM,
|
||||
|
|
|
@ -219,6 +219,7 @@ body.dark div.content_box .loader:before,
|
|||
body.dark div.content_box .loader:after {
|
||||
background-color: #2b2b2b;
|
||||
}
|
||||
body.dark #pool_list h2,
|
||||
body.dark #timeline,
|
||||
body.dark #timeline > .entry {
|
||||
border-color: #2b2b2b;
|
||||
|
@ -416,6 +417,10 @@ body.dark div.user_show div.user-infos.scroll-shadow-hard {
|
|||
background-size: 100% 20px, 100% 20px, 100% 10px, 100% 10px;
|
||||
background-attachment: local, local, scroll, scroll;
|
||||
}
|
||||
body.dark #pool_list > div {
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
box-shadow: 0 0 2px rgba(255,255,255,0.2);
|
||||
}
|
||||
body.dark::-webkit-input-placeholder {
|
||||
color: #666;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,4 @@
|
|||
width: 246px;
|
||||
max-height: 510px;
|
||||
overflow-y: hidden;
|
||||
border: 1px solid #ccc;
|
||||
padding: 3px;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue