test and implement binary clock storage
parent
dff14fb7b8
commit
9887cd7c1c
|
@ -0,0 +1,9 @@
|
|||
limit 0-255 8 bits
|
||||
increment 0-255 8 bits
|
||||
|
||||
w (centisec) 0-16M 24 bits
|
||||
b (centisec) 0-16M 24 bits
|
||||
|
||||
timer (centis) 0-1E12 40 bits
|
||||
|
||||
= 13 bytes
|
|
@ -8,6 +8,37 @@ import lila.db.ByteArray
|
|||
|
||||
object BinaryFormat {
|
||||
|
||||
object clock {
|
||||
|
||||
def write(clock: Clock): ByteArray = ByteArray {
|
||||
def time(seconds: Float) = writeSignedInt24((seconds * 100).toInt)
|
||||
def timer(seconds: Double) = writeLong40((seconds * 100).toLong)
|
||||
Array(writeInt8(clock.limit), writeInt8(clock.increment)) ++
|
||||
time(clock.whiteTime) ++
|
||||
time(clock.blackTime) ++
|
||||
timer(clock.timerOption getOrElse 0d) map (_.toByte)
|
||||
}
|
||||
|
||||
def read(ba: ByteArray): Color => Clock = color ⇒ ba.value map toInt match {
|
||||
case Array(b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13) ⇒
|
||||
readLong40(b9, b10, b11, b12, b13) match {
|
||||
case 0 ⇒ PausedClock(
|
||||
color = color,
|
||||
limit = b1,
|
||||
increment = b2,
|
||||
whiteTime = readSignedInt24(b3, b4, b5).toFloat / 100,
|
||||
blackTime = readSignedInt24(b6, b7, b8).toFloat / 100)
|
||||
case timer ⇒ RunningClock(
|
||||
color = color,
|
||||
limit = b1,
|
||||
increment = b2,
|
||||
whiteTime = readSignedInt24(b3, b4, b5).toFloat / 100,
|
||||
blackTime = readSignedInt24(b6, b7, b8).toFloat / 100,
|
||||
timer = timer.toDouble / 100)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object castleLastMoveTime {
|
||||
|
||||
def write(clmt: CastleLastMoveTime): ByteArray = {
|
||||
|
@ -43,8 +74,7 @@ object BinaryFormat {
|
|||
to ← posAt((b2 & 63) >> 3, b2 & 7)
|
||||
if from != to
|
||||
} yield from -> to,
|
||||
lastMoveTime = Some((b3 << 16) + (b4 << 8) + b5) filter (0 !=)
|
||||
)
|
||||
lastMoveTime = readInt24(b3, b4, b5).some filter (0 !=))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,4 +131,32 @@ object BinaryFormat {
|
|||
}
|
||||
|
||||
@inline private def toInt(b: Byte): Int = b & 0xff
|
||||
|
||||
def writeInt8(int: Int) = math.min(255, int)
|
||||
|
||||
private val int24Max = math.pow(2, 24).toInt
|
||||
def writeInt24(int: Int) = {
|
||||
val i = math.min(int24Max, int)
|
||||
Array(i >> 16, (i >> 8) & 255, i & 255)
|
||||
}
|
||||
def readInt24(b1: Int, b2: Int, b3: Int) = (b1 << 16) + (b2 << 8) + b3
|
||||
|
||||
private val int23Max = math.pow(2, 23).toInt
|
||||
def writeSignedInt24(int: Int) = {
|
||||
val i = math.abs(math.min(int23Max, int))
|
||||
val j = if (int < 0) i + int23Max else i
|
||||
Array(j >> 16, (j >> 8) & 255, j & 255)
|
||||
}
|
||||
def readSignedInt24(b1: Int, b2: Int, b3: Int) = {
|
||||
val i = (b1 << 16) + (b2 << 8) + b3
|
||||
if (i > int23Max) int23Max - i else i
|
||||
}
|
||||
|
||||
private val long40Max = math.pow(2, 40).toLong
|
||||
def writeLong40(long: Long) = {
|
||||
val i = math.min(long40Max, long)
|
||||
Array(i >> 32, (i >> 24) & 255, (i >> 16) & 255, (i >> 8) & 255, i & 255) map (_.toInt)
|
||||
}
|
||||
def readLong40(b1: Int, b2: Int, b3: Int, b4: Int, b5: Int) =
|
||||
(b1.toLong << 32) + (b2 << 24) + (b3 << 16) + (b4 << 8) + b5
|
||||
}
|
||||
|
|
|
@ -434,8 +434,8 @@ object Game {
|
|||
id -> o.id,
|
||||
token -> o.token,
|
||||
players -> List(
|
||||
(_: Color) => o.whitePlayer,
|
||||
(_: Color) => o.blackPlayer),
|
||||
(_: Color) ⇒ o.whitePlayer,
|
||||
(_: Color) ⇒ o.blackPlayer),
|
||||
binaryPieces -> o.binaryPieces,
|
||||
status -> o.status.id,
|
||||
turns -> o.turns,
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package lila.game
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
import chess.Clock
|
||||
import org.specs2.mutable._
|
||||
import org.specs2.specification._
|
||||
|
||||
import lila.db.ByteArray
|
||||
|
||||
class BinaryClockTest extends Specification {
|
||||
|
||||
val _0_ = "00000000"
|
||||
def write(c: Clock): List[String] =
|
||||
(BinaryFormat.clock write c).toString.split(',').toList
|
||||
def read(bytes: List[String]): Clock =
|
||||
(BinaryFormat.clock read ByteArray.parseBytes(bytes))(chess.White)
|
||||
def isomorphism(c: Clock): Clock =
|
||||
(BinaryFormat.clock read (BinaryFormat.clock write c))(chess.White)
|
||||
|
||||
"binary Clock" should {
|
||||
val clock = Clock(2, 2)
|
||||
val bits22 = List("00000010", "00000010")
|
||||
"write" in {
|
||||
write(clock) must_== {
|
||||
bits22 ::: List.fill(11)(_0_)
|
||||
}
|
||||
write(clock.giveTime(chess.White, 0.03f)) must_== {
|
||||
bits22 ::: List("10000000", "00000000", "00000011") ::: List.fill(8)(_0_)
|
||||
}
|
||||
write(clock.giveTime(chess.White, -0.03f)) must_== {
|
||||
bits22 ::: List("00000000", "00000000", "00000011") ::: List.fill(8)(_0_)
|
||||
}
|
||||
}
|
||||
"read" in {
|
||||
read(bits22 ::: List.fill(11)(_0_)) must_== {
|
||||
clock
|
||||
}
|
||||
read(bits22 ::: List("10000000", "00000000", "00000011") ::: List.fill(8)(_0_)) must_== {
|
||||
clock.giveTime(chess.White, 0.03f)
|
||||
}
|
||||
read(bits22 ::: List("00000000", "00000000", "00000011") ::: List.fill(8)(_0_)) must_== {
|
||||
clock.giveTime(chess.White, -0.03f)
|
||||
}
|
||||
}
|
||||
"isomorphism" in {
|
||||
|
||||
isomorphism(clock) must_== clock
|
||||
|
||||
val c2 = clock.giveTime(chess.White, 15)
|
||||
isomorphism(c2) must_== c2
|
||||
|
||||
val c3 = clock.giveTime(chess.Black, 5)
|
||||
isomorphism(c3) must_== c3
|
||||
|
||||
val c4 = clock.run
|
||||
isomorphism(c4).timerOption.get must beCloseTo(c4.timerOption.get, 1)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue