def set_progress(puzzles, user_id): user_data_str = read_dp(user_id) if user_data_str: user_progress = loads(user_data_str)['progress'] user_voids = loads(user_data_str)['voids'] user_solved_time = loads(user_data_str)['solved_time'] user_score = loads(user_data_str)['score'] user_hints = loads(user_data_str)['hints'] else: user_progress = list() user_voids = list() user_solved_time = list() user_hints = dict() user_data_str = dumps( { 'progress': user_progress, 'voids': user_voids, 'solved_time': user_solved_time, 'score': '0', 'hints': user_hints }, indent=2) write_dp(user_id, user_data_str) for idx, p in puzzles.items(): if idx in user_progress: p.is_completed = True p.set_completed_title() elif idx in user_voids: p.is_voided = True p.set_void_title()
def void(update, context): user_id = update.effective_user.id puzzles = context.chat_data[user_id] puzzle_idx = context.user_data['cur_puzzle_idx'] query = update.callback_query query.answer() context.user_data['is_voided'] = True puzzles[puzzle_idx].is_voided = True puzzles[puzzle_idx].set_void_title() bot = context.bot try: last_description = context.user_data['last_description'] bot.delete_message(chat_id=user_id, message_id=last_description.message_id) except: pass user_data_str = read_dp(str(user_id)) if user_data_str: user_progress = loads(user_data_str)['progress'] user_voids = loads(user_data_str)['voids'] user_score = loads(user_data_str)['score'] user_hints = sum(loads(user_data_str)['hints'].values()) else: user_progress = list() user_voids = list() user_score = 0 user_hints = 0 reply_markup = get_options_keyboard(context.chat_data, user_id) if len(user_progress) + len(user_voids) == len(puzzles) - 1: if GIVEN_HINTS - user_hints == 1: query.edit_message_text( f'You have just voided the final puzzle!\n\nYour final score is {int(user_score) + HINT_POINTS*(GIVEN_HINTS - user_hints)} because you had extra {HINT_POINTS} points from the {GIVEN_HINTS - user_hints} unused hint! Nicely done!\n\nNow choose a puzzle to view ...', reply_markup=reply_markup) elif GIVEN_HINTS - user_hints != 0: query.edit_message_text( f'You have just voided the final puzzle!\n\nYour final score is {int(user_score) + HINT_POINTS*(GIVEN_HINTS - user_hints)} because you had extra {HINT_POINTS} points from each of the {GIVEN_HINTS - user_hints} unused hints! Nicely done!\n\nNow choose a puzzle to view ...', reply_markup=reply_markup) else: query.edit_message_text( f'You have just voided the final puzzle!\n\nYour final score is {user_score}. Woohoo!\n\nNow choose a puzzle to view ...', reply_markup=reply_markup) elif len(user_progress) + len(user_voids) == len(puzzles) - 2: query.edit_message_text( f'You have just voided the puzzle! Final puzzle unlocked!\n\nYour score is now {user_score}.\n\nNow choose a puzzle to view ...', reply_markup=reply_markup) else: query.edit_message_text( f'You have just voided the puzzle!\n\nYour score is now {user_score}.\n\nNow choose a puzzle to view ...', reply_markup=reply_markup) save_user_progress(str(user_id), context, False) return CHOOSE_PUZZLE
def save_user_progress(user_id, context): user_data_str = read_dp(user_id) if user_data_str: user_progress = loads(user_data_str)['progress'] else: user_progress = list() user_progress.append(context.user_data['cur_chall_idx']) user_data_str = dumps({'progress': user_progress}, indent=2) write_dp(user_id, user_data_str)
def save_user_progress(user_id): user_data_str = read_dp(user_id) if user_data_str: user_progress = loads(user_data_str)['progress'] else: user_progress = list() user_progress.append(CUR_CHALL_IDX) user_data_str = dumps({'progress': user_progress}, indent=2) write_dp(user_id, user_data_str)
def score(update, context): msg = update.message user_id = msg.from_user.id user_data_str = read_dp(str(user_id)) if user_data_str: user_score = loads(user_data_str)['score'] else: user_score = 0 update.message.reply_text(f'Your current score is {user_score}.')
def set_progress(challs, user_id): user_data_str = read_dp(user_id) if user_data_str: user_progress = loads(user_data_str)['progress'] else: user_progress = list() user_data_str = dumps({'progress': user_progress}, indent=2) write_dp(user_id, user_data_str) for idx, c in challs.items(): if idx in user_progress: c.is_completed = True
def save_user_progress(user_id, context, for_hint): user_data_str = read_dp(user_id) if user_data_str: user_progress = loads(user_data_str)['progress'] user_voids = loads(user_data_str)['voids'] user_solved_time = loads(user_data_str)['solved_time'] user_score = int(loads(user_data_str)['score']) user_hints = loads(user_data_str)['hints'] else: user_progress = list() user_voids = list() user_solved_time = list() user_score = 0 user_hints = dict() puzzle = context.user_data puzzles = load_data_from_json(user_id) if puzzle['is_voided']: user_voids.append(puzzle['cur_puzzle_idx']) elif for_hint: user_hints[puzzle['cur_puzzle_idx']] = user_hints.get( puzzle['cur_puzzle_idx'], 0) + 1 # user_score -= 1 else: user_progress.append(puzzle['cur_puzzle_idx']) user_solved_time.append(time.time()) user_score += puzzle['score'] if len(user_voids) + len(user_progress) == len(puzzles): user_score += HINT_POINTS * (GIVEN_HINTS - sum(user_hints.values())) user_name = puzzle['username'] user_data_str = dumps( { 'username': user_name, 'progress': user_progress, 'voids': user_voids, 'solved_time': user_solved_time, 'score': str(user_score), 'hints': user_hints }, indent=2) write_dp(user_id, user_data_str)
def hints(update, context): msg = update.message user_id = msg.from_user.id user_data_str = read_dp(str(user_id)) if user_data_str: user_hints = sum(loads(user_data_str)['hints'].values()) else: user_hints = 0 if GIVEN_HINTS - user_hints == 1: s = '' else: s = 's' update.message.reply_text( f'You have {GIVEN_HINTS - user_hints} unused hint{s} remaining.')
def check_answer(update, context): user_id = update.message.from_user.id puzzles = context.chat_data[user_id] puzzle_idx = context.user_data['cur_puzzle_idx'] user_name = context.user_data['username'] right_answers = puzzles[puzzle_idx].answers user_answer = update.message.text.lower() keyboard = [[ InlineKeyboardButton(text='Back to puzzles\' list 📃', callback_data='back'), InlineKeyboardButton(text='Done ✔️', callback_data='done') ]] if user_answer in right_answers: # Simply to display current score and number of solved puzzles user_data_str = read_dp(str(user_id)) if user_data_str: user_progress = loads(user_data_str)['progress'] user_voids = loads(user_data_str)['voids'] user_score = loads(user_data_str)['score'] user_hints = sum(loads(user_data_str)['hints'].values()) else: user_progress = list() user_voids = list() user_hints = 0 user_score = 0 if len(user_progress) + len(user_voids) == len(puzzles) - 1: if GIVEN_HINTS - user_hints == 1: result = f'Right answer! Congratulations @{user_name}! You have completed the whole puzzle! Your final score is {int(user_score) + puzzles[puzzle_idx].score + HINT_POINTS*(GIVEN_HINTS - user_hints)} because you had extra {HINT_POINTS} points from the {GIVEN_HINTS - user_hints} unused hint! Nicely done!' elif GIVEN_HINTS - user_hints != 0: result = f'Right answer! Congratulations @{user_name}! You have completed the whole puzzle! Your final score is {int(user_score) + puzzles[puzzle_idx].score + HINT_POINTS*(GIVEN_HINTS - user_hints)} because you had extra {HINT_POINTS} points from each of the {GIVEN_HINTS - user_hints} unused hints! Nicely done!' else: result = f'Right answer! Congratulations @{user_name}! You have completed the whole puzzle! Your final score is {int(user_score) + puzzles[puzzle_idx].score}. Woohoo!' elif len(user_progress) + len(user_voids) == len(puzzles) - 2: result = f'Right answer! Congratulations @{user_name}! You have unlocked the final puzzle! Your score is currently {int(user_score) + puzzles[puzzle_idx].score}.' elif user_progress: result = f'Right answer! Congratulations @{user_name}! You have solved {len(user_progress) + 1} puzzles and your score is now {int(user_score) + puzzles[puzzle_idx].score}!' else: result = f'Right answer! Congratulations @{user_name}! You have solved 1 puzzle and your score is now {int(user_score) + puzzles[puzzle_idx].score}!' puzzles[puzzle_idx].is_completed = True puzzles[puzzle_idx].set_completed_title() save_user_progress(str(user_id), context, False) else: keyboard = [[ InlineKeyboardButton(text='Try again 🔄', callback_data='try_again') ], [ InlineKeyboardButton(text='Void this puzzle ❌', callback_data='ask_void'), InlineKeyboardButton(text='Ask for hint ❓', callback_data='ask_hint') ]] + keyboard result = 'Sorry, wrong answer! Want to try again, void the puzzle, or ask for a hint?' reply_markup = InlineKeyboardMarkup(keyboard) update.message.reply_text(result, reply_markup=reply_markup) return CHOOSE_CONTINUE_OPTION
def hint(update, context): user_id = update.effective_user.id puzzles = context.chat_data[user_id] puzzle_idx = context.user_data['cur_puzzle_idx'] puzzle_hints = puzzles[puzzle_idx].hints query = update.callback_query query.answer() bot = context.bot keyboard = [[ InlineKeyboardButton(text='Try this puzzle 🧩', callback_data='try'), InlineKeyboardButton(text='Back to puzzles\' list 📃', callback_data='back') ], [ InlineKeyboardButton(text='Void this puzzle ❌', callback_data='ask_void'), InlineKeyboardButton(text='Ask for hint ❓', callback_data='ask_hint') ], [InlineKeyboardButton(text='Done ✔️', callback_data='done')]] reply_markup = InlineKeyboardMarkup(keyboard) user_data_str = read_dp(str(user_id)) if user_data_str: user_score = int(loads(user_data_str)['score']) user_hints = sum(loads(user_data_str)['hints'].values()) hint_index = loads(user_data_str)['hints'].get(puzzle_idx, 0) else: user_score = 0 user_hints = 0 hint_index = 0 if puzzles[puzzle_idx].used_hints < len( puzzle_hints) and GIVEN_HINTS - user_hints >= 1: bot.delete_message(chat_id=user_id, message_id=query.message.message_id) bot.send_message( user_id, f'Hint #{hint_index+1} for "{puzzles[puzzle_idx].name}"\n\n{puzzle_hints[hint_index]}' ) puzzles[puzzle_idx].used_hints += 1 save_user_progress(str(user_id), context, True) # Must reread progress user_data_str = read_dp(str(user_id)) if user_data_str: user_score = int(loads(user_data_str)['score']) user_hints = sum(loads(user_data_str)['hints'].values()) else: user_score = 0 user_hints = 0 if GIVEN_HINTS - user_hints == 1: s = '' else: s = 's' text = f'That was a hint for the puzzle! Hope it helps!\n\nYour score is now {user_score} and you have {GIVEN_HINTS-user_hints} unused hint{s} remaining.' else: if GIVEN_HINTS - user_hints == 1: s = '' else: s = 's' # You have not enough hints if GIVEN_HINTS - user_hints == 0: text = f'You have no more available hints!\n\nYour score is still {user_score}.' # You have asked for all the puzzle's hint(s) else: text = f'The puzzle has no more hints!\n\nYour score is still {user_score} and you still have {GIVEN_HINTS-user_hints} unused hint{s} remaining.' try: query.edit_message_text( f'{text}\n\nShowing "{puzzles[puzzle_idx].name}".', reply_markup=reply_markup) except: query.message.reply_text( f'{text}\n\nShowing "{puzzles[puzzle_idx].name}".', reply_markup=reply_markup) return CHOOSE_OPTION
def choose_puzzle(update, context): query = update.callback_query user_id = update.effective_user.id query.answer() puzzle_idx = query.data puzzles = context.chat_data[user_id] # We need to check whether the selected puzzle is the final puzzle user_data_str = read_dp(str(user_id)) if user_data_str: user_progress = loads(user_data_str)['progress'] user_voids = loads(user_data_str)['voids'] else: user_progress = list() user_voids = list() bot = context.bot # If it is not the final puzzle or the final puzzle is already unlocked if not puzzles[puzzle_idx].is_final or len(user_progress) + len( user_voids) >= len(puzzles) - 1: context.user_data['cur_puzzle_idx'] = puzzle_idx context.user_data['score'] = puzzles[puzzle_idx].score context.user_data['username'] = update.effective_user.username context.user_data['is_voided'] = puzzles[puzzle_idx].is_voided name = puzzles[puzzle_idx].name description = puzzles[puzzle_idx].description is_completed = puzzles[puzzle_idx].is_completed is_voided = puzzles[puzzle_idx].is_voided bot.delete_message(chat_id=user_id, message_id=query.message.message_id) keyboard = [[ InlineKeyboardButton(text='Try this puzzle 🧩', callback_data='try'), InlineKeyboardButton(text='Back to puzzles\' list 📃', callback_data='back') ], [ InlineKeyboardButton(text='Void this puzzle ❌', callback_data='ask_void'), InlineKeyboardButton(text='Ask for hint ❓', callback_data='ask_hint') ], [ InlineKeyboardButton(text='Done ✔️', callback_data='done') ]] txt = [f'Showing "{name}".'] # Update response for completed puzzle if is_completed or is_voided: # We can set the index to any number as long as there is no IndexError first_answer = puzzles[puzzle_idx].answers[0] if is_completed: txt.append( f'\nYou already completed this puzzle! The answer was "{first_answer}".' ) elif is_voided: # txt.append(f'\nYou already voided this puzzle!') txt.append( f' You already voided this puzzle! No way back, but the answer was "{first_answer}".\n' ) keyboard = [[keyboard[0][1], keyboard[2][0]]] # only back and done reply_markup = InlineKeyboardMarkup(keyboard) context.user_data['last_description'] = send_description( description, user_id, bot) query.message.reply_text(text=''.join(txt), reply_markup=reply_markup) return CHOOSE_OPTION # Else, the locked final puzzle is selected else: reply_markup = get_options_keyboard(context.chat_data, user_id) try: query.edit_message_text( 'Final puzzle still locked! Choose another puzzle to view...', reply_markup=reply_markup) except: pass # unmodified message return CHOOSE_PUZZLE
def back_to_puzzle(update, context): # When this method is executed, it is guaranteed that the puzzle is neither completed nor voided. query = update.callback_query user_id = update.effective_user.id query.answer() puzzle_idx = context.user_data['cur_puzzle_idx'] puzzles = context.chat_data[user_id] user_data_str = read_dp(str(user_id)) if user_data_str: user_progress = loads(user_data_str)['progress'] user_voids = loads(user_data_str)['voids'] else: user_progress = list() user_voids = list() bot = context.bot context.user_data['cur_puzzle_idx'] = puzzle_idx context.user_data['score'] = puzzles[puzzle_idx].score context.user_data['username'] = update.effective_user.username context.user_data['is_voided'] = puzzles[puzzle_idx].is_voided name = puzzles[puzzle_idx].name description = puzzles[puzzle_idx].description is_completed = puzzles[puzzle_idx].is_completed is_voided = puzzles[puzzle_idx].is_voided try: last_description = context.user_data['last_description'] bot.delete_message(chat_id=user_id, message_id=last_description.message_id) except: pass bot.delete_message(chat_id=user_id, message_id=query.message.message_id) keyboard = [[ InlineKeyboardButton(text='Try this puzzle 🧩', callback_data='try'), InlineKeyboardButton(text='Back to puzzles\' list 📃', callback_data='back') ], [ InlineKeyboardButton(text='Void this puzzle ❌', callback_data='ask_void'), InlineKeyboardButton(text='Ask for hint ❓', callback_data='ask_hint') ], [InlineKeyboardButton(text='Done ✔️', callback_data='done')]] txt = [f'Showing "{name}".'] # Update response for completed puzzle reply_markup = InlineKeyboardMarkup(keyboard) context.user_data['last_description'] = send_description( description, user_id, bot) query.message.reply_text(text=''.join(txt), reply_markup=reply_markup) return CHOOSE_OPTION
import json from env import DP_URL from env2 import actual_run from dpad_manager import read_dp def read_json(filename): datafile = open(filename, 'r', encoding='utf-8') return json.loads(datafile.read()) # Data format: dictionary with key = LB name, value = DontPad data # lb_data = read_json("game_data/leaderboard.json") lb_data = dict( map(lambda x: (x[0], json.loads(read_dp(x[1]))), actual_run.items())) # Data cleaning new_lb_data = [] for k, v in lb_data.items(): new_lb_data.append([k, v['score'], v['solved_time']]) # Old sorting key: sort by score descending, then for the same score sort by time taken to solve each puzzle ascending. # new_lb_data.sort(key = lambda x:[-int(x[1]),[x[2][0]]+[x[2][i]-x[2][i-1] for i in range(1,len(x[2]))]]) # New sorting key: sort by score descending, then for the same score sort by total time taken to solve the last puzzle until the first puzzle ascending. new_lb_data.sort(key=lambda x: [-int(x[1]), x[2][::-1]]) # Update content before final output new_lb_data = list(map(lambda x: x[0] + ": " + x[1], new_lb_data))