def create_game(self, user, cat, game_type=0): """ create a new game for the user given the category set the cu :param user: User object :param cat: models.Category object :param pages: records from model.Page given cat :return: None """ self.game = CurrentGame(user=user, category=cat) #set starting values for game # get the pages associated with the category (cat) self.update_game() self.common_log = self.game s = "event: game_created " s = '%s %s' % (s , self.common_log) self.logger.info(s) self.set_pages_to_use(game_type) #set starting page order for game self.generate_page_ordering() # now set the first page to find in the game self.set_next_page() # save to db self.update_game()
class GameMechanic(object): def __init__(self, search_engine=None, max_score=1000, max_queries=20, max_pages=5, max_queries_per_page=5,game_length_in_seconds=0): """ :return: GameMechanic object """ self.game = None self.search_engine = search_engine self.max_score = max_score self.max_queries = max_queries self.max_pages = max_pages self.max_queries_per_page = max_pages self.game_length_in_seconds = game_length_in_seconds self.logger = get_ifind_logger(__name__) self.common_log = None self.round_log = None self.game_over = 0 def create_game(self, user, cat, game_type=0): """ create a new game for the user given the category set the cu :param user: User object :param cat: models.Category object :param pages: records from model.Page given cat :return: None """ self.game = CurrentGame(user=user, category=cat) #set starting values for game # get the pages associated with the category (cat) self.update_game() self.common_log = self.game s = "event: game_created " s = '%s %s' % (s , self.common_log) self.logger.info(s) self.set_pages_to_use(game_type) #set starting page order for game self.generate_page_ordering() # now set the first page to find in the game self.set_next_page() # save to db self.update_game() def retrieve_game(self, user, game_id): """ find the game associated with this user, and return the record from ifind.models.game_models.CurrentGame :param user: :param game_id: :return: True, if game is found, else False, if not """ self.game = None found = False # look up model for game_id # try except here? cg = CurrentGame.objects.get(id=game_id) # if found, set self.game to game record if cg: self.game = cg self.set_pages_to_use(0) found = True return found def is_game_over(self): """ checks if the game is over :param game: :return: True if the end game criteria have been met, else False """ # example criteria for the game end if (self.get_round_no() > self.max_pages): return True else: return False def get_round_no(self): return self.game.no_rounds+1 def get_game_player_name(self): return self.game.user.username def get_final_round_no(self): return self.game.no_rounds def get_game_category_name(self): return self.game.category.name def double_bonus(self): if self.game.bonus == 0: self.game.bonus = 100 elif self.game.bonus < 3200: self.game.bonus *= 2 def reset_bonus(self): self.game.bonus = 0 def get_max_rounds(self): return self.max_pages def get_current_score(self): return self.game.current_score def get_no_of_queries_issued(self): return self.game.no_of_queries_issued def get_no_of_successful_queries_issued(self): return self.game.no_of_successful_queries_issued def get_no_of_queries_issued_for_current_page(self): return self.game.no_of_queries_issued_for_current_page def reset_no_of_queries_issued_for_current_page(self): self.game.no_of_queries_issued_for_current_page = 0 def get_no_rounds_completed(self): return self.game.no_rounds_completed def get_remaining_rounds(self): return self.get_max_rounds() - self.get_round_no() def get_search_results(self, query, top=10): return self._run_query(query,top) def get_game_id(self): return self.game.id def get_current_page(self): return self.game.current_page def _increment_queries_issued(self, query_successful=False): self.game.no_of_queries_issued += 1 self.game.current_page.no_of_queries_issued += 1 self.game.no_of_queries_issued_for_current_page += 1 up = UserProfile.objects.get(user=self.game.user) up.no_queries_issued += 1 if query_successful: self.game.current_page.no_times_retrieved += 1 self.game.no_of_successful_queries_issued += 1 up.no_successful_queries_issued += 1 self.game.current_page.save() up.save() def _increment_round(self, round_successful=False): self.game.no_rounds += 1 if round_successful: self.double_bonus() self.game.no_rounds_completed += 1 else: self.reset_bonus() def _increment_score(self, points=0): self.game.current_score += points def update_game(self): """ make updates to game then save to db :param game: :return: None """ self.game.save() def set_pages_to_use(self, game_type): """ select a bunch of pages given the category and the game type :param game_type: :return: None """ self.pages = Page.objects.filter(category=self.game.category) #TODO #todo(leifos): check the number of pages does exceed MAX_PAGES def generate_page_ordering(self): """ given the list self.pages, create the ordering of pages for the game :param pages: :return: """ # use the RotationOrdering class to gen the orderinga ro = RotationOrdering() print self.pages page_list = ro.get_ordering(self.pages) # set the page_list to the the game #TODO self.logger.debug(page_list) set_page_list(self.game, page_list) def set_next_page(self): """ :return: True if next page is set, else False """ # from game get the page_list page_list = get_page_list(self.game) l = len(page_list) # given the round, select the page_id from page_list r = self.game.no_rounds if r < l: page_id = page_list[r] self.reset_no_of_queries_issued_for_current_page() print r, page_id else: return False # associate the page from the page model to game try: self.game.current_page = self.pages.get(id=page_id) self.game.current_page.no_times_shown += 1 self.game.current_page.save() round_log = '%s %d' % (self.game.current_page.url, r) s = 'event:page_shown %s %s' % (self.game , round_log) self.logger.info(s) return True except: self.game.current_page = None return False def take_points(self): success = False round_log = 'page_url: %s %d' % (self.game.current_page.url, self.game.no_rounds) if self.game.last_query_score > 0: self._increment_score(self.game.last_query_score) success = True s = 'event:points_taken %s %s %d' % (self.game , round_log , self.game.last_query_score) self.logger.info(s) else: s = 'event:page_skipped %s %s' % (self.game , round_log) self.logger.info(s) self._increment_round(success) self.game.last_query_score = 0 self.game.last_query = '' #self.update_game() # increment round here ????? def handle_query(self, query): score = self._score_query(query) self.game.last_query = query self.game.last_query_score = score success = False if score > 0: success = True self._increment_queries_issued(success) def _score_query(self, query): """sends query to the search engine, checks if the page is returned, assign score to page, based on the rank :param query_terms: string :param url_to_find: string :return: integer """ results = self._run_query(query) rank = self._check_result(results) query_len = self.get_no_terms(query) #query_len = self.query_char_len(query) score = self._score_rank(rank, self.game.bonus, query_len) common_log = 'event: issue_query %s' % (self.game) round_log = '%s %d' % (self.game.current_page.url, self.game.no_rounds) info_log = '%d %d %s' % (score, rank, query) log = '%s %s %s' % (common_log, round_log, info_log) self.logger.info(log) return score def get_no_terms(self, query): terms = query.strip().split(' ') ''' Since the site:gla.ac.uk is added to the end of the query, this would count as a one term in the query So, this will be removed by subtracting by 1 ''' #game no longer uses site:gla query_len = len(terms) #-1 return query_len def query_char_len(self, query): ''' Get num of chars in query terms ''' return len(query) def _run_query(self, query ,top=10): import sys path = '/home/arazzouk/ifind' if path not in sys.path: sys.path.append(path) from ifind.search.query import Query from ifind.search.response import Response """ constructs ifind.search.query, and issues it to the search_engine :param query: :return: ifind.search.response """ # construct ifind.search.query Query iquery = Query(query, result_type="web",top=top) # issue query to self.search_engine iresponse = self.search_engine.search(iquery) return iresponse def _run_query2(self, query): import sys path = '/home/arazzouk/ifind' if path not in sys.path: sys.path.append(path) from ifind.search.query import Query from ifind.search.response import Response """ constructs ifind.search.query, and issues it to the search_engine :param query: :return: ifind.search.response """ # construct ifind.search.query Query iquery = Query(query, result_type="web") # issue query to self.search_engine iresponse = self.search_engine.search(iquery) return iresponse.to_json def _check_result(self, response): """ iterates through the response looking for what rank the url is at :param response: ifind.search.response :param url_to_find: url string :return: rank of the url if found, else 0 """ url_to_find = self.game.current_page.url # is url_to_fin in response?? #iterate through response i = 0 for result in response.results: i +=1 if result.url == url_to_find: return i return 0 def _score_rank(self, rank, bonus=0, query_len=0): """ calculates the score based on the rank of the page :param rank: integer :return: integer """ score = 0 if rank > 0: score = self.max_score / rank return score def handle_game_over(self): s = "event: game_over %s" % (self.game) self.logger.info(s) if self.game.user.username != "anon": #HighScore.objects.all().delete() hs = HighScore.objects.get_or_create(user=self.game.user,category=self.game.category) if hs: if self.game.current_score > hs[0].highest_score: hs[0].highest_score = self.game.current_score hs[0].save() if self.game.no_rounds_completed > hs[0].most_no_pages_found: hs[0].most_no_pages_found = self.game.no_rounds_completed hs[0].save() else: HighScore(user=self.game.user,category=self.game.category, highest_score=self.game.current_score, most_no_pages_found=self.game.no_rounds_completed).save() all_hs = HighScore.objects.filter(user=self.game.user) gac = game_achievements.GameAchievementChecker(self.game.user) up = UserProfile.objects.get(user=self.game.user) return gac.check_and_set_new_achievements(up,all_hs,self.game) def get_last_query_score(self): return self.game.last_query_score def get_last_query(self): return self.game.last_query def __str__(self): if self.game: return 'Game %d - Current Score: %d for ' \ 'user: %s \nPlaying category: %s round: %d queries issued: %d \n' \ '\nPage to find: %s' \ % (self.game.id, self.game.current_score, self.game.user, self.game.category, self.get_round_no(), self.game.no_of_queries_issued, self.game.current_page) else: return 'Unitialised Game'