Skip to content

Commit

Permalink
Revert "remove lichess.org/network (world map)"
Browse files Browse the repository at this point in the history
This reverts commit 0e6fb16.
  • Loading branch information
ornicar committed Dec 22, 2015
1 parent 9489afd commit 0e48dfe
Show file tree
Hide file tree
Showing 11 changed files with 209 additions and 1 deletion.
1 change: 1 addition & 0 deletions app/Env.scala
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ object Env {
def donation = lila.donation.Env.current
def qa = lila.qa.Env.current
def history = lila.history.Env.current
def worldMap = lila.worldMap.Env.current
def opening = lila.opening.Env.current
def video = lila.video.Env.current
def playban = lila.playban.Env.current
Expand Down
21 changes: 21 additions & 0 deletions app/controllers/WorldMap.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package controllers

import play.api.libs.EventSource
import play.api.libs.json._
import play.api.mvc._, Results._

import lila.app._
import views._

object WorldMap extends LilaController {

def index = Action {
Ok(views.html.site.worldMap())
}

def stream = Action {
Ok.chunked(
Env.worldMap.stream.producer &> EventSource()
) as "text/event-stream"
}
}
33 changes: 33 additions & 0 deletions app/views/site/worldMap.scala.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
@()

<!DOCTYPE html>

<html>
<head>
<title>Lichess World Map</title>
<link rel="shortcut icon" href="@routes.Assets.at("images/favicon-32-white.png")" type="image/x-icon" />
@cssAt("worldMap/main.css")
<meta content="noindex, nofollow" name="robots">
</head>
<body>
<h1><a href="http://lichess.org">lichess<span class="extension">.org</span></a> network</h1>
<div id="worldmap"></div>
<div id="stats">
<div class="wrapL">
<div id="time">time: <span></span></div>
<div id="moves">moves: <span></span></div>
<div id="countries">countries: <span></span></div>
</div>
<div class="wrapL">
<div id="topCountries"></div>
</div>
</div>
@jQueryTag
@jsAt("worldMap/MIDIUtils.js")
@jsAt("worldMap/raphael-min.js")
@jsAt("worldMap/world.js")
@jsAt("worldMap/time.js")
@jsAt("worldMap/app.js")
@jsAt("worldMap/stats.js")
</body>
</html>
4 changes: 4 additions & 0 deletions conf/base.conf
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,10 @@ shutup {
playban {
collection.playban = playban
}
worldMap {
geoip = ${geoip}
players.cache_size = 8192
}
push {
collection.device = push_device
google {
Expand Down
4 changes: 4 additions & 0 deletions conf/routes
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,10 @@ GET /themepicker controllers.Main.themepicker
GET /mobile controllers.Main.mobile
GET /lag controllers.Main.lag

# Map
GET /network controllers.WorldMap.index
GET /network/stream controllers.WorldMap.stream

# Mobile Push
POST /mobile/register/:platform/:deviceId controllers.Main.mobileRegister(platform: String, deviceId: String)
POST /mobile/unregister controllers.Main.mobileUnregister
Expand Down
31 changes: 31 additions & 0 deletions modules/worldMap/src/main/Env.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package lila.worldMap

import com.typesafe.config.Config

import com.sanoma.cda.geoip.MaxMindIpGeo
import lila.common.PimpedConfig._

final class Env(
system: akka.actor.ActorSystem,
config: Config) {

private val GeoIPFile = config getString "geoip.file"
private val GeoIPCacheTtl = config duration "geoip.cache_ttl"
private val PlayersCacheSize = config getInt "players.cache_size"

lazy val players = new Players(PlayersCacheSize)

lazy val stream = new Stream(
system = system,
players = players,
geoIp = MaxMindIpGeo(GeoIPFile, 0),
geoIpCacheTtl = GeoIPCacheTtl)
}

object Env {

lazy val current: Env = "worldMap" boot new Env(
system = lila.common.PlayApp.system,
config = lila.common.PlayApp loadConfig "worldMap")
}

37 changes: 37 additions & 0 deletions modules/worldMap/src/main/Players.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package lila.worldMap

import lila.memo.Builder

private[worldMap] final class Players(cacheSize: Int) {

// to each game ID, associate list of player Locations
// there can be 0, 1 or 2 players per game ID,
// but this constraint is not expressed by the cache type :(
private val cache = Builder.size[String, List[Location]](cacheSize)

def getOpponentLocation(gameId: String, myLocation: Location): Option[Location] =

Option(cache getIfPresent gameId) getOrElse Nil match {

// new game ID, store player location
case Nil =>
cache.put(gameId, List(myLocation)); None

// only my location is known
case List(loc) if loc == myLocation => None

// only opponent location is known. Store mine
case List(loc) =>
cache.put(gameId, List(loc, myLocation)); Some(loc)

// both locations are known
case List(l1, l2) if l1 == myLocation => Some(l2)

// both locations are known
case List(l1, l2) if l2 == myLocation => Some(l1)

// both are unknown
case _ => None
}
}

54 changes: 54 additions & 0 deletions modules/worldMap/src/main/Stream.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package lila.worldMap

import akka.actor._
import com.google.common.cache.LoadingCache
import com.sanoma.cda.geoip.{ MaxMindIpGeo, IpLocation }
import java.io.File
import lila.hub.actorApi.round.MoveEvent
import play.api.libs.iteratee._
import play.api.libs.json._
import scala.concurrent.duration._

final class Stream(
system: ActorSystem,
players: Players,
geoIp: MaxMindIpGeo,
geoIpCacheTtl: Duration) {

private val (enumerator, channel) = Concurrent.broadcast[MoveEvent]

private val ipCache = lila.memo.Builder.cache(geoIpCacheTtl, localizeIp)
private def localizeIp(ip: String): Option[Location] =
geoIp getLocation ip flatMap Location.apply

def processMove(move: MoveEvent) =
ipCache get move.ip match {
case None => Input.Empty
case Some(loc) =>
val opponentLoc = players.getOpponentLocation(move.gameId, loc)
Input.El(List(
loc.country,
loc.lat,
loc.lon,
opponentLoc.map(_.lat) getOrElse "",
opponentLoc.map(_.lon) getOrElse "",
move.move,
move.piece,
opponentLoc.map(_.country) getOrElse ""
) mkString "|")
}

private val processor: Enumeratee[MoveEvent, String] =
Enumeratee.mapInput[MoveEvent].apply[String] {
case Input.El(move) => processMove(move)
case _ => Input.Empty
}

val producer = enumerator &> processor

system.lilaBus.subscribe(system.actorOf(Props(new Actor {
def receive = {
case move: MoveEvent => channel push move
}
})), 'moveEvent)
}
16 changes: 16 additions & 0 deletions modules/worldMap/src/main/model.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package lila.worldMap

import com.sanoma.cda.geoip.IpLocation

case class Location(
country: String,
lat: Double,
lon: Double)

object Location {

def apply(ipLoc: IpLocation): Option[Location] = for {
country <- ipLoc.countryName
point <- ipLoc.geoPoint
} yield Location(country, point.latitude, point.longitude)
}
3 changes: 3 additions & 0 deletions modules/worldMap/src/main/package.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package lila

package object worldMap extends PackageObject with WithPlay
6 changes: 5 additions & 1 deletion project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ object ApplicationBuild extends Build {
ai, analyse, mod, monitor, site, round, lobby, setup,
importer, tournament, simul, relation, report, pref, // simulation,
evaluation, chat, puzzle, tv, coordinate, blog, donation, qa,
history, opening, video, shutup, push,
history, worldMap, opening, video, shutup, push,
playban, insight)

lazy val moduleRefs = modules map projectToRef
Expand Down Expand Up @@ -81,6 +81,10 @@ object ApplicationBuild extends Build {
libraryDependencies ++= provided(play.api, RM, PRM)
)

lazy val worldMap = project("worldMap", Seq(common, hub, memo)).settings(
libraryDependencies ++= provided(play.api, maxmind)
)

lazy val qa = project("qa", Seq(common, db, memo, user, security)).settings(
libraryDependencies ++= provided(play.api, RM, PRM)
)
Expand Down

0 comments on commit 0e48dfe

Please sign in to comment.