Exemplo n.º 1
0
 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)
Exemplo n.º 2
0
 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)
Exemplo n.º 3
0
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
Exemplo n.º 4
0
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)