def matchRequest_create(self, data, sesh): """Match Request (Create) Creates a new match request and notifies the opponent Arguments: data {dict} -- Data sent with the request sesh {Sesh._Session} -- The session associated with the request Returns: Services.Effect """ # Verify fields try: DictHelper.eval(data, ['opponent', 'org']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Find opponent dOpponent = Thrower.get(data['opponent'], raw=['alias']) if not dOpponent: return Services.Effect(error=(1104, 'thrower:%s' % data['opponent'])) # Create a new request try: oRequest = MatchRequest({ "_created": int(time()), "initiator": sesh['thrower']['_id'], "opponent": data['opponent'], "org": data['org'] }) except ValueError as e: return Services.Effect(error=(1001, e.args[0])) # Store the instance if not oRequest.create(): return Services.Effect(error=1100) # Sync the data for anyone listening Sync.push( 'auth', 'requests-%s' % data['opponent'], { "type": 'match_request', "_id": oRequest['_id'], "initiator": sesh['thrower']['_id'], "alias": sesh['thrower']['alias'], "org": data['org'] }) # Return the ID of the new request return Services.Effect(oRequest['_id'])
def matchRequest_update(self, data, sesh): """Match Request (Update) Accepts a match request and creates the match with the proper service, then notifies both throwers of the ID of the new match Arguments: data {dict} -- Data sent with the request sesh {Sesh._Session} -- The session associated with the request Returns: Services.Effect """ # Verify fields try: DictHelper.eval(data, ['id']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Find the request oRequest = MatchRequest.get(data['id']) if not oRequest: return Services.Effect(error=(1104, 'match_request:%s' % data['id'])) # If the accepter is not the opponent if sesh['thrower']['_id'] != oRequest['opponent']: return Services.Effect(error=1000) # Create a new match in the proper service oEffect = Services.create( oRequest['org'].lower(), 'match', { "_internal_": Services.internalKey(), "initiator": oRequest['initiator'], "opponent": oRequest['opponent'] }, sesh) if oEffect.errorExists(): return oEffect # Delete the request oRequest.delete() # Notify the initiator of the new match Sync.push('auth', 'request-%s' % data['id'], { "type": "accepted", "match": oEffect.data }) # Return the ID of the new match return Services.Effect(oEffect.data)
def matchRequest_delete(self, data, sesh): """Match Request (Delete) Refuses a match request and deletes it Arguments: data {dict} -- Data sent with the request sesh {Sesh._Session} -- The session associated with the request Returns: Services.Effect """ # Verify fields try: DictHelper.eval(data, ['id']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Find the request oRequest = MatchRequest.get(data['id']) if not oRequest: return Services.Effect(error=(1104, 'match_request:%s' % data['id'])) # If the deleter is not the initiator or opponent if sesh['thrower']['_id'] != oRequest['initiator'] and \ sesh['thrower']['_id'] != oRequest['opponent']: return Services.Effect(error=1000) # Delete it if not oRequest.delete(): return Services.Effect(error=1102) # If the initiator retracted their request if sesh['thrower']['_id'] == oRequest['initiator']: # Let the opponent know Sync.push('auth', 'requests-%s' % oRequest['opponent'], { "type": "match_request_delete", "id": data['id'] }) # Else the opponent rejected the request else: # Let the initiator know Sync.push('auth', 'request-%s' % data['id'], {"type": "rejected"}) # Return OK return Services.Effect(True)
def match_delete(self, data, sesh): """Match (Delete) Deletes an existing match, can only be done if it's not finished Arguments: data {dict} -- Data sent with the request sesh {Sesh._Session} -- Session associated with the request Returns: Services.Effect """ # Verify fields try: DictHelper.eval(data, ['id']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Get the match dMatch = Match.get(data['id'], raw=['finished', 'initiator', 'opponent']) if not dMatch: return Services.Effect(error=(1104, 'watl_match:%s' % data['id'])) # If the thrower is neither the initiator or opponent, or the match is # already marked finished if (dMatch['initiator'] != sesh['thrower']['_id'] and \ dMatch['opponent'] != sesh['thrower']['_id']) or \ dMatch['finished']: return Services.Effect(error=1000) # Else, attempt to delete the record Match.deleteGet(data['id']) # Notify anyone watching the match Sync.push('watl', 'match-%s' % data['id'], {"type": "deleted"}) # Return OK return Services.Effect(True)
def matchGame_update(self, data, sesh): """Match Game Update Takes a new throw value and stores it, then notifies the opponent Arguments: data {dict} -- Data sent with the request sesh {Sesh._Session} -- Session associated with the request Returns: Services.Effect """ # Verify fields try: DictHelper.eval(data, ['id', 'throw', 'value']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Get the match dMatch = Match.get( data['id'], raw=['finished', 'game_finished', 'initiator', 'opponent']) if not dMatch: return Services.Effect(error=(1104, 'natf_match:%s' % data['id'])) # If the match is already finished if dMatch['finished']: return Services.Effect(error=1002) # Is the thrower the initiator or the opponent? if sesh['thrower']['_id'] == dMatch['initiator']: sIs = 'i' elif sesh['thrower']['_id'] == dMatch['opponent']: sIs = 'o' else: return Services.Effect(error=1000) # If the thrower already marked the match as finished if dMatch['game_finished'][sIs]: return Services.Effect(error=1002) # If the throw is not a valid value if data['throw'] not in [ '1', '2', '3', '4', '5', '6', '7', '8', '9', '10' ]: return Services.Effect(error=(1001, [('throw', 'invalid')])) # Validate the value dStruct = Match.struct() if not dStruct['tree']['game'][sIs][data['throw']].valid( data['value']): return Services.Effect(error=(1001, [('value', 'invalid data.value')])) # If it's throw 5, and clutch is set, but we didn't get 'd', 0, or 7 if data['throw'] in ['5', '10']: if data['value']['killshot'] != '0': if data['value']['value'] not in ['d', 0, 8]: return Services.Effect( error=(1001, [('value', 'invalid data.value.value')])) # Update the throw Match.updateThrow(data['id'], sIs, data['throw'], data['value']) # Notify anyone listening Sync.push( 'watl', 'match-%s' % data['id'], { "type": "throw", "thrower": sIs, "throw": data['throw'], "value": data['value'] }) # Return OK return Services.Effect(True)
def matchFinishGame_update(self, data, sesh): """Match Finish Game Marks the game as finished. If both throwers are finished, calculates if there's a winner or it's a tie Arguments: data {dict} -- Data sent with the request sesh {Sesh._Session} -- Session associated with the request Returns: Services.Effect """ # Verify fields try: DictHelper.eval(data, ['id']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Get the match dMatch = Match.get( data['id'], raw=['finished', 'game_finished', 'initiator', 'opponent']) if not dMatch: return Services.Effect(error=(1104, 'natf_match:%s' % data['id'])) # If the match is already finished if dMatch['finished']: return Services.Effect(error=1002) # Is the thrower the initiator or the opponent? if sesh['thrower']['_id'] == dMatch['initiator']: sIs = 'i' elif sesh['thrower']['_id'] == dMatch['opponent']: sIs = 'o' else: return Services.Effect(error=1000) # If the thrower already marked the match as finished if dMatch['game_finished'][sIs]: return Services.Effect(True) # Update the finished state Match.finishGame(data['id'], sIs) # Fetch the updated data dMatch = Match.get(data['id'], raw=['game', 'game_finished']) # If both sides are done if dMatch['game_finished']['i'] and dMatch['game_finished']['o']: # Calculate the stats dPoints = {"i": 0, "o": 0} for w in ["i", "o"]: for t in ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]: if t in ['5', '10']: if dMatch['game'][w][t]['value'] != 'd': dPoints[w] += dMatch['game'][w][t]['value'] else: if dMatch['game'][w][t] != 'd': dPoints[w] += dMatch['game'][w][t] # If we don't have a winner if dPoints['i'] == dPoints['o']: # Add the overtime section Match.addOvertime(data['id']) # Start overtime mode Sync.push('watl', 'match-%s' % data['id'], { "type": "overtime", "subtype": "start" }) # Else, send back the winner else: # Mark as finished Match.finished(data['id']) # Notify the throwers Sync.push( 'watl', 'match-%s' % data['id'], { "type": "winner", "is": dPoints['i'] > dPoints['o'] and 'i' or 'o' }) # Return OK return Services.Effect(True)
def matchFinishOvertime_update(self, data, sesh): """Match Finish Overtime Marks the overtime part as finished. If both throwers are finished, verifies and notifies if the game is over Arguments: data {dict} -- Data sent with the request sesh {Sesh._Session} -- Session associated with the request Returns: Services.Effect """ # Verify fields try: DictHelper.eval(data, ['id']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Get the match dMatch = Match.get( data['id'], raw=['finished', 'initiator', 'opponent', 'overtime']) if not dMatch: return Services.Effect(error=(1104, 'watl_match:%s' % data['id'])) # If the match is already finished if dMatch['finished']: return Services.Effect(error=1002) # Is the thrower the initiator or the opponent? if sesh['thrower']['_id'] == dMatch['initiator']: sIs = 'i' elif sesh['thrower']['_id'] == dMatch['opponent']: sIs = 'o' else: return Services.Effect(error=1000) # If the thrower already marked the match as finished if dMatch['overtime']['finished'][sIs]: return Services.Effect(True) # Update the finished state Match.finishOvertime(data['id'], sIs) # Fetch the updated data dMatch = Match.get(data['id'], raw=['overtime']) # If both sides are done if dMatch['overtime']['finished'] == {'i': True, 'o': True}: # If the lengths don't match if len(dMatch['overtime']['i']) != len(dMatch['overtime']['o']): # Reset finished Match.finishOvertimeReset(data['id']) # Notify throwers we aren't finished Sync.push('watl', 'match-%s' % data['id'], { "type": "overtime", "subtype": "notfinished" }) # Return failure return Services.Effect(False) # Init the consecutive successes iCons = 0 # Count up until we have a clear winner or loser for i in range(len(dMatch['overtime']['i'])): # If we got a drop, consider it a zero if dMatch['overtime']['i'][i] == 'd': dMatch['overtime']['i'][i] = 0 if dMatch['overtime']['o'][i] == 'd': dMatch['overtime']['o'][i] = 0 # If they aren't the same if dMatch['overtime']['i'][i] != dMatch['overtime']['o'][i]: # Mark as finished Match.finished(data['id']) # Notify throwers Sync.push( 'watl', 'match-%s' % data['id'], { "type": "winner", "is": dMatch['overtime']['i'][i] > dMatch['overtime']['o'][i] and 'i' or 'o' }) # Break out of the loop break # If we didn't get a winner, something is wrong else: # Reset finished Match.finishOvertimeReset(data['id']) # Notify throwers we aren't finished Sync.push('watl', 'match-%s' % data['id'], { "type": "overtime", "subtype": "notfinished" }) # Return failure return Services.Effect(False) # Return OK return Services.Effect(True)
def matchOvertime_update(self, data, sesh): """Match Overtime Takes a new throw for overtime and records it, then notifies the opponent Arguments: data {dict} -- Data sent with the request sesh {Sesh._Session} -- Session associated with the request Returns: Services.Effect """ # Verify fields try: DictHelper.eval(data, ['id', 'throw', 'value']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # If the throw is not an int if not isinstance(data['throw'], int): return Services.Effect(error=(1001, [('throw', 'not an int')])) # If the value is anything other than 'd', 0, or 1 if data['value'] not in ['d', 0, 1]: return Services.Effect(error=(1001, [('value', 'invalid')])) # Get the match dMatch = Match.get( data['id'], raw=['finished', 'initiator', 'opponent', 'overtime']) if not dMatch: return Services.Effect(error=(1104, 'watl_match:%s' % data['id'])) # If the match is already finished if dMatch['finished']: return Services.Effect(error=1002) # Is the thrower the initiator or the opponent? if sesh['thrower']['_id'] == dMatch['initiator']: sIs = 'i' elif sesh['thrower']['_id'] == dMatch['opponent']: sIs = 'o' else: return Services.Effect(error=1000) # If the thrower already marked the section as finished if dMatch['overtime']['finished'][sIs]: return Services.Effect(error=1002) # If the value doesn't exist if len(dMatch['overtime'][sIs]) == data['throw']: dMatch['overtime'][sIs].append(data['value']) # Else, overwrite it else: dMatch['overtime'][sIs][data['throw']] = data['value'] # Store the changes Match.updateOvertime(data['id'], sIs, dMatch['overtime']) # Notify anyone listening Sync.push( 'watl', 'match-%s' % data['id'], { "type": "overtime", "subtype": "throw", "thrower": sIs, "throw": data['throw'], "value": data['value'] }) # Return OK return Services.Effect(True)
def matchFinishBigaxeTarget_update(self, data, sesh): """Match Finish Big Axe Target Marks the target part of big axe as finished. If both throwers are finished, verifies and notifies if the game is over or points should start Arguments: data {dict} -- Data sent with the request sesh {Sesh._Session} -- Session associated with the request Returns: Services.Effect """ # Verify fields try: DictHelper.eval(data, ['id']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Get the match dMatch = Match.get(data['id'], raw=['finished', 'initiator', 'opponent', 'bigaxe']) if not dMatch: return Services.Effect(error=(1104, 'natf_match:%s' % data['id'])) # If the match is already finished if dMatch['finished']: return Services.Effect(error=1002) # Is the thrower the initiator or the opponent? if sesh['thrower']['_id'] == dMatch['initiator']: sIs = 'i' elif sesh['thrower']['_id'] == dMatch['opponent']: sIs = 'o' else: return Services.Effect(error=1000) # If the thrower already marked the match as finished if dMatch['bigaxe']['target']['finished'][sIs]: return Services.Effect(True) # Update the finished state Match.finishBigAxe('target', data['id'], sIs) # Fetch the updated data dMatch = Match.get(data['id'], raw=['bigaxe']) # If both sides are done if dMatch['bigaxe']['target']['finished'] == {'i': True, 'o': True}: # If the lengths don't match if len(dMatch['bigaxe']['target']['i']) != len( dMatch['bigaxe']['target']['o']): # Reset finished Match.finishBigAxeReset('target', data['id']) # Notify throwers we aren't finished Sync.push('natf', 'match-%s' % data['id'], { "type": "bigaxe_target", "subtype": "notfinished" }) # Return failure return Services.Effect(False) # Init the consecutive successes iCons = 0 # Count up until we have a clear winner or loser for i in range(len(dMatch['bigaxe']['target']['i'])): # If both are 0 or drops if (dMatch['bigaxe']['target']['i'][i] == 0 or \ dMatch['bigaxe']['target']['i'][i] == 'd') and \ (dMatch['bigaxe']['target']['o'][i] == 0 or \ dMatch['bigaxe']['target']['o'][i] == 'd'): # Reset the consecutive and continue iCons = 0 # If they're both 1 elif dMatch['bigaxe']['target']['i'][i] == 1 and \ dMatch['bigaxe']['target']['o'][i] == 1: # Increase the consecutive successes iCons += 1 # If it's hit 3 if iCons == 3: # Add the section Match.addBigAxe("points", data['id']) # Notify that we're going to points Sync.push('natf', 'match-%s' % data['id'], { "type": "bigaxe_points", "subtype": "start" }) # Break out of the loop break # Else we have a winner else: # Mark as finished Match.finished(data['id']) # Notify throwers Sync.push( 'natf', 'match-%s' % data['id'], { "type": "winner", "is": dMatch['bigaxe']['target']['i'][i] == 1 and 'i' or 'o' }) # Break out of the loop break # If we didn't get a winner or a jump to points, something is wrong else: # Reset finished Match.finishBigAxeReset('target', data['id']) # Notify throwers we aren't finished Sync.push('natf', 'match-%s' % data['id'], { "type": "bigaxe_target", "subtype": "notfinished" }) # Return failure return Services.Effect(False) # Return OK return Services.Effect(True)
def matchBigaxePoints_update(self, data, sesh): """Match Big Axe Points Takes a new throw for points and records it, then notifies the opponent Arguments: data {dict} -- Data sent with the request sesh {Sesh._Session} -- Session associated with the request Returns: Services.Effect """ # Verify fields try: DictHelper.eval(data, ['id', 'throw', 'clutch', 'value']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # If the throw is not an int if not isinstance(data['throw'], int): return Services.Effect(error=(1001, [('throw', 'not an int')])) # If the clutch is not a bool if not isinstance(data['clutch'], bool): return Services.Effect(error=(1001, [('clutch', 'not a bool')])) # If clutch is true but we didn't get 'd', 0, or 7 if data['clutch']: if data['value'] not in ['d', 0, 7]: return Services.Effect(error=(1001, [('value', 'invalid')])) # Get the match dMatch = Match.get(data['id'], raw=['finished', 'initiator', 'opponent', 'bigaxe']) if not dMatch: return Services.Effect(error=(1104, 'natf_match:%s' % data['id'])) # If the match is already finished if dMatch['finished']: return Services.Effect(error=1002) # Is the thrower the initiator or the opponent? if sesh['thrower']['_id'] == dMatch['initiator']: sIs = 'i' elif sesh['thrower']['_id'] == dMatch['opponent']: sIs = 'o' else: return Services.Effect(error=1000) # If the thrower already marked the section as finished if dMatch['bigaxe']['points']['finished'][sIs]: return Services.Effect(error=1002) # If the value doesn't exist if len(dMatch['bigaxe']['points'][sIs]) == data['throw']: dMatch['bigaxe']['points'][sIs].append({ "clutch": data['clutch'], "value": data['value'] }) # Else, overwrite it else: dMatch['bigaxe']['points'][sIs][data['throw']] = { "clutch": data['clutch'], "value": data['value'] } # Store the changes Match.updateBigAxe( 'points', data['id'], sIs, dMatch['bigaxe']['points'], ) # Notify anyone listening Sync.push( 'natf', 'match-%s' % data['id'], { "type": "bigaxe_points", "subtype": "throw", "thrower": sIs, "throw": data['throw'], "clutch": data['clutch'], "value": data['value'] }) # Return OK return Services.Effect(True)