Beispiel #1
0
def createGame(request, container, players, templateID):
  """This calls the WarLight.net API to create a game, and then creates the Game rows in the local DB"""
  gameName = ' vs '.join([p.name for p in players])[:50]

  config = getClotConfig()
  apiRetStr = postToApi('/API/CreateGame', json.dumps( { 
                               'hostEmail': config.adminEmail, 
                               'hostAPIToken': config.adminApiToken,
                               'templateID': templateID,
                               'gameName': gameName,
                               'personalMessage': 'Created by the CLOT at http://' + urlparse.urlparse(request.url).netloc,
                               'players': [ { 'token': p.inviteToken, 'team': 'None' } for p in players]
                               }))
  apiRet = json.loads(apiRetStr)

  gid = long(apiRet.get('gameID', -1))
  if gid == -1:
    raise Exception("CreateGame returned error: " + apiRet.get('error', apiRetStr))

  g = Game(lotID=container.lot.key.id(), wlnetGameID=gid, name=gameName)
  g.players = [p.key.id() for p in players]
  g.put()

  #Ensure we update the container with the new game.  The players may already be there, but put them in in case they're not
  container.games.append(g)
  for p in players:
    container.players[p.key.id()] = p

  logging.info("Created game " + str(g.key.id()) + " '" + gameName + "', wlnetGameID=" + str(gid))

  return g
Beispiel #2
0
def checkInProgressGames(container):
  """This is called periodically to look for games that are finished.  If we find a finished game, we record the winner"""

  #Find all games that we think aren't finished
  activeGames = [g for g in container.games if g.winner is None]

  for g in activeGames:
    #call WarLight's GameFeed API so that it can tell us if it's finished or not
    apiret = hitapi('/API/GameFeed?GameID=' + str(g.wlnetGameID), {})
    data = json.loads(apiret)
    state = data.get('state', 'err')
    if state == 'err': raise Exception("GameFeed API failed.  Message = " + data.get('error', apiret))

    if state == 'Finished':
      #It's finished. Record the winner and save it back.
      winner = findWinner(container, data)
      logging.info('Identified the winner of game ' + str(g.wlnetGameID) + ' is ' + unicode(winner))
      g.winner = winner.key.id()
      g.dateEnded = datetime.datetime.now()
      g.put()
    elif state == 'WaitingForPlayers':
      #It's in the lobby still. Check if it's been too long.
      elapsed = datetime.datetime.now() - g.dateCreated
      if not clot.gameFailedToStart(elapsed):
        logging.info("Game " + str(g.wlnetGameID) + " is in the lobby for " + str(elapsed.days) + " days.")
      else:
        logging.info('Game ' + str(g.wlnetGameID) + " is stuck in the lobby. Marking it as a loss for anyone who didn't join and deleting it.")

        #Delete it over at warlight.net so that players know we no longer consider it a real game
        config = getClotConfig()
        deleteRet = postToApi('/API/DeleteLobbyGame', json.dumps( { 
                                     'Email': config.adminEmail, 
                                     'APIToken': config.adminApiToken,
                                     'gameID': g.wlnetGameID }))

        #If the API doesn't return success, just ignore this game on this run. This can happen if the game just started between when we checked its status and when we told it to delete.
        if 'success' not in deleteRet:
          logging.info("DeleteLobbyGame did not return success. Ignoring this game for this run.  Return=" + deleteRet)
        else:
          #We deleted the game.  Mark it as deleted and finished
          g.deleted = True
          g.winner = findWinnerOfDeletedGame(container, data).key.id()
          g.put()

          #Also remove anyone that declines or fails to join from the ladder.  This is important for real-time ladders since we don't want idle people staying in forever, but you may not want this for your situation
          for playerID in [getPlayerByInviteToken(container, p['id']).key.id() for p in data['players'] if p['state'] != 'Playing']:
            if playerID in container.lot.playersParticipating:
              container.lot.playersParticipating.remove(playerID)
              logging.info("Removed " + str(playerID) + " from ladder since they did not join game " + str(g.wlnetGameID))


    else:
      #It's still going.
      logging.info('Game ' + str(g.wlnetGameID) + ' is not finished, state=' + state + ', numTurns=' + data['numberOfTurns'])
Beispiel #3
0
def checkInProgressGames(container):
    """This is called periodically to look for games that are finished.  If we find a finished game, we record the winner"""

    #Find all games that we think aren't finished
    activeGames = [g for g in container.games if g.winner is None]

    for g in activeGames:
        #call WarLight's GameFeed API so that it can tell us if it's finished or not
        apiret = hitapi('/API/GameFeed?GameID=' + str(g.wlnetGameID), {})
        data = json.loads(apiret)
        state = data.get('state', 'err')
        if state == 'err': raise Exception("GameFeed API failed.  Message = " + data.get('error', apiret))
        
        if state == 'Finished':        
            #It's finished. Record the winner and save it back.
            winner = findWinner(container, data)
            logging.info('Identified the winner of game ' + str(g.wlnetGameID) + ' is ' + unicode(winner))
            g.winner = winner.key.id()
            g.dateEnded = datetime.datetime.now()
            g.put()        
        elif state == 'WaitingForPlayers':
            #It's in the lobby still. Check if it's been too long.
            elapsed = datetime.datetime.now() - g.dateCreated
            players = data.get('players', 'err')
            if players == 'err' : raise Exception("GameFeed API failed.  Message = " + data.get('error', apiret))
            
            hasEitherPlayerDeclined = False
            for p in players:
                playerState = p.get('state', 'err')
                if playerState =='err' : raise Exception("GameFeed API failed.  Message = " + data.get('error', apiret)) 
                if playerState == 'Declined':
                    hasEitherPlayerDeclined = True
                    break
            
            if clot.gameFailedToStart(elapsed) or hasEitherPlayerDeclined == True:
                logging.info('Game ' + str(g.wlnetGameID) + " is stuck in the lobby. Marking it as a loss for anyone who didn't join and deleting it.")
            
                #Delete it over at warlight.net so that players know we no longer consider it a real game
                config = getClotConfig()
                deleteRet = postToApi('/API/DeleteLobbyGame', json.dumps( { 
                                             'Email': config.adminEmail, 
                                             'APIToken': config.adminApiToken,
                                             'gameID': g.wlnetGameID }))
                
                #If the API doesn't return success, just ignore this game on this run. This can happen if the game just started between when we checked its status and when we told it to delete.
                if 'success' not in deleteRet:
                    logging.info("DeleteLobbyGame did not return success. Ignoring this game for this run.  Return=" + deleteRet)
                else:
                    #We deleted the game.  Mark it as deleted and finished
                    g.deleted = True
                    g.winner = findWinnerOfDeletedGame(container, data).key.id()
                    g.put()
                    
                    #Also remove anyone that declines or fails to join from the ladder.  This is important for real-time ladders since we don't want idle people staying in forever, but you may not want this for your situation
                    for playerID in [getPlayerByInviteToken(container, p['id']).key.id() for p in data['players'] if p['state'] != 'Playing']:
                        if playerID in container.lot.playersParticipating:
                            container.lot.playersParticipating.remove(playerID)
                            logging.info("Removed " + str(playerID) + " from ladder since they did not join game " + str(g.wlnetGameID))    
            else :
                logging.info("Game " + str(g.wlnetGameID) + " is in the lobby for " + str(elapsed.days) + " days.")    
        else:
            #It's still going.
            logging.info('Game ' + str(g.wlnetGameID) + ' is not finished, state=' + state + ', numTurns=' + data['numberOfTurns'])