1. Tomoya Chiba
  2. ISreversi

Commits

Tomoya Chiba  committed 943ff3d

refactoring

  • Participants
  • Parent commits 4f7016e
  • Branches master

Comments (0)

Files changed (7)

File app.coffee

View file
 http = require("http")
 path = require("path")
 ReversiServer = require("./controllers/reversi-server")
+SocketIOConnector = require("./controllers/socketio-connector")
 
 app = express()
 server = module.exports = http.createServer(app)
   console.log "Express server listening on port " + app.get("port")
 
 revServer = module.exports.revServer = new ReversiServer()
-revServer.start(sioServer.sockets)
+sioConnector = module.exports.sioConnector = new SocketIOConnector(revServer)
+sioConnector.start(sioServer.sockets)
 

File client/reversi-client.coffee

View file
     @canvas.save
 
   beginKeyWait: () -> canKeyWait = true
-  stopKeyWait: () -> canKeyWait = false
+  stopKeyWait: () -> 
+    setTimeout(@beginKeyWait, 5000)
+    canKeyWait = false
 
 class ReversiClient
 
 
   sendCommand: (px, py) ->
     console.log "put: (x: #{px}, y: #{py})"
-    @socket.emit('game board put', {x: px, y: py})
+    @socket.emit('game move', {x: px, y: py})
 
   updateLog: (update) ->
     html = "<p>#{if update.color == ReversiRule.black then "black" else "white" }: "
     html += "(#{update.point.x}, #{update.point.y})</p>"
-    # update.revPoints.forEach (v) ->
-    #   html += "<li>(#{v.x}, #{v.y})</li>"
-    # html += "</p>"
-    # console.log html
     $(html).hide().prependTo('#chatlog').slideDown()
 
   _updateCallback: (res) ->
     revClient.mouseEventOff()
     revClient = null
 
-  socket.on 'game result', (res) ->
+  socket.on 'game end', (res) ->
     html = "<p>-- game end --</p>"
     $(html).hide().prependTo('#chatlog').slideDown()
-    html = "<p>#{res.result}, black: #{res.black}, white: #{res.white}</p>"
+    html = "<p>#{res.issue}, black: #{res.black}, white: #{res.white}</p>"
     $(html).hide().prependTo('#chatlog').slideDown()
     revClient.mouseEventOff()
     revClient = null
 
-  socket.on 'game turn', (color) ->
-    html = "<p>Your Turn: #{if color == ReversiRule.black then 'black' else 'white'}</p>"
+  socket.on 'game turn', (res) ->
+    html = "<p>Your Turn: #{if res.color == ReversiRule.black then 'black' else 'white'}</p>"
     $(html).hide().prependTo('#chatlog').slideDown()
 
-  socket.on 'response roomlist', (res) ->
+  socket.on 'roomlist', (res) ->
     for idx, val of res
       html = "<p>#{val.name}: #{val.players}</p>"
       $(html).hide().prependTo('#chatlog').slideDown()
 
-  socket.on 'game board update', (res) ->
+  socket.on 'game update', (res) ->
     console.log res
     return unless revClient
     revClient._updateCallback(res)
     revClient.updateLog(res)
 
-  socket.on 'game board submitted', () ->
+  socket.on 'move submitted', () ->
     revClient._submittedCallback() if revClient
 
   $('#loginRoom').on 'submit', ->

File controllers/reversi-server.coffee

View file
     console.log "players: #{@players} (length: #{@players.length})"
     if (idx = @players.indexOf(username)) >= 0
       @players.splice(idx, 1)
-      console.log "players: #{@players} (length: #{@players.length})"
+      console.log "removed:: players: #{@players} (length: #{@players.length})"
       return true
     false
 
   turnPlayer: () ->
+    return null unless @state == 'game'
     idx = @colors.indexOf(@board.turn)
     if idx > -1 
       @players[idx]
 
   isGameEnd: ->
     @board.isGameEnd()
+
+  gameResult: ->
+    self = @
+
+    result = {}
+    @players.forEach (username) ->
+      result[username] = self.playerResult(username)
+    result
+
+  playerResult: (username) ->
+    userColor = @getColor(username)
+    stone = @board.countStone()
+
+    wl = new Array(2)
+    if stone.white > stone.black
+      wl = ['win', 'lose']
+    else if stone.white < stone.black
+      wl = ['lose', 'win']
+    else
+      wl = ['draw', 'draw']
+
+    idx = [ReversiBoard.white, ReversiBoard.black].indexOf(userColor)
+      
+    result =
+      color: userColor
+      issue: wl[idx]
+      black: stone.black
+      white: stone.white
   
   countStone: ->
     @board.countStone()
   cancelGame: () ->
     @state = 'waiting'
 
-  putStone: (x, y, username) ->
-    return null unless @state == 'game'
-    console.log "putStone x: #{x}, y: #{y}, color: #{@getColor(username)}"
-
-    @board.put(x, y, @getColor(username))
-
   getColor: (username) ->
     idx = @players.indexOf(username)
     return null if idx < 0 || idx > 1
     return null if idx < 0 || idx > 1
     @players[idx]
 
+  move: (username, x, y) ->
+    return null unless @state == 'game'
+    console.log "move x: #{x}, y: #{y}, color: #{@getColor(username)}"
+    update = @board.put(x, y, @getColor(username))
+
+    result =
+      success: update != null
+      update: update
+      gameEnd: @isGameEnd()
+      nextTurnPlayer: @turnPlayer()
+      nextColor: @board.turn
+
   @login: (room, username, callback) ->
     if !room then room = new ReversiRoom
-    success = room._addUser(username)
+    status =
+      success: room._addUser(username)
+      gameStart: room.startGame()
+      nextTurnPlayer: room.turnPlayer()
+      nextColor: room.board.turn if room.board
 
-    if callback then callback(room, success)
+    callback(room, status) if callback
 
   @logout: (room, username, callback) ->
     success = false
+    cancelflag = false
     if room
       success = room._removeUser(username)
-      if room.players.length == 0 then room = undefined
+      cancelflag = true if room.state == 'game'
+      room = undefined if room.players.length == 0
+
+    status = 
+      success: success
+      gameCancel: success && cancelflag
 
-    if callback then callback(room, success)
+    room.cancelGame() if room && status.gameCancel 
+    if callback then callback(room, status)
 
   @states: ['waiting', 'game']
 
 class ReversiServer
   constructor: () ->
     @clearMem()
-    
-  start: (@_sockets) ->
-    self = @
-
-    @_sockets.on 'connection', (socket) ->
-      self._userStates[socket.id] = state: 'waiting'
 
-      socket.on 'room login', (name) ->
-        console.log "received/login: #{name}, id: #{socket.id}"
-        self.performLogin(name, socket)
+  clearMem: ->
+    @_roomList = {}
+    @_userInfo = {}
+    @_connectors = []
 
-      socket.on 'room logout', () ->
-        console.log "received/logout (id: #{socket.id})"
-        self.performLogout(socket)
+  userInfo: (username) ->
+    @_userInfo[username]
+  
+  roomInfo: (roomname) ->
+    @_roomList[roomname]
  
-      socket.on 'disconnect', ->
-        if self._userStates[socket.id].state == 'login'
-          console.log "automatically logout: #{socket.id}"
-          self.performLogout(socket)
+  connectors: ->
+    @_connectors
 
-      socket.on 'game board put', (pt) ->
-        room = self._userStates[socket.id].room
-        color = if room then room.getColor(socket.id) else null
-        console.log "put: #{pt.x}, #{pt.y}, #{color}"
-        self.performPutStone(pt.x, pt.y, socket)
+  registerConnector: (connector) ->
+    @_connectors.push connector
 
-      socket.on 'request roomlist', () ->
-        socket.emit('response roomlist', self.genRoomListForMsg())
+  register: (username, client, connector, options) ->
+    @_userInfo[username] =
+      state: {type: 'waiting'}
+      client: client
+      connector: connector
+      options: options
 
-  clearMem: ->
-    @_roomList = {}
-    @_userStates = {}
-
-  performLogin: (name, socket) ->
+  login: (username, roomname) ->
     self = @
-    usrst = @_userStates[socket.id]
-    return if usrst && usrst.state == 'login'
-
-    ReversiRoom.login @_roomList[name], socket.id, (room, success) ->
-      self._roomList[name] = room
-
-      if success
-        console.log "done/login room: #{name}, id: #{socket.id}"
-        socket.join(name)
-        self._sockets.emit('notice login',
-          username: ReversiServer.socketidMask socket.id
-          roomname: name
-        )
-        self._userStates[socket.id] =
-          state: 'login'
-          room: room
-          roomname: name
-
-        if room.startGame()
-          self._sockets.to(name).emit('game standby', name)
-          self.sendTurnNotify(room)
+
+    info = @_userInfo[username]
+    return @fail(username, 'login failed') if info && info.state.type == 'login'
+    maskedName = @maskName(username)
+
+    ReversiRoom.login @_roomList[roomname], username, (room, status) ->
+      self._roomList[roomname] = room
+
+      if status.success
+        self._userInfo[username].state = 
+          type: 'login'
+          roomname: roomname
+        self.requestJoinGroup(username, roomname)
+
+        self.requestNoticeAll 'login',
+          username: maskedName
+          roomname: roomname
+
+        if status.gameStart
+          self.requestNoticeToGroup roomname, 'game standby',
+            roomname: roomname
+
+          self.requestNotice status.nextTurnPlayer, 'game turn',
+            color: status.nextColor
+        console.log "done/login room: #{roomname}, id: #{username}"
       else
-        console.log "fault/login room: #{name}, id: #{socket.id}"
+        self.fail(username, 'login failed')
+        console.log "fault/login room: #{roomname}, id: #{username}"
 
-  performLogout: (socket) ->
+  logout: (username) ->
     self = @
 
-    usrst = @_userStates[socket.id]
-    return unless usrst.state == 'login'
-    roomname = usrst.roomname
+    info = @_userInfo[username]
+    unless info && info.state.type == 'login'
+      return self.fail(username, 'logout failed') 
+    maskedName = @maskName(username)
 
-    ReversiRoom.logout @_roomList[roomname], socket.id, (room, success) ->
+    roomname = info.state.roomname
+    ReversiRoom.logout @_roomList[roomname], username, (room, status) ->
       self._roomList[roomname] = room
 
-      if success
-        console.log "done/logout room: #{roomname}, id: #{socket.id}"
-        if room && room.state == 'game'
-          room.cancelGame()
-          self._sockets.to(roomname).emit('game cancel', roomname)
+      if status.success
+        self._userInfo[username].state =
+          type: 'waiting'
 
-        socket.leave(roomname)
-        self._sockets.emit 'notice logout',
-          username: ReversiServer.socketidMask socket.id
+        self.requestNoticeAll 'logout',
+          username: maskedName
           roomname: roomname
 
-        self._userStates[socket.id] =
-          state: 'waiting'
-      else
-        console.log "fault/logout room: #{roomname}, id: #{socket.id}"
- 
-  performPutStone: (x, y, socket) ->
-    usrst = @_userStates[socket.id]
-    console.log usrst.state
-    if usrst.state == 'login'
-      update = usrst.room.putStone(x, y, socket.id)
-      console.log update
-      console.log usrst.roomname
-      @_sockets.to(usrst.roomname).emit('game board update', update) if update
-      if usrst.room.isGameEnd()
-        @performGameEnd(usrst.room)
-      else if update
-        @sendTurnNotify(usrst.room)
-    socket.emit('game board submitted')
-
-  performGameEnd: (room) ->
-    self = @
-    room.countStone()
-    stone = room.countStone()
-    console.log stone
+        if status.gameCancel
+          self.requestNoticeToGroup roomname, 'game cancel',
+            roomname: roomname
 
-    result = new Array(2)
-    if stone.white > stone.black
-      result = ['win', 'lose']
-    else if stone.white < stone.black
-      result = ['lose', 'win']
-    else
-      result = ['draw', 'draw']
-    [ReversiBoard.white, ReversiBoard.black].forEach (e, i) ->
-      self._sockets.socket(room.findUserByColor(e)).emit 'game result', 
-        result: result[i]
-        black: stone.black
-        white: stone.white
+        self.requestLeaveGroup(username, roomname)
+        console.log "done/logout room: #{roomname}, id: #{username}"
 
-  sendTurnNotify: (room) ->
-    @_sockets.socket(room.turnPlayer()).emit('game turn', room.board.turn)
+      else
+        self.fail(username, 'logout failed') 
+        console.log "fault/logout room: #{roomname}, id: #{username}"
+
+  disconnect: (username) -> @logout(username)
+
+  move: (username, x, y) ->
+    info = @_userInfo[username]
+    switch info.state.type 
+      when 'login'
+        roomname = info.state.roomname
+        room = @_roomList[roomname]
+
+        result = room.move(username, x, y)
+
+        if result.success
+          @requestNoticeToGroup roomname, 'game update',
+            result.update
+
+          if result.gameEnd
+            @noticeGameEnd(roomname)
+          else
+            @requestNotice result.nextTurnPlayer, 'game turn',
+              color: result.nextColor
+    @requestNotice username, 'move submitted',
+      success: result.success
+
+  fail: (username, msg) ->
+    @requestNotice username, msg
+
+  noticeGameEnd: (roomname) ->
+    room = @_roomList[roomname]
+    results = room.gameResult()
+    for username, result of results
+      @requestNotice username, 'game end', 
+        result
+
+  requestNoticeAll: (type, data) ->
+    @_connectors.forEach (connector) ->
+      connector.noticeAll(type, data)
+   
+  requestNoticeToGroup: (groupname, type, data) ->
+    @_connectors.forEach (connector) ->
+      connector.noticeToGroup(groupname, type, data)
+
+  requestNotice: (username, type, data) ->
+    cinfo = @findConnectInfo(username)
+    cinfo.connector.notice(cinfo.client, type, data)
+
+  requestJoinGroup: (username, groupname) ->
+    cinfo = @findConnectInfo(username)
+    cinfo.connector.joinGroup(cinfo.client, groupname)
+
+  requestLeaveGroup: (username, groupname) ->
+    cinfo = @findConnectInfo(username)
+    cinfo.connector.leaveGroup(cinfo.client, groupname)
+
+  findConnectInfo: (username) ->
+    client: @_userInfo[username].client
+    connector: @_userInfo[username].connector
+
+  noticeRoomlist: (username) ->
+    roomlist = @genRoomListForMsg()
+    console.log roomlist
+    @requestNotice username, 'roomlist',
+      roomlist: roomlist
 
   genRoomListForMsg: () ->
     for idx, val of @_roomList
-      name: idx
-      players: val.players if val
-      
-  @socketidMask: (str) ->
-    if str.length > 5 then str.slice(0, 4) + "*****" else str
+      if val
+        name: idx
+        players: val.players
+
+  maskName: (username) ->
+    info = @_userInfo[username]
+    if info.options && info.options.maskName
+      ReversiServer.genMaskName(username)
+    else
+      username
+
+  @genMaskName: (str) ->
+    if str.length > 5 then str.slice(0, 5) + "*****" else str
 
 module.exports = ReversiServer
 

File controllers/socketio-connector.coffee

View file
+
+# connector:
+#   need to implement:
+#     joinGroup
+#     leaveGroup
+#     notice
+#     noticeToGroup
+#     noticeAll
+class SocketIOConnector
+  constructor: (@operator) ->
+    @operator.registerConnector(@)
+
+  start: (@_sockets) ->
+    self = @
+    @_sockets.on 'connection', (socket) ->
+      self.connectResponse(socket)
+
+  connectResponse: (socket) ->
+    self = @
+    username = socket.id
+
+    @operator.register username, socket, self,
+      maskName: true
+
+    # self._userStates[socket.id] = state: 'waiting'
+
+    socket.on 'room login', (roomname) ->
+      # console.log "received/login: #{name}, id: #{socket.id}"
+      self.operator.login username, roomname
+
+    socket.on 'room logout', () ->
+      # console.log "received/logout (id: #{socket.id})"
+      self.operator.logout username
+
+    socket.on 'disconnect', ->
+      self.operator.disconnect username
+
+    socket.on 'game move', (pt) ->
+      self.operator.move username, pt.x, pt.y
+
+    socket.on 'request roomlist', () ->
+      self.operator.noticeRoomlist username
+
+  joinGroup: (client, groupname) ->
+    client.join(groupname)
+
+  leaveGroup: (client, groupname) ->
+    client.leave(groupname)
+
+  noticeAll: (type, data) ->
+    @notice(@_sockets, type, data)
+
+  noticeToGroup: (groupname, type, data) ->
+    @notice(@_sockets.to(groupname), type, data)
+
+  notice: (client, type, data) ->
+    switch type
+      when 'login'
+        client.emit 'notice login',
+          username: data.username
+          roomname: data.roomname
+
+      when 'logout'
+        client.emit 'notice logout',
+          username: data.username
+          roomname: data.roomname
+
+      when 'game turn'
+        client.emit 'game turn',
+          color: data.color
+
+      when 'game standby'
+        client.emit 'game standby',
+          name: data.name
+
+      when 'game cancel'
+        client.emit 'game cancel',
+          name: data.name
+
+      when 'game update'
+        client.emit 'game update',
+          data
+          # point: data.point
+          # color: data.color
+          # revPoints: data.revPoints
+          
+      when 'game end'
+        client.emit 'game end',
+          data
+          # color: data.color
+          # issue: data.issue
+          # black: data.black
+          # white: data.white
+
+      when 'roomlist'
+        client.emit 'roomlist',
+          data.roomlist
+
+      when 'move submitted'
+        client.emit 'move submitted',
+          success: data.success
+
+
+
+module.exports = SocketIOConnector
+

File controllers/tcp-server.coffee

View file
+net = require('net')
+
+class TcpConnector
+  constructor: (port) ->
+    server = net.createServer tcpResponse
+    server.listen(port)
+    console.log('listening on port 3000')
+
+  tcpResponse: (client) ->
+    console.log 'server -> tcp server created.'
+
+    client.on 'data', (data) ->
+      console.log "server-> #{data}/ from: #{client.remoteAddress}:#{client.remotePort}"
+      client
+
+    client.on 'close', ->
+      console.log "server-> close connection #{client.remoteAddress}:#{client.remotePort}"
+
+  doCommand: (com, client) ->
+    switch com.command
+      when 'OPEN'
+        username = com.args[0]
+
+        nameSplit = username.split(",") 
+        roomname = if nameSplit.length > 1 then roomname = nameSplit[0] else username
+
+      when 'MOVE'
+        posChar = com.args[0]
+        posCharX = posChar[0]
+        posCharY = posChar[1]
+
+        charParseArr = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
+        
+        charIdx = charParseArr.indexOf(posCharX) + 1
+        pos =
+          x: charIdx
+          y: parseInt(posCharY, 10)
+
+  @parser: (str) ->
+    strArray = str.split(' ')
+
+    command: strArray[0]
+    args: strArray.slice(1)
+
+
+      
+
+      
+      
+

File package.json

View file
   },
   "devDependencies": {
     "mocha": "*",
-    "should": "*",
+    "chai": "*",
     "superagent": "*",
     "socket.io-client": "*"
   }

File test/controllers/reversi-server-test.coffee

View file
-
-app = require('../../app')
-sioServer = app.sioServer
-revServer = app.revServer
-
 ReversiServer = require('../../controllers/reversi-server')
 Reversi = require('../../controllers/reversi')
-io = require('socket.io-client')
-should = require('should')
-request = require('superagent')
-
-options =
-  transports: ['websocket']
-  'force new connection': true
+chai = require('chai')
+chai.should()
 
-socketURL = 'http://localhost:3000'
+class TestConnector
+  constructor: (@operator) ->
+    @operator.registerConnector(@)
 
-gameStandby = (roomName, callback) ->
-  clients = new Array(2)
+  joinGroup: ->
+    @joinfunc.apply(this, arguments) if @joinfunc
 
-  clients[0] = io.connect(socketURL, options)
-  clients[0].on 'connect', ->
-    clients[1] = io.connect(socketURL, options)
-    clients[1].on 'connect', ->
+  leaveGroup: ->
+    @leavefunc.apply(this, arguments) if @leavefunc
 
-      clients[0].on 'game standby', ->
-        clients[1].on 'game standby', ->
-          callback(clients)
+  notice: ->
+    @noticefunc.apply(this, arguments) if @noticefunc
 
-      for i in [0..1]
-        clients[i].emit('room login', roomName)
+  noticeToGroup: ->
+    @noticeToGroupfunc.apply(this, arguments) if @noticeToGroupfunc
 
-turnPlayer = (room, clients) ->
-  tp = room.turnPlayer()
-  for i in [0..clients.length - 1]
-    if clients[i].socket.sessionid == tp
-      return clients[i]
-  return null
-
-notTurnPlayer = (room, clients) ->
-  tp = room.turnPlayer()
-  for i in [0..clients.length - 1]
-    if clients[i].socket.sessionid != tp
-      return clients[i]
-  return null
+  noticeAll: ->
+    @noticeAllfunc.apply(this, arguments) if @noticeAllfunc
 
 describe 'ReversiServer', ->
-  beforeEach ->
-    revServer.clearMem()
-
-  it 'connect', (done) ->
-    client = io.connect(socketURL, options)
-
-    client.on 'connect', ->
-      sid = @socket.sessionid
-
-      revServer._userStates[sid].state.should.equal('waiting')
-      client.disconnect()
-      done()
-
-  it 'login (create room and response)', (done) ->
-    client = io.connect(socketURL, options)
-    roomName = 'testroom'
-
-    client.on 'connect', ->
-      sid = @socket.sessionid
-
-      client.on 'notice login', (msg) ->
-        msg.roomname.should.equal(roomName)
 
-        revServer._userStates[sid].state.
-          should.equal('login')
+  testConnector = null
+  revServer = null
 
-        revServer._userStates[sid].roomname.
-          should.equal(roomName)
-
-        revServer._roomList[roomName].should.exist
-          
-        client.disconnect()
-        done()
-
-      client.emit 'room login', roomName
-
-  it 'login (cannot login duality)', (done) ->
-    client = io.connect(socketURL, options)
-    roomName1 = 'testroomone'
-    roomName2 = 'testroomtwo'
-    count = 0
-
-    client.on 'connect', ->
-      sid = @socket.sessionid
-
-      client.on 'notice login', (msg) ->
-        count++
-        revServer._userStates[sid].state.
-          should.equal('login')
-
-      check = ->
-        count.should.equal 1
-        client.disconnect()
+  beforeEach ->
+    revServer = new ReversiServer()
+    testConnector = new TestConnector(revServer)
+  
+  it 'registerConnector', ->
+    revServer.connectors().length.should.eql(1)
+
+  it 'register', ->
+    username = 'testuser'
+    testClient = 
+      id: "test"
+
+    revServer.register(username, testClient, testConnector)
+
+    info = revServer.userInfo(username)
+
+    info.state.type.should.eql('waiting')
+    info.client.should.eql(testClient)
+    info.connector.should.eql(testConnector)
+
+  describe 'login', ->
+    it 'login (create room and response)', (done) ->
+      username = 'testuser'
+      roomname = 'testroom'
+      testClient = 
+        id: "test"
+
+      testConnector.noticeAllfunc = (type, data) ->
+        type.should.eql 'login'
+        data.username.should.eql username
+        data.roomname.should.eql roomname
         done()
 
-      setTimeout(check, 1000)
-      client.emit 'room login', roomName1
-      client.emit 'room login', roomName2
-
+      revServer.register(username, testClient, testConnector)
+      revServer.login(username, roomname)
 
-  it 'logout (delete room and repsonse)', (done) ->
-    client = io.connect(socketURL, options)
-    roomName = 'testroom-logout'
-
-    client.on 'connect', ->
-      sid = @socket.sessionid
-
-      client.on 'notice login', (msg) ->
-        console.log "login correct: #{msg.roomname}"
-        client.emit 'room logout'
-
-      client.on 'notice logout', (msg) ->
-        msg.roomname.should.equal(roomName)
-
-        revServer._userStates[sid].state.
-          should.equal('waiting')
-
-        should.not.exist(revServer._roomList[roomName])
-
-        console.log "logout correct: #{msg.roomname}"
-        client.disconnect()
-        done()
-
-      client.emit 'room login', roomName
-
-  it 'startGame', (done) ->
-    clients = new Array(3)
-    roomName = 'testroom'
-    sids = new Array(3)
-    gameStates = [false, false, false]
-    
-    checker = (idx) ->
-      clients[idx].on 'game standby', ->
-        gameStates[idx] = true
-
-        if gameStates[0] = true && gameStates[1] = true
-          clients[2].emit('room login', roomName)
-
-      if idx == 0
-        setTimeout(doneCheck, 1800)
-      
-    doneCheck = () ->
-      gameStates[0].should.equal(true)
-      gameStates[1].should.equal(true)
-      gameStates[2].should.equal(false)
-      for i in [0..2]
-        clients[i].disconnect()
-      done()
-
-    clients[0] = io.connect(socketURL, options)
-    clients[0].on 'connect', ->
-      sids[0] = @socket.sessionid
-      checker(0)
-
-      clients[1] = io.connect(socketURL, options)
-      clients[1].on 'connect', ->
-        sids[1] = @socket.sessionid
-        checker(1)
-
-        clients[2] = io.connect(socketURL, options)
-        clients[2].on 'connect', ->
-          sids[2] = @socket.sessionid
-          checker(2)
-
-          clients[0].emit('room login', roomName)
-          clients[1].emit('room login', roomName)
-
-  it 'put Stone', (done) ->
-    roomName = 'testroom2'
-    gameStandby roomName, (clients) ->
-      room = revServer._roomList[roomName]
+    it 'double login', (done) ->
+      username = 'testuser'
+      roomname = 'testroom'
+      roomname2 = 'testroom2'
+      testClient = 
+        id: "test"
       count = 0
 
-      tp = turnPlayer(room, clients)
-
-      clients.forEach (e) ->
-        e.on 'game board update', (res) ->
-          res.point.x.should.equal(3)
-          res.point.y.should.equal(4)
-          res.color.should.equal(Reversi.black)
-          res.revPoints[0].x.should.equal(4)
-          res.revPoints[0].y.should.equal(4)
-          if count++ == 1
-            clients.forEach (e) ->
-              e.disconnect()
-            done()
-
-      tp.emit 'game board put', {x: 3, y: 4}
-
-  it 'turn notify'
-  ###
-    ,(done) ->
-    roomName = 'testroom3'
-    gameStandby roomName, (clients) ->
-      room = revServer._roomList[roomName]
+      testConnector.noticeAllfunc = (type, data) ->
+        type.should.eql 'login'
+        data.username.should.eql username
+        data.roomname.should.eql roomname
+        done() if count++ > 0
+
+      testConnector.noticefunc = (client, type, data) ->
+        client.should.eql testClient
+        type.should.eql 'login failed'
+        done() if count++ > 0
+
+      revServer.register(username, testClient, testConnector)
+      revServer.login(username, roomname)
+      revServer.login(username, roomname2)
+
+  describe 'logout', ->
+    it 'login and logout', (done) ->
+      username = 'testuser'
+      roomname = 'testroom'
+      testClient = 
+        id: "test"
       count = 0
 
-      tp = turnPlayer(room, clients)
-
-      aftercare = ->
-        clients.forEach (e) ->
-          e.disconnect()
-        done()
-
-      clients.forEach (e) ->
-        e.on 'game board update', (res) ->
-          res.point.x.should.equal(3)
-          res.point.y.should.equal(4)
-          res.color.should.equal(Reversi.black)
-          res.revPoints[0].x.should.equal(4)
-          res.revPoints[0].y.should.equal(4)
-          if count++ >= 3
-            aftercare()
-
-        e.on 'game turn', (color) ->
-          console.log color
-          should.fail("must not send when not updated") if dontSend
-          if count++ >= 3
-            aftercare()
-
-      dontSend = true
-      tp.emit 'game board put', {x: 5, y: 5}
-      dontSend = false
-      tp.emit 'game board put', {x: 3, y: 4}
-  ###
-
-  it 'game cancel', (done) ->
-    roomName = 'cancelroom'
-    gameStandby roomName, (clients) ->
+      testConnector.noticeAllfunc = (type, data) ->
+        switch type
+          when 'login'
+            data.username.should.eql username
+            data.roomname.should.eql roomname
+            count++
+          when 'logout'
+            data.username.should.eql username
+            data.roomname.should.eql roomname
+            done() if count++ > 0
+
+      revServer.register(username, testClient, testConnector)
+      revServer.login(username, roomname)
+      revServer.logout(username, roomname)
+    it 'cannot logout before login', (done) ->
+      username = 'testuser'
+      roomname = 'testroom'
+      testClient = 
+        id: "test"
       count = 0
 
-      check = () ->
-        revServer._roomList[roomName].players.length.should.equal(1)
-        clients.forEach (e) ->
-          e.disconnect()
-        done()
-
-      clients.forEach (e) ->
-        e.on 'game cancel', (name) ->
-          name.should.equal(roomName)
-          check() if count++ == 3
+      testConnector.noticefunc = (client, type, data) ->
+        type.should.eql 'logout failed'
+        done() 
 
-        e.on 'notice logout', (msg) ->
-          msg.roomname.should.equal(roomName)
-          check() if count++ == 3
+      revServer.register(username, testClient, testConnector)
+      revServer.logout(username, roomname)
 
-      clients[0].emit 'room logout'
+  describe 'gamestart', ->
+    it 'gamestart', (done) ->
+      usernames = ['testuser1', 'testuser2']
+      roomname = 'testroom'
+      testClients = [{id: "test1"}, {id: "test2"}] 
+      count = 0
 
-      
-  it 'game end', (done) ->
-    roomName = 'gameendroom'
-    gameStandby roomName, (clients) ->
-      room = revServer._roomList[roomName]
+      testConnector.noticeAllfunc = (type, data) ->
+        switch type
+          when 'login'
+            switch data.username
+              when usernames[0]
+                console.log arguments
+                data.roomname.should.be.eql roomname
+                done() if count++ > 2
+              when usernames[1]
+                data.roomname.should.be.eql roomname
+                done() if count++ > 2
+
+      testConnector.noticeToGroupfunc = (groupname, type, data) ->
+        switch type
+          when 'game standby'
+            data.roomname.should.eql roomname
+            done() if count++ > 2
+
+      testConnector.noticefunc = (client, type, data) ->
+        type.should.eql 'game turn'
+        data.color.should.eql Reversi.black
+        done() if count++ > 2
+
+      revServer.register(usernames[0], testClients[0], testConnector)
+      revServer.register(usernames[1], testClients[1], testConnector)
+      revServer.login(usernames[0], roomname)
+      revServer.login(usernames[1], roomname)
+
+    it 'gamecancel', (done) ->
+      usernames = ['testuser1', 'testuser2']
+      roomname = 'testroom'
+      testClients = [{id: "test1"}, {id: "test2"}] 
       count = 0
 
-      check = () ->
-        clients.forEach (e) ->
-          e.disconnect()
+      check = ->
+        room = revServer.roomInfo(roomname)
+        room.state.should.eql 'waiting'
         done()
 
-      clients.forEach (e) ->
-        e.on 'game result', (res) ->
-          console.log res
-          res.black.should.equal(5)
-          res.white.should.equal(0)
-          check() if count++ == 1
-
-        e.on 'game board update', ->
-          console.log room.countStone()
-
-      room.board.board[5][5] = Reversi.black
-      tp = turnPlayer(room, clients)
-      tp.emit 'game board put', {x: 3, y: 4}
-
-
+      testConnector.noticeToGroupfunc = (groupname, type, data) ->
+        switch type
+          when 'game standby'
+            data.roomname.should.eql roomname
+            check() if count++ > 0
+          when 'game cancel'
+            data.roomname.should.eql roomname
+            check() if count++ > 0
+
+      revServer.register(usernames[0], testClients[0], testConnector)
+      revServer.register(usernames[1], testClients[1], testConnector)
+      revServer.login(usernames[0], roomname)
+      revServer.login(usernames[1], roomname)
+      revServer.logout(usernames[0], roomname)
+
+  describe 'move', ->
+    it 'move', (done) ->
+      usernames = ['testuser1', 'testuser2']
+      roomname = 'testroom'
+      testClients = [{id: "test1"}, {id: "test2"}] 
+      count = 0
+      turnCount = 0
+
+      testConnector.noticeToGroupfunc = (groupname, type, data) ->
+        groupname.should.eql(roomname)
+        switch type
+          when 'game standby'
+            data.roomname.should.eql roomname
+            done() if count++ > 1
+          when 'game update'
+            data.point.x.should.eql(3)
+            data.point.y.should.eql(4)
+            data.color.should.eql(Reversi.black)
+            data.revPoints[0].x.should.eql(4)
+            data.revPoints[0].y.should.eql(4)
+            done() if count++ > 1
+
+      testConnector.noticefunc = (client, type, data) ->
+        switch type
+          when 'game turn'
+            if turnCount++ == 0
+              data.color.should.eql Reversi.black
+              idx = if client.id == 'test1' then 0 else 1
+              revServer.move(usernames[idx], 3, 4)
+            else
+              data.color.should.eql Reversi.white
+          when 'move submitted'
+            data.success.should.eql true
+            done() if count++ > 1
+
+      revServer.register(usernames[0], testClients[0], testConnector)
+      revServer.register(usernames[1], testClients[1], testConnector)
+      revServer.login(usernames[0], roomname)
+      revServer.login(usernames[1], roomname)
+
+    it 'gameEnd', (done) ->
+      usernames = ['testuser1', 'testuser2']
+      roomname = 'testroom'
+      testClients = [{id: "test1"}, {id: "test2"}] 
+      count = 0
+      turnCount = 0
+
+      turnPlayer = new Array(2)
+
+      check =  ->
+        if count++ > 1
+          done()
+          # room = revServer.roomInfo(roomname)
+
+      testConnector.noticeToGroupfunc = (groupname, type, data) ->
+        groupname.should.eql(roomname)
+        switch type
+          when 'game update'
+            data.point.x.should.eql(3)
+            data.point.y.should.eql(4)
+            data.color.should.eql(Reversi.black)
+            data.revPoints[0].x.should.eql(4)
+            data.revPoints[0].y.should.eql(4)
+            check()
+
+      testConnector.noticefunc = (client, type, data) ->
+        switch type
+          when 'game turn'
+            if turnCount++ == 0
+              room = revServer.roomInfo(roomname)
+
+              data.color.should.eql Reversi.black
+              turnPlayer[0] = if client.id == 'test1' then 0 else 1
+              turnPlayer[1] = 1 - turnPlayer[0]
+              
+              room.board.board[5][5] = Reversi.black
+              revServer.move(usernames[turnPlayer[0]], 3, 4)
+            else
+              data.color.should.eql Reversi.white
+          when 'game end'
+            switch client.id
+              when testClients[turnPlayer[0]].id
+                data.color.should.eql Reversi.black
+                data.issue.should.eql 'win'
+              when testClients[turnPlayer[1]].id
+                data.color.should.eql Reversi.white
+                data.issue.should.eql 'lose'
+            data.black.should.eql(5)
+            data.white.should.eql(0)
+            check()
+
+      revServer.register(usernames[0], testClients[0], testConnector)
+      revServer.register(usernames[1], testClients[1], testConnector)
+      revServer.login(usernames[0], roomname)
+      revServer.login(usernames[1], roomname)