def display_arabic_add_subtract_problem(screen, color, operands, font): operand_rows = [format_operand(operand) for operand in operands] max_length = max(len(row) for row in operand_rows) operand_rows.append('-' * max_length) text = '\n'.join(operand_rows) response_x, response_y, width = display_centered_text( screen, text, color, font, ) return response_x, response_y, width
def give_problem( operands, result_file, font_size=100, frames_per_second=20, font=None, bead_color=GREEN, separator_bead_color=ORANGE, prior_response_time=None, number_style=NumberStyle.ARABIC, language='en', ): if font is None: font = pygame.font.SysFont( 'Lucida Console', font_size ) column_width = height_to_width(font_size) clock = pygame.time.Clock() entered_digits = [] # wait for start while True: screen.fill(BLACK) exit_while = False if prior_response_time: display_centered_text( screen, '{:.2f}'.format(prior_response_time), bead_color, font, ) for event in pygame.event.get(): if event.type == pygame.KEYDOWN: if event.key == pygame.K_q: return True, None start_time = pygame.time.get_ticks() exit_while = True if exit_while: break pygame.display.flip() clock.tick(frames_per_second) # present problem and collect response read = True while True: if read and number_style == NumberStyle.VERBAL: read_problem( operands, inter_operand_pause=2., language=language ) read = False screen.fill(BLACK) if number_style == NumberStyle.ABACUS: x_response, y_response = display_abacus_add_subtract_problem( screen, bead_color, separator_bead_color, (25, 25), font_size, operands, font=font, ) draw_columns( screen, bead_color, (x_response - len(entered_digits) * column_width, y_response), font_size, entered_digits, separator_bead_color=separator_bead_color, ) elif number_style == NumberStyle.ARABIC: ( x_response, y_response, width ) = display_arabic_add_subtract_problem( screen, bead_color, operands, font ) surface = font.render( format_operand(numerify(entered_digits)), True, bead_color ) screen.blit( surface, (x_response + width - surface.get_width(), y_response) ) elif number_style == NumberStyle.VERBAL: display_centered_text( screen, format_number(numerify(entered_digits)), bead_color, font, ) else: pass for event in pygame.event.get(): if event.type == pygame.KEYDOWN: collect_digits(entered_digits, event.key) if event.key in ENTER_KEYS: response_time = ( pygame.time.get_ticks() - start_time ) / 1000. correct, response = check_response( entered_digits, operands ) write_problem_result( result_file, operands, response, response_time, correct, number_style, ) if correct: return False, response_time else: start_time = pygame.time.get_ticks() entered_digits.clear() read = True elif event.key == pygame.K_q: return True, None else: pass pygame.display.flip() clock.tick(frames_per_second)
def multiplication_and_division_loop( screen, background_color, foreground_color, fps=20, font=None, n_digits=3, operation='mult' ): filename = '{:%Y_%m_%d}_{}.dat'.format( datetime.datetime.today(), operation, ) response_time = None clock = pygame.time.Clock() font_size = 100 font = font or pygame.font.SysFont('Lucida Console', font_size) with open(filename, 'a') as stream: while True: # See if user wants to do another another = False while True: screen.fill(background_color) if response_time: display_centered_text( screen, '{:.2f}'.format(response_time), foreground_color, font ) pygame.display.flip() clock.tick(fps) for event in pygame.event.get(): if event.type == pygame.KEYDOWN: if event.key == pygame.K_q: return else: another = True if another: break o1, o2 = np.random.randint(low=1, high=10**n_digits, size=2) o3 = o1 * o2 while True: end, response_time = give_multiplication_or_division_problem( o1, o2, o3, screen, stream, background_color, foreground_color, fps=fps, font=font, operation=operation, ) if end: break
def give_multiplication_or_division_problem( o1, o2, o3, screen, result_stream, background_color, foregrount_color, fps=20, font=None, font_size=100, operation='mult', ): if font is None: font = pygame.font.SysFont( 'Lucida Console', font_size ) n_digits = max(len(digitize(o1)), len(digitize(o2))) clock = pygame.time.Clock() start_time = pygame.time.get_ticks() entered_digits = [] response = None response_time = None response_entered = False response_correct = False while True: screen.fill(background_color) if operation == 'mult': columns = 2 * n_digits + max(2 * n_digits - 1, 0) // 3 display_centered_text( screen, ' {}\nx {}\n{}\n {}'.format( format_number(o1, columns=columns, sign=False), format_number(o2, columns=columns, sign=False), '-' * (columns + 2), format_number(numerify(entered_digits), columns=columns, sign=False), ), foreground_color, font, ) else: display_centered_text( screen, '{} / {}\n= {} '.format( o3, o2, numerify(entered_digits) ), foreground_color, font, ) pygame.display.flip() for event in pygame.event.get(): if event.type == pygame.KEYDOWN: collect_digits(entered_digits, event.key) if event.key in ENTER_KEYS: response_time = (pygame.time.get_ticks() - start_time) / 1000. response_entered = True response = numerify(entered_digits) if operation == 'mult': response_correct = (response == o3) else: response_correct = (response == o1) if response_entered: write_multiplication_or_division_result( result_stream, o1, o2, o3, response, response_time, response_correct, operation=operation, ) if response_correct: return response_correct, response_time else: return response_correct, None clock.tick(fps)
def abacus_reading_problem( result_file, display_digits, flash_seconds, font, fps=20, ): n_digits = len(display_digits) column_width = height_to_width(font.get_height()) clock = pygame.time.Clock() x_display = .5 * ( SCREEN_WIDTH - n_digits * column_width ) y_display = .5 * (SCREEN_HEIGHT - font.get_height()) # display number for specified period of time screen.fill(BLACK) draw_columns( screen, GREY, # GREEN, (x_display, y_display), font.get_height(), display_digits, separator_bead_color=ORANGE, ) pygame.display.flip() pygame.time.wait(int(1000 * flash_seconds)) # get response entered_digits = [] clock = pygame.time.Clock() break_out = False while True: screen.fill(BLACK) for event in pygame.event.get(): if event.type == pygame.KEYDOWN: collect_digits(entered_digits, event.key) if event.key in ENTER_KEYS: break_out = True is_correct = ( entered_digits == display_digits ) if break_out: break x_display = .5 * ( SCREEN_WIDTH - len(entered_digits) * column_width ) draw_columns( screen, GREY, # GREEN, (x_display, y_display), font.get_height(), entered_digits, separator_bead_color=ORANGE, ) pygame.display.flip() clock.tick(fps) # Display whether correct or not screen.fill(BLACK) display_centered_text( screen, 'Correct' if is_correct else 'Incorrect', GREY, font, ) pygame.display.flip() pygame.time.wait(750) return is_correct, numerify(entered_digits)