Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
.idea/
target/
.bloop/
.metals/
metals.sbt
.vscode/settings.json
7 changes: 4 additions & 3 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
version = "3.0.5"
align.openParenCallSite = false
danglingParentheses = true
danglingParentheses.preset = true
maxColumn = 100
project.git = true
# project.git = true
rewrite.rules = [RedundantBraces, RedundantParens, SortImports, PreferCurlyFors]
docstrings = JavaDoc
# docstrings = JavaDoc
85 changes: 39 additions & 46 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,7 @@ name := "taklib"

lazy val commonSettings = Seq(
version := "0.2.0",
scalaVersion := "2.12.1",
scalacOptions ++= Seq(
"-deprecation",
"-encoding", "UTF-8", // yes, this is 2 args
"-feature",
"-unchecked",
"-Xfatal-warnings",
"-Xlint",
"-Yno-adapted-args",
// "-Ywarn-dead-code", // N.B. doesn't work well with the ??? hole
"-Ywarn-numeric-widen",
"-Ywarn-value-discard",
"-Ywarn-unused",
"-Ywarn-unused-import",
"-Xfuture",
"-Ypartial-unification"
)
scalaVersion := "2.13.8"
)

lazy val taklib = (project in file("taklib"))
Expand All @@ -34,54 +18,63 @@ lazy val opentak = (project in file("opentak"))
.settings(commonSettings, name := "opentak")

// Remove these options in 'sbt console' because they're not nice for interactive usage
scalacOptions in (taklib, Compile, console) ~= (_.filterNot(Set("-Xfatal-warnings", "-Ywarn-unused-import").contains))
scalacOptions in (takcli, Compile, console) ~= (_.filterNot(Set("-Xfatal-warnings", "-Ywarn-unused-import").contains))
scalacOptions in (tpsserver, Compile, console) ~= (_.filterNot(Set("-Xfatal-warnings", "-Ywarn-unused-import").contains))
scalacOptions in (opentak, Compile, console) ~= (_.filterNot(Set("-Xfatal-warnings", "-Ywarn-unused-import").contains))
scalacOptions in (taklib, Compile, console) ~= (_.filterNot(
Set("-Xfatal-warnings", "-Ywarn-unused-import").contains
))
scalacOptions in (takcli, Compile, console) ~= (_.filterNot(
Set("-Xfatal-warnings", "-Ywarn-unused-import").contains
))
scalacOptions in (tpsserver, Compile, console) ~= (_.filterNot(
Set("-Xfatal-warnings", "-Ywarn-unused-import").contains
))
scalacOptions in (opentak, Compile, console) ~= (_.filterNot(
Set("-Xfatal-warnings", "-Ywarn-unused-import").contains
))

resolvers += Resolver.sonatypeRepo("releases")

val catsVersion = "0.9.0"
val parserCombinators = "org.scala-lang.modules" %% "scala-parser-combinators" % "1.0.5"
val catsVersion = "2.7.0"
val parserCombinators = "org.scala-lang.modules" %% "scala-parser-combinators" % "2.1.0"
val dependencies = Seq(
"org.typelevel" %% "cats" % catsVersion,
"org.typelevel" %% "cats-core" % catsVersion,
parserCombinators,
"org.scala-graph" %% "graph-core" % "1.11.4"
"org.scala-graph" %% "graph-core" % "1.13.4"
)
val testDependencies = Seq(
"org.scalatest" %% "scalatest" % "3.0.1" % "test",
"org.scalacheck" %% "scalacheck" % "1.13.4" % "test",
"com.ironcorelabs" %% "cats-scalatest" % "2.2.0" % "test"
"org.scalatest" %% "scalatest" % "3.2.11" % "test",
"org.scalacheck" %% "scalacheck" % "1.15.4" % "test",
"com.ironcorelabs" %% "cats-scalatest" % "3.1.1" % "test",
"org.typelevel" %% "discipline-core" % "1.4.0" % "test",
"org.typelevel" %% "discipline-scalatest" % "2.0.0",
"org.typelevel" %% "cats-kernel-laws" % catsVersion % "test",
"org.scalatestplus" %% "scalacheck-1-15" % "3.2.11.0" % "test"
)

libraryDependencies in taklib ++= dependencies
libraryDependencies in taklib ++= testDependencies
libraryDependencies in takcli ++= Seq(
"org.typelevel" %% "cats-effect" % "0.2"
taklib / libraryDependencies ++= dependencies
taklib / libraryDependencies ++= testDependencies
takcli / libraryDependencies ++= Seq(
"org.typelevel" %% "cats-effect" % "3.3.5"
)

resolvers in tpsserver += Resolver.sonatypeRepo("snapshots")
val http4sVersion = "0.17.0-M1"
val circeVersion = "0.7.0"
libraryDependencies in tpsserver ++= Seq(
"io.circe" %% "circe-core" % circeVersion,
val http4sVersion = "0.23.10"
val circeVersion = "0.14.1"
tpsserver / libraryDependencies ++= Seq(
"io.circe" %% "circe-core" % circeVersion,
"io.circe" %% "circe-generic" % circeVersion,
"io.circe" %% "circe-parser" % circeVersion,
"io.circe" %% "circe-parser" % circeVersion,
"io.circe" %% "circe-optics" % circeVersion % "test",

"org.http4s" %% "http4s-blaze-server" % http4sVersion,
"org.http4s" %% "http4s-circe" % http4sVersion,
"org.http4s" %% "http4s-dsl" % http4sVersion,
"org.http4s" %% "http4s-circe" % http4sVersion,
"org.http4s" %% "http4s-dsl" % http4sVersion,
"org.http4s" %% "http4s-blaze-client" % http4sVersion % "test",
"org.http4s" %% "http4s-client" % http4sVersion % "test",

"org.http4s" %% "http4s-client" % http4sVersion % "test",
"ch.qos.logback" % "logback-classic" % "1.2.1"
) ++ testDependencies

libraryDependencies in opentak += parserCombinators
libraryDependencies in opentak ++= testDependencies

opentak / libraryDependencies += parserCombinators
opentak / libraryDependencies ++= testDependencies

initialCommands in (taklib, console) += "import com.github.daenyth.taklib._"

coverageEnabled in taklib := true
taklib / coverageEnabled := true
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import com.github.daenyth.taklib.Implicits.RichParsing
import com.github.daenyth.taklib._

import scala.util.parsing.combinator.RegexParsers
import scala.annotation.nowarn

/**
* Playtak protocol encoding/decoding between the wire
* representation (string) and in-library representation (case classes)
*
* See PlaytakCodec#encode and PlaytakCodec#decode
*/
/** Playtak protocol encoding/decoding between the wire representation (string) and in-library
* representation (case classes)
*
* See PlaytakCodec#encode and PlaytakCodec#decode
*/
object PlaytakCodec {
def encode(outgoing: Playtak.Outgoing): String =
Outgoing.encode(outgoing)
Expand All @@ -26,9 +26,8 @@ object PlaytakCodec {

import Playtak.Incoming._

val client: Parser[Client] = "Client" ~ "([A-Za-z-.0-9]{4,15})".r ^^ {
case _ ~ s =>
Client(s)
val client: Parser[Client] = "Client" ~ "([A-Za-z-.0-9]{4,15})".r ^^ { case _ ~ s =>
Client(s)
}

val msg: Parser[String] = """[^\n\r]{1,256}""".r
Expand All @@ -48,9 +47,8 @@ object PlaytakCodec {
def simpleGameMessage[A](str: String, gameMsg: GameNumber => A): Parser[A] =
gameNumber <~ str ^^ gameMsg

val register: Parser[Register] = "Register" ~> username ~ email ^^ {
case username ~ email =>
Register(username, email)
val register: Parser[Register] = "Register" ~> username ~ email ^^ { case username ~ email =>
Register(username, email)
}
val userLogin: Parser[UserLogin] = "Login" ~> username ~ password ^^ {
case username ~ password =>
Expand All @@ -63,7 +61,7 @@ object PlaytakCodec {
val asPlayer = color match {
case "W" => Some(White)
case "B" => Some(Black)
case _ => None
case _ => None
}
Seek(size, time, increment, asPlayer)
}
Expand All @@ -75,7 +73,7 @@ object PlaytakCodec {
val playStone = stoneType match {
case "C" => PlayCapstone(idx)
case "W" => PlayStanding(idx)
case _ => PlayFlat(idx)
case _ => PlayFlat(idx)
}
Place(gameNumber, playStone)
}
Expand All @@ -101,8 +99,8 @@ object PlaytakCodec {
val shout: Parser[Shout] = "Shout" ~> msg ^^ Shout
val joinRoom: Parser[JoinRoom] = "JoinRoom" ~> roomName ^^ JoinRoom
val leaveRoom: Parser[LeaveRoom] = "LeaveRoom" ~> roomName ^^ LeaveRoom
val shoutRoom: Parser[ShoutRoom] = "ShoutRoom" ~> roomName ~ msg ^^ {
case room ~ msg => ShoutRoom(room, msg)
val shoutRoom: Parser[ShoutRoom] = "ShoutRoom" ~> roomName ~ msg ^^ { case room ~ msg =>
ShoutRoom(room, msg)
}
val tell: Parser[Tell] = "Tell" ~> username ~ msg ^^ { case user ~ msg => Tell(user, msg) }
val ping: Parser[Ping.type] = "^PING$".r ^^^ Ping
Expand All @@ -119,21 +117,21 @@ object PlaytakCodec {
def encode(outgoing: Playtak.Outgoing): String = {
import Playtak.Outgoing._
outgoing match {
case Welcome => "Welcome!"
case LoginOrRegisterNow => "Login or Register"
case WelcomeUser(username) => s"Welcome $username"
case ge: GameEvent => encodeGameEvent(ge)
case Shout(username, msg) => s"Shout <$username> $msg"
case RoomJoined(name) => s"Joined room $name"
case RoomLeft(name) => s"Left room $name"
case Welcome => "Welcome!"
case LoginOrRegisterNow => "Login or Register"
case WelcomeUser(username) => s"Welcome $username"
case ge: GameEvent => encodeGameEvent(ge)
case Shout(username, msg) => s"Shout <$username> $msg"
case RoomJoined(name) => s"Joined room $name"
case RoomLeft(name) => s"Left room $name"
case ShoutRoom(name, username, msg) => s"ShoutRoom $name <$username> $msg"
case Tell(username, msg) => s"Tell <$username> $msg"
case Told(username, msg) => s"Told <$username> $msg"
case ServerMessage(msg) => s"Message $msg"
case Error(msg) => s"Error $msg"
case OnlineUsers(count) => s"Online $count"
case NOK => "NOK"
case OK => "OK"
case Tell(username, msg) => s"Tell <$username> $msg"
case Told(username, msg) => s"Told <$username> $msg"
case ServerMessage(msg) => s"Message $msg"
case Error(msg) => s"Error $msg"
case OnlineUsers(count) => s"Online $count"
case NOK => "NOK"
case OK => "OK"
}
}

Expand All @@ -155,10 +153,12 @@ object PlaytakCodec {
s"Game Start $gameNumber $size $whitePlayerusername vs $blackPlayerusername $yourColor"
case Place(gameNumber, playStone) =>
import Stone._
// TODO this is just totally broken
@nowarn
val stoneType = playStone.stone match {
case _: Capstone => "C"
case _: Capstone => "C"
case _: StandingStone => "W"
case _: FlatStone => ""
case _: FlatStone => ""
}
s"Game#$gameNumber P ${playStone.at.name} $stoneType"
case m: Move =>
Expand All @@ -175,7 +175,7 @@ object PlaytakCodec {
case DoubleRoad =>
"R-R" // Not actually supported by playtak or default rules, but different result sets can treat it differently.
case FlatWin(player) => player.fold("0-F", "F-0")
case Draw => "1/2-1/2"
case Draw => "1/2-1/2"
case WinByResignation(player) =>
player.fold("0-1", "1-0") // Again not supported by playtak; this is PTN format
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package com.github.daenyth.opentak.protocol

import com.github.daenyth.opentak.protocol.Playtak.{GameNumber, Username}
import com.github.daenyth.taklib.White
import org.scalatest.{EitherValues, FlatSpec, Matchers}
import org.scalatest.EitherValues
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

class PlaytakCodecTest extends FlatSpec with Matchers with EitherValues {
class PlaytakCodecTest extends AnyFlatSpec with Matchers with EitherValues {
import PlaytakCodec.Incoming._
import Playtak.Incoming._

Expand Down
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version = 0.13.13
sbt.version = 1.6.1
6 changes: 3 additions & 3 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
logLevel := Level.Warn
addSbtPlugin("io.github.davidgregory084" % "sbt-tpolecat" % "0.1.20")

addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.0")
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.9.3")

addSbtPlugin("org.scoverage" % "sbt-coveralls" % "1.1.0")
addSbtPlugin("org.scoverage" % "sbt-coveralls" % "1.3.1")
34 changes: 18 additions & 16 deletions takcli/src/main/scala/com/github/daenyth/takcli/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,24 @@ import com.github.daenyth.taklib._

import scala.io.StdIn
import scala.util.control.NoStackTrace
import cats.syntax.flatMap._
import cats.syntax.applicativeError._
import cats.syntax.all._
import cats.effect.IOApp
import cats.effect.ExitCode

object Main {
object Main extends IOApp {

def main(args: Array[String]): Unit =
def run(args: List[String]): IO[ExitCode] =
mainT
.recoverWith {
case CleanExit => IO(println("Exiting"))
.recoverWith { case CleanExit =>
IO.println("Exiting")
}
.unsafeRunSync()
.as(ExitCode.Success)

def mainT: IO[Unit] = printStartup >> getInitialGame >>= runGameLoop

def getInitialGame: IO[Game] = promptSize.flatMap {
Game.ofSize(_) match {
case scala.Left(err) => IO(println(err)) >> getInitialGame
case scala.Left(err) => IO(println(err)) >> getInitialGame
case scala.Right(game) => IO(game)
}
}
Expand All @@ -45,10 +46,10 @@ object Main {

def printGame(g: Game) = IO {
val nextPlayInfo = g.turnNumber match {
case 1 => "White to play (Black stone)"
case 2 => "Black to play (White stone)"
case 1 => "White to play (Black stone)"
case 2 => "Black to play (White stone)"
case n if n % 2 == 0 => "Black to play"
case _ => "White to play"
case _ => "White to play"
}
println(s"Move ${g.turnNumber} - $nextPlayInfo")
print(pretty(g))
Expand All @@ -61,8 +62,8 @@ object Main {
IO {
print("Game size?\n > ")
StdIn.readInt()
}.recoverWith {
case n: NumberFormatException => IO(println(s"Bad size: $n")) >> promptSize
}.recoverWith { case n: NumberFormatException =>
IO(println(s"Bad size: $n")) >> promptSize
}

def pretty(g: Game): String =
Expand All @@ -75,16 +76,17 @@ object Main {
def promptAction: IO[TurnAction] =
IO(StdIn.readLine("Your Move?\n > "))
.flatMap { input =>
if (input == null) { throw CleanExit } else
if (input == null) { throw CleanExit }
else
PtnParser
.parseEither(PtnParser.turnAction, input)
.fold(
err => IO.raiseError(PtnParseError(err)),
ta => IO.pure(ta)
)
}
.recoverWith {
case PtnParseError(err) => IO(println(s"Bad move: $err")) >> promptAction
.recoverWith { case PtnParseError(err) =>
IO(println(s"Bad move: $err")) >> promptAction
}
}

Expand Down
4 changes: 1 addition & 3 deletions taklib/src/main/scala/com/github/daenyth/taklib/Board.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import com.github.daenyth.taklib.Stone._

import scala.annotation.tailrec
import scala.collection.immutable.IndexedSeq
import cats.syntax.either._
import cats.syntax.monoid._
import cats.instances.vector._
import cats.syntax.all._
import cats.{Eq => Equal}

import scala.util.Try
Expand Down
Loading