forked from lichess-org/lila
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
25 changed files
with
769 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
@() | ||
|
||
<!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") | ||
</head> | ||
<body> | ||
<h1><a href="http://lichess.org">lichess<span class="extension">.org</span></a> activity</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/raphael-min.js") | ||
@jsAt("worldMap/world.js") | ||
@jsAt("worldMap/time.js") | ||
@jsAt("worldMap/app.js") | ||
@jsAt("worldMap/stats.js") | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,33 @@ | ||
package lila.round | ||
// package lila.round | ||
|
||
import akka.actor._ | ||
// import akka.actor._ | ||
|
||
import com.roundeights.hasher.Implicits._ | ||
// import com.roundeights.hasher.Implicits._ | ||
|
||
import lila.hub.actorApi.round.MoveEvent | ||
import play.api.libs.iteratee._ | ||
// import lila.hub.actorApi.round.MoveEvent | ||
// import play.api.libs.iteratee._ | ||
|
||
private final class MoveBroadcast(salt: String) extends Actor { | ||
// private final class MoveBroadcast(salt: String) extends Actor { | ||
|
||
context.system.lilaBus.subscribe(self, 'moveEvent) | ||
// context.system.lilaBus.subscribe(self, 'moveEvent) | ||
|
||
override def postStop() { | ||
context.system.lilaBus.unsubscribe(self) | ||
} | ||
// override def postStop() { | ||
// context.system.lilaBus.unsubscribe(self) | ||
// } | ||
|
||
private val (enumerator, channel) = Concurrent.broadcast[String] | ||
// private val (enumerator, channel) = Concurrent.broadcast[String] | ||
|
||
def receive = { | ||
// def receive = { | ||
|
||
case MoveBroadcast.GetEnumerator => sender ! enumerator | ||
// case MoveBroadcast.GetEnumerator => sender ! enumerator | ||
|
||
case move: MoveEvent => channel push s"${tokenOf(move.gameId)} ${move.ip}" | ||
} | ||
// case move: MoveEvent => channel push s"${tokenOf(move.gameId)} ${move.ip}" | ||
// } | ||
|
||
def tokenOf(gameId: String) = gameId.salt(salt).md5.hex take 8 | ||
} | ||
// def tokenOf(gameId: String) = gameId.salt(salt).md5.hex take 8 | ||
// } | ||
|
||
object MoveBroadcast { | ||
// object MoveBroadcast { | ||
|
||
case object GetEnumerator | ||
} | ||
// case object GetEnumerator | ||
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
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 GeoIPCacheSize = config getInt "geoip.cache_size" | ||
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, GeoIPCacheSize)) | ||
} | ||
|
||
object Env { | ||
|
||
lazy val current: Env = "[boot] worldMap" describes new Env( | ||
system = lila.common.PlayApp.system, | ||
config = lila.common.PlayApp loadConfig "worldMap") | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
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) | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
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._ | ||
|
||
final class Stream( | ||
system: ActorSystem, | ||
players: Players, | ||
geoIp: MaxMindIpGeo) { | ||
|
||
private val (enumerator, channel) = Concurrent.broadcast[MoveEvent] | ||
|
||
private val processor: Enumeratee[MoveEvent, String] = | ||
Enumeratee.mapInput[MoveEvent].apply[String] { | ||
case Input.El(move) => | ||
geoIp getLocation move.ip flatMap Location.apply match { | ||
case None => Input.Empty | ||
case Some(loc) => | ||
val opponentLoc = players.getOpponentLocation(move.gameId, loc) | ||
Input.El(Json.stringify { | ||
Json.obj( | ||
"country" -> loc.country, | ||
"lat" -> loc.lat, | ||
"lon" -> loc.lon, | ||
"oLat" -> opponentLoc.map(_.lat), | ||
"oLon" -> opponentLoc.map(_.lon) | ||
) | ||
}) | ||
} | ||
case _ => Input.Empty | ||
} | ||
|
||
val producer = enumerator &> processor | ||
|
||
system.lilaBus.subscribe(system.actorOf(Props(new Actor { | ||
def receive = { | ||
case move: MoveEvent => channel push move | ||
} | ||
})), 'moveEvent) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package lila | ||
|
||
package object worldMap extends PackageObject with WithPlay |
Oops, something went wrong.