def join_create(self, data, sesh): """Join Connects a session to an account or contact so that any messages associated with either are stored for later polling 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, ['service', 'key']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Update the sync cache Sync.join(sesh.id(), data['service'], data['key']) # Return OK return Services.Effect(True)
def favourite_create(self, data, sesh): """Favourite (Create) Adds a favourite to the logged in thrower 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])) # If someone tries to add themselves if data['id'] == sesh['thrower']['_id']: return Services.Effect(False) # Make sure the thrower exists if not Thrower.exists(data['id']): return Services.Effect(error=(1104, data['id'])) # Add the thrower to the logged in thrower's favourites and return the # result return Services.Effect( Favourites.add(sesh['thrower']['_id'], data['id']))
def leave_create(self, data, sesh): """Leave Disconnects a session from an account or contact so that messages are no longer collected for 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, ['service', 'key']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Update the sync cache Sync.leave(sesh.id(), data['service'], data['key']) # Return OK return Services.Effect(True)
def practiceData_read(self, data, sesh): """Practice Data Returns all the data points associated with a practice session 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])) # Fetch the practice data dPractice = Practice.get(data['id'], raw=['data', 'stats']) if not dPractice: return Services.Effect(error=(1104, 'practice:%s' % data['id'])) # Return the data return Services.Effect(dPractice)
def pull_read(self, data, sesh): """Pull A client is requesting an update on anything they might be looking at 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, ['service', 'key']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # If we have messages to delete if 'messages' in data and data['messages']: Sync.clear(sesh.id(), data['service'], data['key'], data['messages']) # Get as many messages as possible lRet = Sync.pull(sesh.id(), data['service'], data['key']) # Return whatever was found return Services.Effect(lRet)
def clear_update(self, data, sesh): """Clear Clears the given number of messages from the sync cache 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, ['service', 'key', 'count']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Clear the messages from the sync cache Sync.clear(sesh.id(), data['service'], data['key'], data['count']) # Return OK return Services.Effect(True)
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 practicePattern_update(self, data, sesh): """Practice Pattern (Update) Replaces an existing Practice Pattern for the current thrower 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])) # Find the pattern oPattern = PracticePattern.get(data['_id']) if not oPattern: return Services.Effect(error=(1104, 'practice_pattern:%s' % data['_id'])) # If the user has no rights if oPattern['thrower'] != sesh['thrower']['_id']: return Services.Effect(error=1000) # Remove fields that can't be changed del data['_id'] if '_created' in data: del data['_created'] if 'thrower' in data: del data['thrower'] # Update whatever is left, catch any invalid values lErrors = [] for k in data: try: oPattern[k] = data[k] except ValueError as e: lErrors.extend(e.args[0]) # If there's any errors if lErrors: return Services.Effect(error=(103, lErrors)) # Update the pattern oPattern.save() # Return OK return Services.Effect(True)
def match_create(self, data, sesh): """Match (Create) Creates a new match and returns its ID 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, ['_internal_', 'initiator', 'opponent']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Verify the key, remove it if it's ok if not Services.internalKey(data['_internal_']): return Services.Effect(error=Errors.SERVICE_INTERNAL_KEY) del data['_internal_'] # Create a new match instance try: oMatch = Match({ "_created": int(time()), "finished": False, "calculated": False, "initiator": data['initiator'], "opponent": data['opponent'], "game_finished": { "i": False, "o": False }, "game": { "i": {}, "o": {} } }) except ValueError as e: return Services.Effect(error=(1001, e.args[0])) # Store the instance if not oMatch.create(): return Services.Effect(error=1100) # Return the ID return Services.Effect(oMatch['_id'])
def signin_create(self, data): """Signin Signs a user into the system Arguments: data {dict} -- The data passed to the request Returns: Result """ # Verify fields try: DictHelper.eval(data, ['alias', 'passwd']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Look for the thrower by alias oThrower = Thrower.get(data['alias'], index='alias', limit=1) if not oThrower: return Services.Effect(error=1201) # Validate the password if not oThrower.passwordValidate(data['passwd']): return Services.Effect(error=1201) # Create a new session oSesh = Sesh.create() # Store the thrower ID and information in it oSesh['thrower'] = oThrower.record() # Save the session oSesh.save() # Return the session ID and primary thrower data return Services.Effect({ "session": oSesh.id(), "thrower": { "_id": oSesh['thrower']['_id'], "alias": oSesh['thrower']['alias'], "org": oSesh['thrower']['org'] } })
def passwdForgot_update(self, data): """Password Forgot (Change Password) Validates the key and changes the password to the given value Arguments: data {dict} -- Data sent with the request Returns: Services.Effect """ # Verify fields try: DictHelper.eval(data, ['passwd', 'key']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Look for the thrower by the key oThrower = Thrower.get(filter={"forgot": { "key": data['key'] }}, limit=1) if not oThrower: return Services.Effect( error=1203) # Don't let people know if the key exists or not # Check if we even have a forgot section, or the key has expired, or the # key is invalid if 'forgot' not in oThrower or \ oThrower['forgot']['expires'] <= int(time()) or \ oThrower['forgot']['key'] != data['key']: return Services.Effect(error=1203) # Make sure the new password is strong enough if not Thrower.passwordStrength(data['passwd']): return Services.Effect(error=1204) # Store the new password and update oThrower['passwd'] = Thrower.passwordHash(data['passwd']) oThrower.fieldDelete('forgot') oThrower.save(changes=False) # Return OK return Services.Effect(True)
def throwerVerify_update(self, data): """Thrower Verify Sets the thrower's email to verified if the key is valid Arguments: data {dict} -- Data sent with the request Returns: Services.Effect """ # Verify fields try: DictHelper.eval(data, ['_internal_', 'id', 'verify']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Verify the key, remove it if it's ok if not Services.internalKey(data['_internal_']): return Services.Effect(error=Errors.SERVICE_INTERNAL_KEY) del data['_internal_'] # Find the thrower oThrower = Thrower.get(data['id']) # If it doesn't exist if not oThrower: return Services.Effect(error=(1104, data['id'])) # If the thrower is already verified if oThrower['verified'] == True: return Services.Effect(True) # If the code is not valid if data['verify'] != oThrower['verified']: return Services.Effect(error=1205) # Update the thrower oThrower['verified'] = True oThrower.save(changes=False) # 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 matchRequest_read(self, data, sesh): """Match Request (Read) Fetchs a match request and returns 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 dRequest = MatchRequest.get(data['id'], raw=True) if not dRequest: return Services.Effect(error=(1104, 'match_request:%s' % data['id'])) # Get the ID of the other thrower if sesh['thrower']['_id'] == dRequest['initiator']: sID = dRequest['opponent'] elif sesh['thrower']['_id'] == dRequest['opponent']: sID = dRequest['initiator'] else: return Services.Effect(error=1000) # Get the other thrower's alias and add it to the request dAlias = Thrower.get(sID, raw=['alias']) dRequest['alias'] = dAlias and dAlias['alias'] or 'N/A' # Return the request return Services.Effect(dRequest)
def throwerOrg_update(self, data, sesh): """Thrower Org Changes the default organisation for the current signed in user Arguments: data {dict} -- Data sent with the request sesh {Sesh._Session} -- The session associated with the user Returns: Effect """ # Verify fields try: DictHelper.eval(data, ['org']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Find the thrower oThrower = Thrower.get(sesh['thrower']['_id']) if not oThrower: return Services.Effect(error=1104) # Set the new org try: oThrower['org'] = data['org'] except ValueError: return Services.Effect(error=(1000, [('org', 'invalid')])) # Save oThrower.save(changes={"creator": sesh['thrower']['_id']}) # Update the session sesh['thrower']['org'] = data['org'] sesh.save() # Return OK return Services.Effect(True)
def match_read(self, data, sesh): """Match (Read) Fetches and returns the stats from an existing match 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])) # Find the match dMatch = Match.get(data['id'], raw=True) if not dMatch: return Services.Effect(error=(1104, 'watl_match:%s' % data['id'])) # Get the aliases of both throwers oEffect = Services.read( 'auth', 'thrower/aliases', { "_internal_": Services.internalKey(), "ids": [dMatch['opponent'], dMatch['initiator']] }) if oEffect.errorExists(): return oEffect # Add the aliases dMatch['initiator_alias'] = oEffect.data[dMatch['initiator']] dMatch['opponent_alias'] = oEffect.data[dMatch['opponent']] # Else return the match return Services.Effect(dMatch)
def search_read(self, data, sesh): """Search Looks up throwers by alias 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, ['q']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Run a search and return the results return Services.Effect(Thrower.search(data['q']))
def throwerPasswd_update(self, data, sesh): """Thrower Password Changes the password for the current signed in user Arguments: data {dict} -- Data sent with the request sesh {Sesh._Session} -- The session associated with the user Returns: Effect """ # Verify fields try: DictHelper.eval(data, ['passwd', 'new_passwd']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Find the thrower oThrower = Thrower.get(sesh['thrower']['_id']) if not oThrower: return Services.Effect(error=1104) # Validate the password if not oThrower.passwordValidate(data['passwd']): return Services.Effect(error=(1001, [('passwd', 'invalid')])) # Make sure the new password is strong enough if not Thrower.passwordStrength(data['new_passwd']): return Services.Effect(error=1204) # Set the new password and save oThrower['passwd'] = Thrower.passwordHash(data['new_passwd']) oThrower.save(changes={"creator": sesh['thrower']['_id']}) # Return OK return Services.Effect(True)
def throwerAlias_update(self, data, sesh): """Thrower Alias Changes the alias associated with the thrower 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, ['alias']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # If the alias is invalid if not Thrower.struct()['tree']['alias'].valid(data['alias']): return Services.Effect(error=(1001, [('alias', 'invalid')])) # Look for someone else with that alias dThrower = Thrower.get(data['alias'], index='alias', raw=['_id']) if dThrower: return Services.Effect(error=(1200, data['alias'])) # Try to change the alias if not Thrower.alias(sesh['thrower']['_id'], data['alias']): return Services.Effect(False) # Update the session sesh['thrower']['alias'] = data['alias'] sesh.save() # Return OK return Services.Effect(True)
def practicePattern_create(self, data, sesh): """Practice Pattern (Create) Creates a new Practice Pattern for the current thrower 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, ['title', 'descr', 'throws']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Create the instance try: oPattern = PracticePattern({ "_created": int(time()), "thrower": sesh['thrower']['_id'], "title": data['title'], "descr": data['descr'], "throws": data['throws'] }) except ValueError as e: return Services.Effect(error=(1001, e.args[0])) # Store the instance if not oPattern.create(): return Services.Effect(error=1100) # Return the new ID return Services.Effect(oPattern['_id'])
def throwerAliases_read(self, data): """Thrower Aliases Recieves a list of thrower IDs and returns a dictionary of IDs to aliases Arguments: data {dict} -- Data sent with the request Returns: Effect """ # Verify fields try: DictHelper.eval(data, ['_internal_', 'ids']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Verify the key, remove it if it's ok if not Services.internalKey(data['_internal_']): return Services.Effect(error=Errors.SERVICE_INTERNAL_KEY) del data['_internal_'] # If the IDs are not a list if not isinstance(data['ids'], list): return Services.Effect(error=(1001, [('ids', 'not a list')])) # If the list is empty if not data['ids']: return Services.Effect({}) # Get and return all the thrower aliases return Services.Effect({ d['_id']: d['alias'] for d in Thrower.get(data['ids'], raw=['_id', 'alias']) })
def practicePattern_delete(self, data, sesh): """Practice Pattern (Delete) Deletes an existing Practice Pattern for the current thrower 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])) # Find the pattern oPattern = PracticePattern.get(data['id']) if not oPattern: return Services.Effect(error=(1104, 'practice_pattern:%s' % data['id'])) # If the user has no rights if oPattern['thrower'] != sesh['thrower']['_id']: return Services.Effect(error=1000) # Delete the pattern if not oPattern.delete(): return Services.Effect(False) # Return OK return Services.Effect(True)
def favourite_delete(self, data, sesh): """Favourite (Delete) Removes a favourite from the logged in thrower 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])) # Remove the thrower from the logged in thrower's favourites and return # the result return Services.Effect( Favourites.remove(sesh['thrower']['_id'], data['id']))
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 practice_create(self, data, sesh): """Practice Create Stores the details of a practice session 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, ['points']) except ValueError as e: return Services.Effect(error=(1001, [(f, "missing") for f in e.args])) # Make sure the value is a list of data points if not isinstance(data['points'], list): return Services.Effect(error=(1001, [('points', 'must be a list')])) # Init the stored structure dData = { "_created": int(time()), "data": [], "thrower": sesh['thrower']['_id'], "stats": { "ksLeft": { "attempts": 0, "drops": 0, "hits": 0, "points": 0 }, "ksRight": { "attempts": 0, "drops": 0, "hits": 0, "points": 0 }, "regular": { "attempts": 0, "sixes": 0, "fours": 0, "threes": 0, "twos": 0, "ones": 0, "zeros": 0, "drops": 0, "hits": 0, "points": 0 } } } # Go through every set for l in data['points']: # If it's a killshot if l[0] == 'L': # Increase the attempts dData['stats']['ksLeft']['attempts'] += 1 # If it's a drop if l[1] == 'd': dData['stats']['ksLeft']['drops'] += 1 # If it's a hit elif l[1] == 8: dData['stats']['ksLeft']['hits'] += 1 dData['stats']['ksLeft']['points'] += 8 # Add the points else: dData['stats']['ksLeft']['points'] += l[1] elif l[0] == 'R': # Increase the attempts dData['stats']['ksRight']['attempts'] += 1 # If it's a drop if l[1] == 'd': dData['stats']['ksRight']['drops'] += 1 # If it's a hit elif l[1] == 8: dData['stats']['ksRight']['hits'] += 1 dData['stats']['ksRight']['points'] += 8 # Add the points else: dData['stats']['ksRight']['points'] += l[1] # Else it's a standard throw else: # Increase the attempts dData['stats']['regular']['attempts'] += 1 # Increase the appropriate value if l[1] == 'd': dData['stats']['regular']['drops'] += 1 elif l[1] == 6: dData['stats']['regular']['sixes'] += 1 dData['stats']['regular']['hits'] += 1 dData['stats']['regular']['points'] += 5 elif l[1] == 4: dData['stats']['regular']['fours'] += 1 dData['stats']['regular']['hits'] += 1 dData['stats']['regular']['points'] += 5 elif l[1] == 3: dData['stats']['regular']['threes'] += 1 dData['stats']['regular']['hits'] += 1 dData['stats']['regular']['points'] += 3 elif l[1] == 2: dData['stats']['regular']['twos'] += 1 dData['stats']['regular']['hits'] += 1 dData['stats']['regular']['points'] += 3 elif l[1] == 1: dData['stats']['regular']['ones'] += 1 dData['stats']['regular']['hits'] += 1 dData['stats']['regular']['points'] += 1 elif l[1] == 0: dData['stats']['regular']['zeros'] += 1 # Append the set dData['data'].append({"killshot": l[0], "value": l[1]}) # Create a new instance of the practice try: oPractice = Practice(dData) except ValueError as e: return Services.Effect(error=(1001, e.args[0])) # Store the instance if not oPractice.create(): return Services.Effect(error=1100) # Update the total stats PracticeStats.add(sesh['thrower']['_id'], dData['stats']) # 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 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)