Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use akka 2.6.5 and korolev 0.15.1 #2

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
17 changes: 15 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
target
dist/*
target/
lib_managed/
src_managed/
project/boot/
project/plugins/project/
.history
.cache
.lib/
.idea
*.iml
.bloop*
.metals*
*.db
*.log
.idea
*.iml
18 changes: 18 additions & 0 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
version = "2.2.1"

style = defaultWithAlign

docstrings = ScalaDoc

align = more

maxColumn = 120
rewrite.rules = [RedundantParens, SortImports, PreferCurlyFors]
unindentTopLevelOperators = true
align.tokens = [{code = "=>", owner = "Case"}]
align.openParenDefnSite = false
align.openParenCallSite = false
optIn.breakChainOnFirstMethodDot = false
optIn.configStyleArguments = false
danglingParentheses = false
spaces.inImportCurlyBraces = true
8 changes: 4 additions & 4 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
val akkaVersion = "2.5.26"
val korolevVersion = "0.14.0"
val akkaVersion = "2.6.5"
val korolevVersion = "0.15.1"
val commonSettings = Seq(
scalacOptions ++= Seq("-Yrangepos", "-deprecation"),
organization := "com.tenderowls",
version := "1.0.0-SNAPSHOT",
scalaVersion := "2.13.1"
scalaVersion := "2.13.2"
)

lazy val match3 = project
Expand Down Expand Up @@ -37,7 +37,7 @@ lazy val client = project
dockerUpdateLatest := true,
normalizedName := "match3-client",
libraryDependencies ++= Seq(
"com.github.fomkin" %% "korolev-server-akkahttp" % korolevVersion,
"com.github.fomkin" %% "korolev-akka" % korolevVersion,
"org.slf4j" % "slf4j-simple" % "1.7.+"
)
)
Expand Down
163 changes: 66 additions & 97 deletions client/src/main/scala/com/tenderowls/match3/client/Application.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,23 @@ import com.tenderowls.match3._
import com.tenderowls.match3.client.components.BoardComponent
import com.tenderowls.match3.client.components.BoardComponent.Rgb
import com.tenderowls.match3.server.actors.LobbyActor
import com.tenderowls.match3.server.data.{ColorCell, PlayerInfo, Score}
import korolev.akkahttp._
import korolev.execution._
import com.tenderowls.match3.server.data.{ ColorCell, PlayerInfo, Score }
import scala.concurrent.ExecutionContext.Implicits.global
import korolev.server._
import korolev.state.javaSerialization._
import levsha.dsl._
import levsha.dsl.html._

import korolev.akka._
import scala.concurrent.Future
import scala.concurrent.duration._
import scala.util.Random
import korolev.akka.AkkaHttpServerConfig

object Application extends App {

import State.globalContext._

private implicit val actorSystem = ActorSystem("match3", defaultExecutionContext = Some(defaultExecutor))
private implicit val materializer: ActorMaterializer = ActorMaterializer()
private implicit val actorSystem = ActorSystem("match3")
private implicit val askTimeout: Timeout = 1.second
private implicit val akkaScheduler: actor.Scheduler = actorSystem.scheduler

Expand Down Expand Up @@ -67,9 +66,10 @@ object Application extends App {
head = { _ =>
Seq(
link(href := "static/main.css", rel := "stylesheet", `type` := "text/css"),
meta(name :="viewport", content := "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"),
script(language := "javascript", src := "static/gestures.js")
)
meta(
name := "viewport",
content := "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"),
script(language := "javascript", src := "static/gestures.js"))
},
render = {
case State.Login =>
Expand All @@ -83,121 +83,97 @@ object Application extends App {

optimize {
body(
div(display @= "flex",
div(
display @= "flex",
alignItems @= "center",
flexDirection @= "column",
h3(textAlign @= "center", "Multiplayer match-three"),
h6(textAlign @= "center", fontStyle @= "italic",
h6(
textAlign @= "center",
fontStyle @= "italic",
"Written in Scala and Korolev by Aleksey Fomkin",
a(fontStyle @= "italic", display @= "block", href := "https://github.com/tenderowls/match3", "https://github.com/tenderowls/match3")
),
form(clazz := "panel", marginTop @= "15px", display @= "flex",
a(
fontStyle @= "italic",
display @= "block",
href := "https://github.com/tenderowls/match3",
"https://github.com/tenderowls/match3")),
form(
clazz := "panel",
marginTop @= "15px",
display @= "flex",
input(nameInputId, `type` := "text", placeholder := "Your nickname"),
button("Enter lobby"),
event("submit")(onSubmit)
)
)
)
event("submit")(onSubmit))))
}
case State.LoggedIn(name, State.YouWin) =>
optimize {
body(
div(clazz := "panel",
h2("You win! ❤️"),
enterLobbyButton(name)
)
)
body(div(clazz := "panel", h2("You win! ❤️"), enterLobbyButton(name)))
}

case State.LoggedIn(name, State.YouLose) =>
optimize {
body(
div(clazz := "panel",
h2("You lose. \uD83D\uDCA9"),
enterLobbyButton(name)
)
)
body(div(clazz := "panel", h2("You lose. \uD83D\uDCA9"), enterLobbyButton(name)))
}

case State.LoggedIn(name, State.Draw) =>
optimize {
body(
div(clazz := "panel",
h2("Draw"),
enterLobbyButton(name)
)
)
body(div(clazz := "panel", h2("Draw"), enterLobbyButton(name)))
}

case State.LoggedIn(_, State.Lobby) =>
optimize {
body(
div(clazz := "panel",
div(
clazz := "panel",
h2("Looking for opponent..."),
div(
button(
"Play with bot",
event("click")(_.publish(ClientEvent.PlayWithBot))
)
)
)
)
div(button("Play with bot", event("click")(_.publish(ClientEvent.PlayWithBot))))))
}

case State.LoggedIn(_, State.Game(gameInfo, boardParams)) =>

def moveIndicator(player: PlayerInfo, score: Score) = {
val thisMove = gameInfo.currentPlayer == player
optimize {
div(
clazz := (
if (thisMove) "move-indicator move-indicator__current"
else "move-indicator"
),
if (thisMove) "move-indicator move-indicator__current"
else "move-indicator"
),
div(
display @= "flex",
justifyContent @= "space-between",
player.name,
when(thisMove)(div(gameInfo.timeRemaining.map(s => s.toSeconds.toString)))
),
renderScore(score)
)
when(thisMove)(div(gameInfo.timeRemaining.map(s => s.toSeconds.toString)))),
renderScore(score))
}
}

val board = BoardComponent.create(boardParams) { (access, event) =>
event match {
case BoardComponent.Event.Move(swap) =>
access.publish(ClientEvent.MakeMove(swap))
case BoardComponent.Event.AnimationEnd =>
access.publish(ClientEvent.SyncAnimation)
case BoardComponent.Event.AddScore(score) =>
access.maybeTransition {
case [email protected](_, [email protected](info, _)) if info.currentPlayer == info.you =>
state.copy(state = game.copy(info = info.copy(yourScore = info.yourScore + score)))
case [email protected](_, [email protected](info, _)) if info.currentPlayer == info.opponent =>
state.copy(state = game.copy(info = info.copy(opponentScore = info.opponentScore + score)))
}
}
val board = BoardComponent.create(boardParams) {
(access, event) =>
event match {
case BoardComponent.Event.Move(swap) =>
access.publish(ClientEvent.MakeMove(swap))
case BoardComponent.Event.AnimationEnd =>
access.publish(ClientEvent.SyncAnimation)
case BoardComponent.Event.AddScore(score) =>
access.maybeTransition {
case state @ State.LoggedIn(_, game @ State.Game(info, _)) if info.currentPlayer == info.you =>
state.copy(state = game.copy(info = info.copy(yourScore = info.yourScore + score)))
case state @ State.LoggedIn(_, game @ State.Game(info, _)) if info.currentPlayer == info.opponent =>
state.copy(state = game.copy(info = info.copy(opponentScore = info.opponentScore + score)))
}
}
}

optimize {
body(
delay(1.second) { access =>
access.maybeTransition {
case [email protected](_, game: State.Game) =>
state.copy(state = game.copy(info = game.info.copy(timeRemaining = game.info.timeRemaining.map(_ - 1.second))))
}
},
div(clazz := "game",
moveIndicator(gameInfo.you, gameInfo.yourScore),
board,
moveIndicator(gameInfo.opponent, gameInfo.opponentScore)
)
)
body(delay(1.second) { access =>
access.maybeTransition {
case state @ State.LoggedIn(_, game: State.Game) =>
state.copy(
state = game.copy(info = game.info.copy(timeRemaining = game.info.timeRemaining.map(_ - 1.second))))
}
}, div(clazz := "game", moveIndicator(gameInfo.you, gameInfo.yourScore), board, moveIndicator(gameInfo.opponent, gameInfo.opponentScore)))
}
}
)
})

private val route = akkaHttpService(serviceConfig).apply(AkkaHttpServerConfig())

Expand All @@ -214,21 +190,16 @@ object Application extends App {
} yield ()

optimize {
button(
"Enter lobby",
event("click")(onClick)
)
button("Enter lobby", event("click")(onClick))
}
}

private def renderScore(score: Score): Node = optimize {
div(
score.data.map {
case (colorCell, count) =>
val color = BoardComponent.cellToColor(colorCell)
renderScoreLine(color, 3, count.toDouble / maxScore.toDouble)
}
)
div(score.data.map {
case (colorCell, count) =>
val color = BoardComponent.cellToColor(colorCell)
renderScoreLine(color, 3, count.toDouble / maxScore.toDouble)
})
}

private def renderScoreLine(color: Rgb, h: Int, progress: Double): Node = {
Expand All @@ -241,9 +212,7 @@ object Application extends App {
clazz := "score-bar",
width @= s"${Math.min(progress * 100, 100)}%",
height @= s"${h}px",
backgroundColor @= color.toString
)
)
backgroundColor @= color.toString))
}
}
}
}
Loading