Use ratings date in cache filename
This commit is contained in:
@@ -2,13 +2,17 @@ package org.jeudego.pairgoth.ratings
|
|||||||
|
|
||||||
import com.republicate.kson.Json
|
import com.republicate.kson.Json
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
import java.time.LocalDate
|
||||||
|
|
||||||
object AGARatingsHandler: RatingsHandler(RatingsManager.Ratings.AGA) {
|
object AGARatingsHandler: RatingsHandler(RatingsManager.Ratings.AGA) {
|
||||||
override val defaultURL: URL by lazy {
|
override val defaultURL: URL by lazy {
|
||||||
throw Error("No URL for AGA...")
|
throw Error("No functional URL for AGA...")
|
||||||
}
|
}
|
||||||
override val active = false
|
override val active = false
|
||||||
override fun parsePayload(payload: String): Json.Array {
|
override fun parsePayload(payload: String): Pair<LocalDate, Json.Array> {
|
||||||
return Json.Array()
|
return Pair(
|
||||||
|
LocalDate.MIN,
|
||||||
|
Json.Array()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,11 +2,18 @@ package org.jeudego.pairgoth.ratings
|
|||||||
|
|
||||||
import com.republicate.kson.Json
|
import com.republicate.kson.Json
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
object EGFRatingsHandler: RatingsHandler(RatingsManager.Ratings.EGF) {
|
object EGFRatingsHandler: RatingsHandler(RatingsManager.Ratings.EGF) {
|
||||||
|
val ratingsDateFormatter = DateTimeFormatter.ofPattern("dd MMM yyyy")
|
||||||
override val defaultURL = URL("https://www.europeangodatabase.eu/EGD/EGD_2_0/downloads/allworld_lp.html")
|
override val defaultURL = URL("https://www.europeangodatabase.eu/EGD/EGD_2_0/downloads/allworld_lp.html")
|
||||||
override fun parsePayload(payload: String): Json.Array {
|
override fun parsePayload(payload: String): Pair<LocalDate, Json.Array> {
|
||||||
return payload.lines().filter {
|
val ratingsDateString = payload.lines().filter { it.startsWith("(") }.first().trim().removeSurrounding("(", ")")
|
||||||
|
val ratingsDate = LocalDate.parse(ratingsDateString, ratingsDateFormatter)
|
||||||
|
return Pair(
|
||||||
|
ratingsDate,
|
||||||
|
payload.lines().filter {
|
||||||
it.matches(Regex("\\s+\\d+(?!.*\\(undefined\\)|Anonymous).*"))
|
it.matches(Regex("\\s+\\d+(?!.*\\(undefined\\)|Anonymous).*"))
|
||||||
}.mapNotNullTo(Json.MutableArray()) {
|
}.mapNotNullTo(Json.MutableArray()) {
|
||||||
val match = linePattern.matchEntire(it)
|
val match = linePattern.matchEntire(it)
|
||||||
@@ -29,6 +36,7 @@ object EGFRatingsHandler: RatingsHandler(RatingsManager.Ratings.EGF) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
// 19574643 Abad Jahin FR 38GJ 20k -- 15 2 T200202B
|
// 19574643 Abad Jahin FR 38GJ 20k -- 15 2 T200202B
|
||||||
var linePattern =
|
var linePattern =
|
||||||
|
@@ -1,17 +1,20 @@
|
|||||||
package org.jeudego.pairgoth.ratings
|
package org.jeudego.pairgoth.ratings
|
||||||
|
|
||||||
import com.republicate.kson.Json
|
import com.republicate.kson.Json
|
||||||
import okhttp3.Interceptor
|
|
||||||
import okhttp3.OkHttpClient
|
|
||||||
import okhttp3.Request
|
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.nio.charset.Charset
|
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
object FFGRatingsHandler: RatingsHandler(RatingsManager.Ratings.FFG) {
|
object FFGRatingsHandler: RatingsHandler(RatingsManager.Ratings.FFG) {
|
||||||
|
val ratingsDateFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy")
|
||||||
override val defaultURL = URL("https://ffg.jeudego.org/echelle/echtxt/ech_ffg_V3.txt")
|
override val defaultURL = URL("https://ffg.jeudego.org/echelle/echtxt/ech_ffg_V3.txt")
|
||||||
override fun parsePayload(payload: String): Json.Array {
|
override fun parsePayload(payload: String): Pair<LocalDate, Json.Array> {
|
||||||
return payload.lines().mapNotNullTo(Json.MutableArray()) { line ->
|
val ratingsDateString = payload.lineSequence().first().substringAfter("#Echelle au ").substringBefore(" ")
|
||||||
|
val ratingsDate = LocalDate.parse(ratingsDateString, ratingsDateFormatter)
|
||||||
|
return Pair(
|
||||||
|
ratingsDate,
|
||||||
|
payload.lines().mapNotNullTo(Json.MutableArray()) { line ->
|
||||||
val match = linePattern.matchEntire(line)
|
val match = linePattern.matchEntire(line)
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
logger.error("could not parse line: $line")
|
logger.error("could not parse line: $line")
|
||||||
@@ -31,6 +34,7 @@ object FFGRatingsHandler: RatingsHandler(RatingsManager.Ratings.FFG) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun defaultCharset() = StandardCharsets.ISO_8859_1
|
override fun defaultCharset() = StandardCharsets.ISO_8859_1
|
||||||
|
@@ -6,18 +6,27 @@ import okhttp3.OkHttpClient
|
|||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import org.jeudego.pairgoth.web.WebappManager
|
import org.jeudego.pairgoth.web.WebappManager
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
|
import java.io.File
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
|
import java.text.DateFormat
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
import kotlin.io.path.name
|
||||||
|
import kotlin.io.path.useDirectoryEntries
|
||||||
|
|
||||||
abstract class RatingsHandler(val origin: RatingsManager.Ratings) {
|
abstract class RatingsHandler(val origin: RatingsManager.Ratings) {
|
||||||
|
companion object {
|
||||||
private val delay = TimeUnit.HOURS.toMillis(1L)
|
private val delay = TimeUnit.HOURS.toMillis(1L)
|
||||||
|
private val ymd = DateTimeFormatter.ofPattern("yyyyMMdd")
|
||||||
|
}
|
||||||
private val client = OkHttpClient()
|
private val client = OkHttpClient()
|
||||||
abstract val defaultURL: URL
|
abstract val defaultURL: URL
|
||||||
open val active = true
|
open val active = true
|
||||||
val cacheFile = RatingsManager.path.resolve("${origin.name}.json").toFile()
|
// val cacheFile = RatingsManager.path.resolve("${origin.name}.json").toFile()
|
||||||
lateinit var players: Json.Array
|
lateinit var players: Json.Array
|
||||||
private var updated = false
|
private var updated = false
|
||||||
|
|
||||||
@@ -25,23 +34,38 @@ abstract class RatingsHandler(val origin: RatingsManager.Ratings) {
|
|||||||
WebappManager.properties.getProperty("ratings.${origin.name.lowercase(Locale.ROOT)}")?.let { URL(it) } ?: defaultURL
|
WebappManager.properties.getProperty("ratings.${origin.name.lowercase(Locale.ROOT)}")?.let { URL(it) } ?: defaultURL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getRatingsFiles() = RatingsManager.path.useDirectoryEntries("${origin.name}-*.json") { entries ->
|
||||||
|
entries.sortedBy { it.fileName.name }.map {
|
||||||
|
it.toFile()
|
||||||
|
}.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getLatestRatingsFile() = getRatingsFiles().lastOrNull()
|
||||||
|
|
||||||
|
private fun initIfNeeded(ratingsFile: File): Boolean {
|
||||||
|
return if (!this::players.isInitialized) {
|
||||||
|
players = Json.parse(ratingsFile.readText())?.asArray() ?: Json.Array()
|
||||||
|
true
|
||||||
|
} else false
|
||||||
|
}
|
||||||
|
|
||||||
fun updateIfNeeded(): Boolean {
|
fun updateIfNeeded(): Boolean {
|
||||||
return if (Date().time - cacheFile.lastModified() > delay) {
|
val latestRatingsFile = getLatestRatingsFile()
|
||||||
RatingsManager.logger.info("Updating $origin cache from $url")
|
if (latestRatingsFile != null && Date().time - latestRatingsFile.lastModified() < delay) {
|
||||||
|
return initIfNeeded(latestRatingsFile)
|
||||||
|
}
|
||||||
val payload = fetchPayload()
|
val payload = fetchPayload()
|
||||||
players = parsePayload(payload).also {
|
val (lastUpdated, lastPlayers) = parsePayload(payload)
|
||||||
val cachePayload = it.toString()
|
val targetRatingsFilename = "${origin.name}-${ymd.format(lastUpdated)}.json"
|
||||||
cacheFile.printWriter().use { out ->
|
if (latestRatingsFile != null && latestRatingsFile.name == targetRatingsFilename) {
|
||||||
out.println(cachePayload)
|
return initIfNeeded(latestRatingsFile)
|
||||||
}
|
}
|
||||||
|
RatingsManager.logger.info("Updating $origin cache from $url")
|
||||||
|
RatingsManager.path.resolve(targetRatingsFilename).toFile().printWriter().use { out ->
|
||||||
|
out.println(lastPlayers.toString())
|
||||||
}
|
}
|
||||||
true
|
players = lastPlayers
|
||||||
} else if (!this::players.isInitialized) {
|
return true
|
||||||
players = Json.parse(cacheFile.readText())?.asArray() ?: Json.Array()
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fetchPlayers(): Json.Array {
|
fun fetchPlayers(): Json.Array {
|
||||||
@@ -62,7 +86,7 @@ abstract class RatingsHandler(val origin: RatingsManager.Ratings) {
|
|||||||
}
|
}
|
||||||
open fun defaultCharset() = StandardCharsets.UTF_8
|
open fun defaultCharset() = StandardCharsets.UTF_8
|
||||||
fun updated() = updated
|
fun updated() = updated
|
||||||
abstract fun parsePayload(payload: String): Json.Array
|
abstract fun parsePayload(payload: String): Pair<LocalDate, Json.Array>
|
||||||
val logger = LoggerFactory.getLogger(origin.name)
|
val logger = LoggerFactory.getLogger(origin.name)
|
||||||
val atom = "[-._`'a-zA-ZÀ-ÿ]"
|
val atom = "[-._`'a-zA-ZÀ-ÿ]"
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user