Skip to content

Commit

Permalink
code sent by Alexander Schrei
Browse files Browse the repository at this point in the history
  developed at Scala Coding Session - March 2018
  changed to simple project, import of "org.vaadin.addons" % "vaactor"
  • Loading branch information
otto-ringhofer committed Mar 18, 2018
1 parent 7883f95 commit d31e564
Show file tree
Hide file tree
Showing 7 changed files with 254 additions and 0 deletions.
25 changes: 25 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name := "vaadin-raffle"

version := "0.1"

scalaVersion := "2.12.4"

resolvers ++= Seq(
"vaadin-addons" at "http://maven.vaadin.com/vaadin-addons"
)

val vaadinVersion = "8.3.1"
val akkaVersion = "2.5.11"
libraryDependencies ++= Seq(
"org.vaadin.addons" % "vaactor" % "1.0.2",
"javax.servlet" % "javax.servlet-api" % "3.1.0" % "provided",
"com.vaadin" % "vaadin-server" % vaadinVersion,
"com.vaadin" % "vaadin-client-compiled" % vaadinVersion,
"com.vaadin" % "vaadin-themes" % vaadinVersion,
"com.vaadin" % "vaadin-push" % vaadinVersion,
"com.typesafe.akka" %% "akka-actor" % akkaVersion
)

containerLibs in Jetty := Seq("org.eclipse.jetty" % "jetty-runner" % "9.3.21.v20170918" intransitive())

enablePlugins(JettyPlugin)
1 change: 1 addition & 0 deletions project/build.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sbt.version = 1.1.1
1 change: 1 addition & 0 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "4.0.2")
102 changes: 102 additions & 0 deletions src/main/scala/org/scala_vienna/raffle/RaffleComponent.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package org.scala_vienna.raffle

import org.scala_vienna.raffle.RaffleServer._
import org.vaadin.addons.vaactor.Vaactor.VaactorComponent
import org.vaadin.addons.vaactor.VaactorUI
import com.vaadin.data.provider.{ DataProvider, ListDataProvider }
import com.vaadin.server.Sizeable
import com.vaadin.ui.themes.ValoTheme
import com.vaadin.ui._
import scala.collection.JavaConverters._

class RaffleComponent(override val vaactorUI: VaactorUI, title: String) extends CustomComponent with VaactorComponent {
/** Contains list of chatroom menbers */
val participantsList = new java.util.ArrayList[String]()
val participantsDataProvider: ListDataProvider[String] = DataProvider.ofCollection[String](participantsList)
val participantsPanel: ListSelect[String] = new ListSelect("Raffle Participants", participantsDataProvider) {
setWidth(100, Sizeable.Unit.PIXELS)
}

/** Contains list of messages from chatroom */
//val chatList = new java.util.ArrayList[ChatServer.Statement]()
//val chatDataProvider: ListDataProvider[ChatServer.Statement] = DataProvider.ofCollection[ChatServer.Statement](chatList)
//val chatPanel: Grid[ChatServer.Statement] = new Grid[ChatServer.Statement]("Chat", chatDataProvider) {
// addColumn(d => d.name)
// addColumn(d => d.msg)
// setWidth(400, Sizeable.Unit.PIXELS)
//}

/** Contains username */
val userName = new TextField()

val loginPanel: HorizontalLayout = new HorizontalLayout {
setSpacing(true)
addComponents(
userName,
new Button("Enter Raffle", _ => { RaffleServer.raffleServer ! Subscribe(Client(userName.getValue, self)) })
)
}


/** Contains user interface for login/logout and sending of messages */
val userPanel = new Panel(
new VerticalLayout {
setSpacing(true)
setMargin(true)
addComponents(
new HorizontalLayout {
setSpacing(true)
addComponents(loginPanel)
})
}
)

val startButton = new Button("Start", _ => { RaffleServer.raffleServer ! StartRaffle })

val winnerLabel: Label = new Label {
setValue("Winner: ")
addStyleName(ValoTheme.LABEL_H2)
}

startButton.setVisible(false)

setCompositionRoot(new VerticalLayout {

addComponents(
new Label {
setValue(title)
addStyleName(ValoTheme.LABEL_H1)
},
new HorizontalLayout {
setSpacing(true)
addComponents(
new VerticalLayout {
setSpacing(true)
addComponents(userPanel)
},
participantsPanel)
},
winnerLabel,
startButton)
})


/** Receive function, is called in context of VaadinUI (via ui.access) */
override def receive: PartialFunction[Any, Unit] = {
// User entered chatroom, update member list
case Enter(participants) =>

participantsList.clear()
participantsList.addAll(participants.asJava)
participantsDataProvider.refreshAll()

case SubscriptionFailure(error) =>
Notification.show(error, Notification.Type.WARNING_MESSAGE)

case YouAreCoordinator => startButton.setVisible(true)

case Result(name) => {
winnerLabel.setValue(s"Winner: $name")
}
}
}
88 changes: 88 additions & 0 deletions src/main/scala/org/scala_vienna/raffle/RaffleServer.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package org.scala_vienna.raffle

import org.vaadin.addons.vaactor.VaactorServlet

import akka.actor.{ Actor, ActorRef, Props }

import scala.util.Random

object RaffleServer {

/** Clients handled by chat room
*
* @param name name of user
* @param actor actorref for communication
*/
case class Client(name: String, actor: ActorRef)

/** Subscribe client to chatroom, processed by chatroom
*
* @param client enters chatroom
*/
case class Subscribe(client: Client)

case class SubscriptionSuccess(name: String)

case class SubscriptionFailure(error: String)

case class SubscriptionCancelled(name: String)

case class Participants(names: Seq[String])

case class Enter(participants: List[String])

case object YouAreCoordinator

case object StartRaffle

case class Result(name: String)


case object RequestMembers

/** ActoRef of chatroom actor */
val raffleServer: ActorRef = VaactorServlet.system.actorOf(Props[ServerActor], "raffleServer")

/** Actor handling chatroom */
class ServerActor extends Actor {

// List of participants
private var participants = Map.empty[String, Client]

/** Process received messages */
def receive: Receive = {
// Subscribe from client
case Subscribe(client) =>
// no name, reply with failure
if (client.name.isEmpty)
sender ! SubscriptionFailure("Empty name not valid")
// duplicate name, reply with failure
else if (participants.contains(client.name))
sender ! SubscriptionFailure(s"Name '${ client.name }' already subscribed")
// add client to chatroom, reply with success, brodcast Enter to clients
else {
if (client.name == "stevan") {
sender ! YouAreCoordinator
}
participants += client.name -> client
//sender ! SubscriptionSuccess(client.name)
broadcast(Enter(participants.keys.toList))
}
case StartRaffle => {
val winner = Random.nextInt(participants.size)
broadcast(Result(participants.keys.toSeq(winner)))
}
// RequestMembers from client, send member list to sending client
//case RequestMembers =>
// sender ! Participants(participants.keySet.toList)
}

/** Send message to every client in chatroom
*
* @param msg message
*/
def broadcast(msg: Any): Unit = participants foreach { _._2.actor ! msg }

}

}
19 changes: 19 additions & 0 deletions src/main/scala/org/scala_vienna/raffle/RaffleServlet.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.scala_vienna.raffle

import javax.servlet.annotation.WebServlet

import org.vaadin.addons.vaactor.VaactorServlet
import com.vaadin.annotations.VaadinServletConfiguration

/** Define servlet, url pattern and ui-class to start
*
*/
@WebServlet(
urlPatterns = Array("/*"),
asyncSupported = true
)
@VaadinServletConfiguration(
productionMode = false,
ui = classOf[RaffleUI]
)
class RaffleServlet extends VaactorServlet
18 changes: 18 additions & 0 deletions src/main/scala/org/scala_vienna/raffle/RaffleUI.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.scala_vienna.raffle

import org.vaadin.addons.vaactor.VaactorUI
import com.vaadin.annotations.Push
import com.vaadin.server.VaadinRequest
import com.vaadin.shared.communication.PushMode
import com.vaadin.shared.ui.ui.Transport

@Push(
value = PushMode.AUTOMATIC,
transport = Transport.WEBSOCKET
)
class RaffleUI extends VaactorUI {

override def init(request: VaadinRequest): Unit =
setContent(new RaffleComponent(this, "Vaactor raffle"))

}

0 comments on commit d31e564

Please sign in to comment.