def __init__(self, db): self.db = db self.emails_to_uids = db['emails_to_uids'] self.users = db['users'] #take max of list of existing users joined with the list containing 0, will be 1 for new db self.next_registered_user = None self.next_guest_user = 1 self.find_next_user_id() self.feedhandler = Feed_Handler(self.db)
def __init__(self, db): random.seed() self.db = db self.games_table = db['games'] self.waiting_gids = list() self.next_int_gid = self.find_next_game_id() try: self.ai_words_list = pickle.load(open('ai/ai_word_list.pickle', 'r')) except: try: self.ai_words_list = pickle.load(open('../ai/ai_word_list.pickle', 'r')) except: print 'Unable to load ai word list from pickle file' exit(1) self.feedhandler = Feed_Handler(db)
class Account_Handler(): def __init__(self, db): self.db = db self.emails_to_uids = db['emails_to_uids'] self.users = db['users'] #take max of list of existing users joined with the list containing 0, will be 1 for new db self.next_registered_user = None self.next_guest_user = 1 self.find_next_user_id() self.feedhandler = Feed_Handler(self.db) def handle_login_request(self): result={'result':"Success", 'errors':[]} cl = cherrypy.request.headers['Content-Length'] data_json = cherrypy.request.body.read(int(cl)) incoming_data = json.loads(data_json) if 'usermail' not in incoming_data: result = {'result':'Error', 'errors':["'usermail' is a required field in a login post"]} return json.dumps(result) if 'password' not in incoming_data: result = {'result':'Error', 'errors':["'password' is a required field in a login post"]} return json.dumps(result) if incoming_data['usermail'] not in self.emails_to_uids: result['result'] = "Error" result['errors'].append("Invalid email/password combination") else: expected_hash = self.users[self.emails_to_uids[incoming_data['usermail']]]['hashed_pass'] hashed_incoming = self.hash_pwd(incoming_data['password']) if hashed_incoming != expected_hash: result['result'] = "Error" result['errors'].append("Invalid email/password combination") else: result['result'] = self.emails_to_uids[incoming_data['usermail']] result['errors'] = [] return json.dumps(result) def handle_register_request(self, usermail=None, password=None, username=None): cl = cherrypy.request.headers['Content-Length'] data_json = cherrypy.request.body.read(int(cl)) data = json.loads(data_json) pwd = data["password"] usermail = data["usermail"] hashed_pass = self.hash_pwd(pwd) username = data["username"] if usermail in self.emails_to_uids: result = {'errors':['Email already in use'], 'result':None} else: new_uid = str(self.find_next_user_id()) self.users[new_uid] = {"usermail": usermail, "hashed_pass": hashed_pass, "username": username, "friends": [], "incoming_friend_requests": [], "outgoing_friend_requests": [], "profile_image" : None } result = {'errors':[], 'result':new_uid} self.emails_to_uids[usermail] = new_uid return json.dumps(result) def get_guest_uid(self): userid = "g" + str(self.next_guest_user) self.users[userid] = {"username" : "Guest_" + str(self.next_guest_user), "hashed_pass" : None, "usermail" : None, "friends" : None, "incoming_friend_requests" : None, "outgoing_friend_requests" : None, "profile_image" : None} self.next_guest_user += 1 guest_info = {'uid' : userid, 'errors': []} return json.dumps(guest_info) def find_next_user_id(self): if self.next_registered_user: to_return = self.next_registered_user self.next_registered_user += 1 return to_return else: to_return = 0 for uid in self.users: try: intuid = int(uid) if to_return < intuid: to_return = intuid except: pass to_return += 1 self.next_registered_user = to_return + 1 return to_return def handle_new_friend_request(self, uid, uid_requested): is_friends = False if uid_requested not in self.users: return json.dumps({"result":"Error", "errors" : ["Friend requested uid is unknown to database"]}) if uid not in self.users: return json.dumps({"result":"Error", "errors" : ["Request made by unknown user"]}) #See if the uid being requested has already requested the uid requesting if uid_requested in self.users[uid]['incoming_friend_requests']: self.make_friends(uid, uid_requested) self.remove_pairs_pending_requests(uid, uid_requested) is_friends = True else: if uid not in self.users[uid_requested]['incoming_friend_requests']: self.users[uid_requested]['incoming_friend_requests'].append(uid) if uid_requested not in self.users[uid]['outgoing_friend_requests']: self.users[uid]['outgoing_friend_requests'].append(uid_requested) raise cherrypy.HTTPRedirect('/lobby/' + str(uid)) return json.dumps({"result":"Success", "is_friends" : is_friends, "errors":[]}) def handle_friend_request_response(self, uid, requester_uid, response): #if response = "decline" is assumed is_accepted = False if response == "accept": is_accepted = True if requester_uid not in self.users: return json.dumps({"result":"Error", "errors" : ["Requester uid is unknown to database"]}) if uid not in self.users: return json.dumps({"result":"Error", "errors" : ["Post for friend request response made by unknown user"]}) if is_accepted and (requester_uid in self.users[uid]['incoming_friend_requests']) and (uid in self.users[requester_uid]['outgoing_friend_requests']): self.make_friends(uid, requester_uid) self.remove_pairs_pending_requests(uid, requester_uid) raise cherrypy.HTTPRedirect("/lobby/" + str(uid)) return json.dumps({"result":"Success", "errors": []}) def handle_friend_delete(self, uid, unfriended_uid): if uid not in self.users: return json.dumps({"result" : "Error", "errors" : ["Requester uid is unknown to database"]}) self.delete_friendship(uid, unfriended_uid) self.remove_pairs_pending_requests(uid, unfriended_uid) raise cherrypy.HTTPRedirect("/lobby/" + str(uid)) return json.dumps({"result" : "Success", "errors" : []}) def update_settings_request(self,uid): result={'result':"Success", 'errors':[]} cl = cherrypy.request.headers['Content-Length'] data_json = cherrypy.request.body.read(int(cl)) incoming_data = json.loads(data_json) if 'usermail' not in incoming_data: result = {'result':'Error', 'errors':["'usermail' is a required field in updating settings post"]} return json.dumps(result) if 'password' not in incoming_data: result = {'result':'Error', 'errors':["'password' is a required field in updating settings post"]} return json.dumps(result) if 'username' not in incoming_data: result = {'result':'Error', 'errors':["'username' is a required field in updating settings post"]} return json.dumps(result) else: expected_hash = self.users[uid]['hashed_pass'] hashed_incoming = self.hash_pwd(incoming_data['password']) if hashed_incoming != expected_hash: result['result'] = "Error" result['errors'].append("Invalid password") else: if incoming_data['usermail'] in self.emails_to_uids and incoming_data['usermail'] != incoming_data['old_usermail']: result = {'result':'Error', 'errors':["email is already in use"]} return json.dumps(result) else: result['result'] = uid self.users[uid]["username"] = incoming_data['username'] if incoming_data['usermail'] != incoming_data['old_usermail']: self.users[uid]["usermail"] = incoming_data['usermail'] self.emails_to_uids[incoming_data['usermail']] = str(uid) del self.emails_to_uids[incoming_data['old_usermail']] if incoming_data['newpassword'] != '': hashed_pass = self.hash_pwd(incoming_data['newpassword']) self.users[uid]["hashed_pass"] = hashed_pass result['errors'] = [] return json.dumps(result) def upload_avatar(self, uid, img_file, submit): all_data = None while True: data = img_file.file.read(8192) if all_data: all_data += data else: all_data = data if not data: break size = len(all_data) file_extension = self.get_extension(img_file.filename.lower()) filename = str(uid) + '.' + file_extension filepath = './img/' + filename saved_file = open(filepath, 'wb') saved_file.write(all_data) saved_file.close() self.users[uid]['profile_image'] = filename #raise cherrypy.HTTPRedirect('/settings/' + str(uid)) def get_extension(self, filename): for ext in ['png', 'jpg', 'gif']: if filename.endswith(ext): return ext return 'png' def make_friends(self, uid1, uid2): if uid2 not in self.users[uid1]['friends']: self.users[uid1]['friends'].append(uid2) if uid1 not in self.users[uid2]['friends']: self.users[uid2]['friends'].append(uid1) self.feedhandler.post_new_friendship(uid1, uid2) def delete_friendship(self, uid1, uid2): if uid2 in self.users[uid1]['friends']: self.users[uid1]['friends'].remove(uid2) if uid1 in self.users[uid2]['friends']: self.users[uid2]['friends'].remove(uid1) def remove_pairs_pending_requests(self, uid1, uid2): if uid2 in self.users[uid1]['incoming_friend_requests']: self.users[uid1]['incoming_friend_requests'].remove(uid2) if uid2 in self.users[uid1]['outgoing_friend_requests']: self.users[uid1]['outgoing_friend_requests'].remove(uid2) if uid1 in self.users[uid2]['incoming_friend_requests']: self.users[uid2]['incominig_friend_requests'].remove(uid1) if uid1 in self.users[uid2]['outgoing_friend_requests']: self.users[uid2]['outgoing_friend_requests'].remove(uid1) def hash_pwd(self, pwd): hashed = hashlib.sha224(pwd).hexdigest() return hashed
class Game_Handler(): def __init__(self, db): random.seed() self.db = db self.games_table = db['games'] self.waiting_gids = list() self.next_int_gid = self.find_next_game_id() try: self.ai_words_list = pickle.load(open('ai/ai_word_list.pickle', 'r')) except: try: self.ai_words_list = pickle.load(open('../ai/ai_word_list.pickle', 'r')) except: print 'Unable to load ai word list from pickle file' exit(1) self.feedhandler = Feed_Handler(db) def get_dummy_game(self, gid): result = {} result["answer"] = "this is a test phrase" result["incorrect_letters"] = ['u','b','c'] result["incorrect_words"] = ['wronge guess'] result["correct_letters"] = ['s','i','t','a'] result["guesser_uid"] = 'u1' result["creator_uid"] = 'u2' result["errors"] = [] result["result"] = "Success" return json.dumps(result) def post_phrase_guess(self, uid, gid, guess): is_bad = self.validate_guess_and_guesser(uid, gid, guess) if(is_bad is not None): return json.dumps(is_bad, encoding='latin-1') guess = guess.upper() self.guess_phrase(gid, guess) output ={'result':'Success', 'message': None} raise cherrypy.HTTPRedirect('/gameplay/' + str(uid) + '/' + str(gid)) def post_letter_guess(self, uid, gid, guess): is_bad = self.validate_guess_and_guesser(uid, gid, guess) if(is_bad is not None): return json.dumps(is_bad, encoding='latin-1') guess = guess.upper() self.guess_letter(gid, guess) output ={'result':'Success', 'message': None} raise cherrypy.HTTPRedirect('/gameplay/' + str(uid) + '/' + str(gid)) def validate_guess_and_guesser(self, uid, gid, guess): if(gid not in self.games_table): output = {'result':'Error', 'errors':["Game does not exist"]} elif(uid != self.games_table[gid]['guesser_uid']): output = {'result':'Error', 'errors':["Must be the guessing user to guess"]} elif not guess: output = {'result':'Failure', 'message':"Incoming data not valid"} elif uid != self.games_table[gid]['guesser_uid']: output = {'result':'Failure', 'message':"Must be the guessing user to guess"} else: output=None return output def guess_phrase(self, gid, phrase): if gid not in self.games_table: return json.dumps({'result':'Error', 'errors':["Game does not exist"]}) game_dict = self.games_table[gid] if not phrase in game_dict['incorrect_words']: if phrase == game_dict['answer']: for letter in phrase: if not letter in game_dict['correct_letters']: game_dict['correct_letters'].append(letter) else: game_dict['incorrect_words'].append(phrase) self.check_win(game_dict, phrase) def guess_letter(self, gid, letter): game_dict = self.games_table[gid] answer = game_dict['answer'] correct_letters = game_dict['correct_letters'] incorrect_letters = game_dict['incorrect_letters'] if letter not in correct_letters and letter not in incorrect_letters: if letter.upper() in answer.upper(): print letter + ' in ' + answer game_dict['correct_letters'].append(letter) else: print letter + ' not in ' + answer game_dict['incorrect_letters'].append(letter) self.check_win(game_dict, letter) else: print letter + ' already guessed' def check_win(self, game_dict, guess): # Check if the guesser won if len(guess) > 1: if guess == game_dict['answer']: game_dict['win'] = game_dict['guesser_uid'] self.feedhandler.post_game_result(game_dict['guesser_uid'], game_dict['creator_uid'], True, game_dict['answer']) else: if len(set(game_dict['answer'])) is len(game_dict['correct_letters']): game_dict['win'] = game_dict['guesser_uid'] self.feedhandler.post_game_result(game_dict['guesser_uid'], game_dict['creator_uid'], True, game_dict['answer']) # Check if the creator won guesses_made = len(game_dict['incorrect_letters']) + len(game_dict['incorrect_words']) if guesses_made >= 6: game_dict['win'] = game_dict['creator_uid'] self.feedhandler.post_game_result(game_dict['guesser_uid'], game_dict['creator_uid'], False, game_dict['answer']) def get_game(self, gid): # Active Game if gid in self.games_table: #make the ai player guess a letter each time there is a get on an ai game if the ai is guessing if self.games_table[gid]['is_ai'] and self.games_table[gid]['guesser_uid'] == "ai": self.make_ai_guess(gid) output = self.games_table[gid] output['result'] = 'Success' output['errors'] = [] # Logic Error: No active game with this gid else: output = {'result': 'Error', 'errors': ['This is not an active game id.']} return json.dumps(output, encoding='latin-1') def get_game_no_ai_guess(self, gid): # Active Game if gid in self.games_table: output = self.games_table[gid] output['result'] = 'Success' output['errors'] = [] # Logic Error: No active game with this gid else: output = {'result': 'Error', 'errors': ['This is not an active game id.']} return json.dumps(output, encoding='latin-1') def get_game_request(self, uid): request_state = self.handle_get_game_request(uid) gid = request_state['gid'] self.wait_for_game(uid, gid) def get_ai_game_request(self, uid): request_state = self.handle_get_ai_game_request(uid) gid = request_state['gid'] print 'from gameplay gid is ' + str(gid) self.wait_for_game(uid, gid) def wait_for_game(self, uid, gid): #if waiting: while(1): if gid not in self.games_table: sleep(2) # Wait 2 seconds and check if game exists else: creator = self.games_table[gid]['creator_uid'] if creator == uid: print 'from gameplay gid is ' + str(gid) raise cherrypy.HTTPRedirect('/phrase/' + str(uid) + '/' + str(gid)) else: answer = self.games_table[gid]['answer'] #if answer == "None": answer = False if not answer: sleep(2) continue else: raise cherrypy.HTTPRedirect('/gameplay/' + str(uid) + '/' + str(gid)) def handle_get_game_request(self, uid): waiting = True # whether or not we need to wait for a second player uid = str(uid) # If there are players waiting for a game, choose a waiting gid if not len(self.waiting_gids) is 0: (new_gid, first_uid) = self.waiting_gids[0] # Make sure this uid isn't just requesting the same game twice if first_uid != uid: self.waiting_gids.pop(0) (guesser_uid, creator_uid) = self.assign_player_roles(first_uid, uid) self.games_table[new_gid] = {'answer': None, 'incorrect_letters': [], 'incorrect_words': [], 'correct_letters': [], 'guesser_uid' : guesser_uid, 'creator_uid':creator_uid, 'is_ai':False, 'ai_possible_words':[], 'win': None} waiting = False # Otherwise, choose a new gid and add it to the list of waiting gids else: new_gid = str(self.next_int_gid) self.next_int_gid += 1 self.waiting_gids.append((new_gid, uid)) waiting = True output = {'gid': new_gid, 'waiting': waiting, 'errors':[]} return output def handle_get_ai_game_request(self, uid): new_gid = str(self.next_int_gid) self.next_int_gid += 1 ai_uid = "ai" (guesser_uid, creator_uid) = self.assign_player_roles(uid, ai_uid) self.games_table[new_gid] = {'answer': None, 'incorrect_letters': [], 'incorrect_words': [], 'correct_letters': [], 'guesser_uid' : guesser_uid, 'creator_uid':creator_uid, 'is_ai':True, 'ai_possible_words':[], 'win': None} if creator_uid == ai_uid: self.games_table[new_gid]['answer'] = self.make_random_ai_phrase() output = {'gid': new_gid, 'waiting':False, 'errors':[]} return output def make_ai_guess(self, gid): #pick letter answer = self.games_table[gid]['answer'] correct_letters = self.games_table[gid]['correct_letters'] incorrect_letters = self.games_table[gid]['incorrect_letters'] guessed_letters = set(correct_letters + incorrect_letters) viable_guess_letters = set(list(string.ascii_uppercase)) - guessed_letters correct_count = 0 regex_string = "" for letter in answer: if letter in correct_letters: regex_string += letter.lower() correct_count += 1 else: regex_string += '.' if float(correct_count)/len(answer) >= 2.0/3: if len(self.games_table[gid]['ai_possible_words']) is 0: print 'getting phrase' regex = re.compile(regex_string) self.games_table[gid]['ai_possible_words'] = [m.group(0).upper() for l in self.ai_words_list for m in [regex.search(l)] if m] print len(self.games_table[gid]['ai_possible_words']) word = self.games_table[gid]['ai_possible_words'].pop() print len(self.games_table[gid]['ai_possible_words']) # Set possible words to None to denote all possible words have been guessed if len(self.games_table[gid]['ai_possible_words']) is 0: self.games_table[gid]['ai_possible_words'] = None # All words fitting regex in AI knowledge base have been guessed elif self.games_table[gid]['ai_possible_words'] is None: print 'no phrases left to guess' letter = letter_frequency.choose_highest_freq_letter(viable_guess_letters) self.guess_letter(gid, letter) else: print 'guessing phrase' word = self.games_table[gid]['ai_possible_words'].pop() self.guess_phrase(gid, word) else: letter = letter_frequency.choose_random_letter_weighted(viable_guess_letters) self.guess_letter(gid, letter) def make_random_ai_phrase(self): word = random.choice(self.ai_words_list) print word return word.upper() def post_game_prompt(self, uid, gid, answer=None): template = "RequestPhrase.html" if(gid[0] == 'g'): template = "GuestRequestPhrasei.html" guesser_name = "Your Opponent" if uid != self.games_table[gid]['creator_uid']: return env.get_template(template).render(uid=uid, gid=gid, guesser_name = guesser_name, error = 1) if not answer: return env.get_template(template).render(uid=uid, gid=gid, guesser_name = guesser_name, error = 1) answer = answer.upper() stripped_answer = ''.join(answer.split(' ')) # Answer without whitespace if len(answer) in range(3, 31) and stripped_answer.isalpha(): self.games_table[gid]['answer'] = answer output = {'result': 'Success', 'message': 'Your game will begin shortly!'} raise cherrypy.HTTPRedirect('/gameplay/' + str(uid) + '/' + str(gid)) else: return env.get_template(template).render(uid=uid, gid=gid, guesser_name = guesser_name, error = 1) def assign_player_roles(self, uid1, uid2): if random.randint(0,1) == 0: guesser_uid = uid1 creator_uid = uid2 else: guesser_uid = uid2 creator_uid = uid1 return (guesser_uid, creator_uid) def find_next_game_id(self): if len(self.games_table) is 0: return 1 else: return max(int(x) for x in self.games_table)