def run_app(renew_log=False):
    print(
        '========================================================================'
    )
    print(APP_WELCOME)
    print(
        '========================================================================'
    )
    print('\n')

    # calculating secret length according to poly degree and crc
    secret_length = len(
        generate_smallest_secret(
            POLY_DEGREE, CRC_LENGTH, min_size=128, echo=False)) * 8
    # initialize log
    if not os.path.exists('out'):
        os.makedirs('out')
    if renew_log:
        initialize_app_log(LOG_FILE_APP)
    running = True
    while running:
        # list options for user
        print(APP_CHOOSE_FUNCTION)
        for key in APP_FUNCTIONAILTIES.keys():
            print("%s: %s" % (key, APP_FUNCTIONAILTIES[key]))
        print()

        # get input option from user
        correct_option = False
        input_option = ''
        while not correct_option:
            input_option = input(APP_DESIRED_OPTION)
            if input_option not in APP_FUNCTIONAILTIES.keys():
                print(APP_OPTION_FALSE)
            else:
                correct_option = True

        # create DB handler
        db_handler = DBHandler()
        # initiate log
        app_log_dict = dict()
        initialize_app_log_dict(app_log_dict)
        # Exit application
        if input_option == list(APP_FUNCTIONAILTIES.keys())[2]:
            running = False
            print(APP_BYE)
        # Enroll new fingerprint
        elif input_option == list(APP_FUNCTIONAILTIES.keys())[0]:
            app_log_dict['action'] = 'ENCODE'
            new_id = get_id()
            app_log_dict['vault_id'] = new_id
            print(APP_SCAN_FP)
            # Scanning fingerprint, recapture if not enough good minutiae
            good_fp = False
            capture_time_start = time.time()
            capture_time_end = time.time()
            while not good_fp:
                capture_time_start = time.time()
                good_fp = capture_new_fp_xyt(new_id)
                capture_time_end = time.time()
                if not good_fp:
                    print(APP_RETRY_FP)
            app_log_dict['capture_time'] = round(
                capture_time_end - capture_time_start, 2)
            action_fp_time = time.time()
            enroll_new_fingerprint(
                db_handler, new_id,
                FP_TEMP_FOLDER + FP_OUTPUT_NAME + new_id + '.xyt',
                app_log_dict)
            print('\n')
            print(
                'Execution time fuzzy vault algorithm including DB: {}'.format(
                    round(time.time() - action_fp_time, 2)))
            write_app_log(LOG_FILE_APP, app_log_dict)
            remove_temp_files(new_id)
        # Verify fingerprint
        elif input_option == list(APP_FUNCTIONAILTIES.keys())[1]:
            app_log_dict['action'] = 'DECODE'
            id_to_verify = get_id()
            app_log_dict['vault_id'] = id_to_verify
            print(APP_SCAN_FP)
            # Scanning fingerprint, recapture if not enough good minutiae
            good_fp = False
            while not good_fp:
                capture_time_start = time.time()
                good_fp = capture_new_fp_xyt(id_to_verify)
                capture_time_end = time.time()
                if not good_fp:
                    print(APP_RETRY_FP)
            app_log_dict['capture_time'] = round(
                capture_time_end - capture_time_start, 2)
            action_fp_time = time.time()
            verify_fingerprint(
                db_handler, id_to_verify,
                FP_TEMP_FOLDER + FP_OUTPUT_NAME + id_to_verify + '.xyt',
                secret_length, app_log_dict)
            print('\n')
            print(
                'Execution time fuzzy vault algorithm including DB: {}'.format(
                    round(time.time() - action_fp_time, 2)))
            write_app_log(LOG_FILE_APP, app_log_dict)
            remove_temp_files(id_to_verify)
        else:
            print(APP_ERROR)
        print(
            '========================================================================'
        )
        print('\n')
        time.sleep(1)
        db_handler.close_handler()
def run_experiment_single(db_path, log_parameter_file, log_db_file, gallery_xyt, probe_xyt,
                          log_flag=True, echo=False, number=0):
    """
    Run experiment and match gallery with probe xyt once
    :param db_path: path where xyt paths are stored
    :param log_parameter_file: name of log file to save parameters
    :param log_db_file: name of log file to save db results
    :param gallery_xyt: name of gallery xyt file
    :param probe_xyt: name of probe xyt file
    :param log_flag: log functionality
    :param echo: if True, printing intermediate messages to console
    :param number: experiment run number
    :param number: number of experiment
    :returns: True if match is found (gallery is same finger as probe)
    """

    def log_parameters():
        too_few_minutia = False
        with open(log_parameter_file, 'a') as log:
            versus = '{} vs {}'.format(probe_xyt, gallery_xyt)
            minutiae_candidates = log_dict['minutiae_candidates']
            total_subsets = log_dict['total_subsets']
            evaluated_subsets = log_dict['evaluated_subsets']
            amount_geom = log_dict['amount_geom_table']
            t_geom_creation = log_dict['geom_creation_time']
            t_interpol = log_dict['time_interpolation']
            t_geom = log_dict['time_geom']
            tries_geom = log_dict['geom_match_tries']
            single_matches_geom = log_dict['geom_single_match']
            geom_iteration = log_dict['geom_iteration']
            if log_dict['too_few_minutiae_gallery']:
                too_few_minutia = True
                gallery_basis_str = 'Invalid'
                probe_basis_str = 'No Basis'
            elif log_dict['too_few_minutiae_probe']:
                too_few_minutia = True
                gallery_basis_str = 'No Basis'
                probe_basis_str = 'Invalid'
            else:
                gallery_basis_str = print_minutia_basis(log_dict['geom_gallery_basis'])
                probe_basis_str = print_minutia_basis(log_dict['geom_probe_basis'])
            thresholds = log_dict['thresholds']
            t_encode = round(t_middle - t_start, 2) if not too_few_minutia else 0
            t_decode = round(t_end - t_middle, 2) if not too_few_minutia else 0
            t_total = round(t_end - t_start, 2) if not too_few_minutia else 0
            subset_eval = 'Subsets random' if log_dict['subset_eval_random'] else 'Subsets precomputed'
            log.write('{};{};{};{};{};{};{};{};{};{};{};{};{};{};{};{};{};{};{};{};{};{}\n'.format(
                versus, Constants.POLY_DEGREE, Constants.MINUTIAE_POINTS_AMOUNT, Constants.CHAFF_POINTS_AMOUNT,
                thresholds,
                secret_length + CRC_LENGTH, minutiae_candidates, total_subsets, evaluated_subsets,
                t_encode, t_decode, round(t_geom_creation, 2),
                round(t_interpol, 2), round(t_geom, 2), t_total, tries_geom, single_matches_geom,
                amount_geom, geom_iteration, gallery_basis_str, probe_basis_str, subset_eval
            ))

    def log_database_matches(match):
        # log result
        with open(log_db_file, 'a') as log_db:
            gallery_str = gallery_xyt.replace('.xyt', '')
            probe_str = probe_xyt.replace('.xyt', '')
            gallery_finger, gallery_capture = gallery_str.split('_')
            probe_finger, probe_capture = probe_str.split('_')
            if match:
                match_str = "wahr"
            else:
                match_str = "falsch"
            if log_dict['too_few_minutiae_gallery']:
                match_str = "invalid gallery"
            if log_dict['too_few_minutiae_probe']:
                match_str = "invalid probe"
            log_db.write('{g_f};{g_c};{p_f};{p_c};{match_str}\n'.format(
                g_f=gallery_finger, g_c=gallery_capture, p_f=probe_finger, p_c=probe_capture, match_str=match_str))

    if echo:
        print('==========================================================')
        print('Run {xyt_g} vs {xyt_p}'.format(xyt_g=gallery_xyt, xyt_p=probe_xyt))
        print('==========================================================')

    # time execution
    t_start = time.time()

    # create DB handler
    db_handler = DBHandler()
    # create dict for logging purposes and initiate all default values
    log_dict = dict()
    initialize_log_dict(log_dict, number=number)

    # calculate secret according to polynomial degree. secret has to be able to be encoded in bytes (*8)
    secret_bytes = generate_smallest_secret(Constants.POLY_DEGREE, CRC_LENGTH, min_size=128, echo=echo)
    secret_length = len(secret_bytes) * 8

    fuzzy_vault = generate_vault(db_path + gallery_xyt, Constants.MINUTIAE_POINTS_AMOUNT, Constants.CHAFF_POINTS_AMOUNT,
                                 Constants.POLY_DEGREE, secret_bytes, CRC_LENGTH, GF_2_M, log_dict, echo=echo)
    if not fuzzy_vault:
        if echo:
            print('Failure due to too few minutiae to generate vault...\n')
        log_dict['too_few_minutiae_gallery'] = True
        if log_flag:
            log_parameters()
            if log_db_file:
                log_database_matches(False)
        return

    if echo:
        print('Finished generating fuzzy vault')

    # generate random vault id
    vault_id = random.randint(1, 100)

    # send vault to database
    if SAVE_VAULT_TO_DB:
        store_in_cosmos_db(db_handler, fuzzy_vault, vault_id)

    # end of ENCODE and start of DECODE
    t_middle = time.time()

    t_start_geom_creation = time.time()
    # get vault from database
    if GET_VAULT_FROM_DB:
        db_vault = retrieve_from_cosmos_db(db_handler, vault_id)
        db_vault.create_geom_table()
        log_dict['geom_creation_time'] = round(time.time() - t_start_geom_creation, 2)
        success = verify_secret(db_path + probe_xyt, Constants.MINUTIAE_POINTS_AMOUNT, Constants.POLY_DEGREE,
                                CRC_LENGTH, secret_length, GF_2_M, db_vault, log_dict, echo=echo)
        db_vault.clear_vault()
    else:
        fuzzy_vault.create_geom_table()
        log_dict['geom_creation_time'] = round(time.time() - t_start_geom_creation, 2)
        success = verify_secret(db_path + probe_xyt, Constants.MINUTIAE_POINTS_AMOUNT, Constants.POLY_DEGREE,
                                CRC_LENGTH, secret_length, GF_2_M, fuzzy_vault, log_dict, echo=echo)
        fuzzy_vault.clear_vault()

    # finish time execution
    t_end = time.time()

    # log run
    if log_flag:
        log_parameters()
        if log_db_file:
            log_database_matches(success)

    # clear up
    log_dict.clear()
    db_handler.close_handler()

    if echo:
        print('Execution time: {} seconds'.format(int(t_end - t_start)))

        # prints SUCCESS or FAILURE
        if success:
            print("SUCCESS\n")
        else:
            print("FAILURE...\n")