Phase I

Create Lottery Project

Create a Lottery project and set-up

~/temp $ smile new Lottery
~/temp $ cd lottery
~/temp/lottery
~/temp/lottery $ sbt
$[Lottery] smile

Load project in IntelliJ(build.sbt) and Eclipse(import k)

Lottery Mongo Module

  • Open Lottery.ksmile in Eclipse.
  • Edit Lottery.ksmile and insert the below content to create a LotteryMongo module
Lottery.ksmile
group lottery {
    mongo-module LotteryMongo at com.metastay.lotterymongo
}
  • $smile
  • In Eclipse refresh to see the LotteryMonogo.kmongo
  • Edit LotteryMongo.kmongo to add a collection.
LotteryMongo.kmongo
collection Lottery {
    property lotteryName:String
    property amount:Int
    property participantList:String*
    property winner:String?
    property open:Boolean
}
  • $compile
  • Write test cases in LotteryMongoTestSuite.scala
LotteryMongoTestSuite.scala
   test("lottery", Tag("lottery")) {
     LotteryWriter().drop()
     val lotteryName = "KarnatakaLotto"
     val row = LotteryRow(lotteryName = lotteryName, amount = 20000, open = true)
     LotteryWriter().save(row);
     assert(LotteryQuery().count == 1)

     //Add Participant
     val q = LotteryQuery().lotteryName.is(lotteryName)
     val u = LotteryUpdate().participantList.addToSet("John")
     LotteryWriter().updateOne(q, u)
     assert(q.findOne.get.participantList.size == 1)

     //Remove Lottery
     //LotteryWriter().remove(q)
     //assert(LotteryQuery().count == 0)
   }
  • import com.metastay.lotterymongo.lottery._
  • Run Test
    • $project LotteryMongo
    • $test-only com.metastay.lotterymongo.LotteryMongoTestSuite – -n lottery
    • Show the tables in mongochef/robomongo

Lottery Play Module

Building Lottery web-app, to see the list of lotteries, and adding play module to createLottery, addParticipant, runLottery.

Web Reader

First add a data module in Lottery.ksmile to hold data to represent Lottery details. LotteryPlay will use LotteryDetails data, so it depends on LotteryData

group Lottery {
    data-module LotteryData at com.metastay.lottery
    mongo-module LotteryMongo at com.metastay.lotterymongo
    play-module LotteryPlay(LotteryData, LotteryMongo) at lotteryplay
}
  • $smile
  • LotteryData.kdata add a Lottery
data Lottery ( lotteryName:String, amount:Int, participantList:String*, winner:String?,  status:String)
  • add web-reader to LotteryPlay.kplay
web-reader Lottery {
    view lotteryList (GET){
        output(lotteryName:String, amount:Int, participantList:String*, winner:String?, status:String)*
    }
    view lotteryDetails (GET){
        input(lotteryName:String)
        output(LotteryData::Lottery)
    }
}
  • $compile
  • Implement LotteryWebReaderCode.lotteryList
override def lotteryList: Request[LotteryListView.Input] => List[LotteryListView.Output] = {
  import LotteryListView._
  request: Request[Input] =>
    val input = request.body;
    LotteryQuery().find.map(
    row =>
      LotteryListView.Output(
        lotteryName = row.lotteryName,
        amount = row.amount,
        participantList =  row.participantList,
        status = if(row.open)  "OPEN" else "CLOSED",
        winner = row.winner
      )
    )
}
override def lotteryDetails: Request[LotteryDetailsView.Input] => Lottery = {
  import LotteryDetailsView._;
  request: Request[Input] => val input = request.body
    val row = LotteryQuery().lotteryName.is(input.lotteryName).findOne.get

    new Lottery(
      lotteryName = row.lotteryName,
      amount = row.amount,
      participantList =  row.participantList,
      status = if (row.open) "OPEN" else "CLOSED",
      winner = row.winner
    )
}

Web Writer

  • Create lottery passing parameters like name and amount
  • Add Participant to a lottery by passing the participantName and lottery name to which the participant will be added to.
  • Run lottery which will pick a winner amoung the participant and close the lottery.
  • Add the below code in Lottery.ksmile to create a Play Module and depend on LotteryMongo to access LotteryMongo.
Lottery.ksmile
play-module LotteryPlay(LotteryMongo) at lotteryplay
  • $smile
  • Refresh Eclipse to see the LotteryPlay.kplay
  • Adding createLottery, addParticipant, run POST calls with an url “api”
LotteryPlay.kplay
module LotteryPlay (LotteryPlay)
route "api"

web-writer Lottery {
    action createLottery(POST) {
        input(lotteryName: String, amount: Int)
    }

    action addParticipant(POST) {
        input(lotteryName: String, participantName:String)
    }

    action run(POST) {
        input(lotteryName: String)
    }
}
  • $compile
  • Implement the code to LotteryWebWriterCode.scala
LotteryWebWriterCode.scala
   import com.metastay.lotterymongo.lottery._
   object LotteryWebWriterCode extends LotteryWebWriterTrait {


     override def createLottery: Request[CreateLotteryAction.Input] => Result = {
       import CreateLotteryAction._
       request: Request[Input] =>
         val input = request.body;
         LotteryWriter().save(LotteryRow(lotteryName = input.lotteryName, amount = input.amount, open = true))
         Ok(s"${input.lotteryName} Lottery Created")
     }

     override def addParticipant: Request[AddParticipantAction.Input] => Result = {
       import AddParticipantAction._;
       request: Request[Input] =>
         val input = request.body;
         val q = LotteryQuery().lotteryName.is(input.lotteryName)
         val u = LotteryUpdate().participantList.addToSet(input.participantName)
         LotteryWriter().updateOne(q, u)
         Ok(s"${input.participantName} has been added to ${input.lotteryName}")
     }


     override def run: Request[RunAction.Input] => Result = {
       import RunAction._
       request: Request[Input] =>
         val input = request.body;
         val q = LotteryQuery().lotteryName.is(input.lotteryName)
         val participantList = q.findOne.get.participantList //To find the participantList
         val winnerIndex = scala.util.Random.nextInt(participantList.size) //To find a winner Index
         val winner = participantList(winnerIndex)
         val u = LotteryUpdate().winner.set(Some(winner)).open.set(false)
         LotteryWriter().updateOne(q, u)
         Ok(s"${winner} has won ${input.lotteryName} Lottery")
     }
   }

Rest api

Expose rest API through Swagger

$[Lottery]add-swagger
$[Lottery] run

Test though swagger