def prepare_procedure(atcoder_client: AtCoderClient, problem: Problem, config: Config):
    workspace_root_path = config.code_style_config.workspace_dir
    template_code_path = config.code_style_config.template_file
    lang = config.code_style_config.lang
    pid = problem.get_alphabet()
    problem_dir_path = os.path.join(workspace_root_path, problem.get_contest().get_id(), pid)

    def emit_error(text):
        logger.error(with_color('Problem {}: {}'.format(pid, text), Fore.RED))

    def emit_warning(text):
        logger.warning('Problem {}: {}'.format(pid, text))

    def emit_info(text):
        logger.info('Problem {}: {}'.format(pid, text))
    if config.etc_config.skip_existing_problems:
        if os.path.exists(problem_dir_path):
            emit_info(f'Skipped preparation because the directory already exists: {problem_dir_path}')
            return
    emit_info('{} is used for template'.format(template_code_path))
    try:
        content = atcoder_client.download_problem_content(problem)
    except InputFormatDetectionError as e:
        emit_error('Failed to download input format.')
        raise e
    except SampleDetectionError as e:
        emit_error('Failed to download samples.')
        raise e
    if (len(content.get_samples()) == 0):
        emit_info('No samples.')
    else:
        os.makedirs(problem_dir_path, exist_ok=True)
        create_examples(content.get_samples(), problem_dir_path, config.etc_config.in_example_format, config.etc_config.out_example_format)
        emit_info('Created examples.')
    code_file_path = os.path.join(problem_dir_path, 'main.{}'.format(lang.extension))
    if os.path.exists(code_file_path):
        backup_id = 1
        while True:
            backup_name = '{}.{}'.format(code_file_path, backup_id)
            if (not os.path.exists(backup_name)):
                new_path = backup_name
                shutil.copy(code_file_path, backup_name)
                break
            backup_id += 1
        emit_info("Backup for existing code '{}' -> '{}'".format(code_file_path, new_path))
    try:
        prediction_result = predict_format(content)
        emit_info(with_color('Format prediction succeeded', Fore.LIGHTGREEN_EX))
    except (NoPredictionResultError, MultiplePredictionResultsError) as e:
        prediction_result = FormatPredictionResult.empty_result()
        if isinstance(e, NoPredictionResultError):
            msg = 'No prediction -- Failed to understand the input format'
        else:
            msg = 'Too many prediction -- Failed to understand the input format'
        emit_warning(with_color(msg, Fore.LIGHTRED_EX))
    constants = predict_constants(content.original_html)
    code_generator = config.code_style_config.code_generator
    with open(template_code_path, 'r') as f:
        template = f.read()
    create_code(code_generator(CodeGenArgs(template, prediction_result.format, constants, config.code_style_config)), code_file_path)
    emit_info('Saved code to {}'.format(code_file_path))
    metadata_path = os.path.join(problem_dir_path, 'metadata.json')
    Metadata(problem, os.path.basename(code_file_path), config.etc_config.in_example_format.replace('{}', '*'), config.etc_config.out_example_format.replace('{}', '*'), lang, constants.judge_method, constants.timeout).save_to(metadata_path)
    emit_info('Saved metadata to {}'.format(metadata_path))
    if (config.postprocess_config.exec_cmd_on_problem_dir is not None):
        emit_info(_message_on_execution(problem_dir_path, config.postprocess_config.exec_cmd_on_problem_dir))
        config.postprocess_config.execute_on_problem_dir(problem_dir_path)
    output_splitter()
def prepare_procedure(atcoder_client: AtCoderClient, problem: Problem, config: Config):
    workspace_root_path = config.code_style_config.workspace_dir
    template_code_path = config.code_style_config.template_file
    lang = config.code_style_config.lang
    pid = problem.get_alphabet()
    problem_dir_path = os.path.join(workspace_root_path, problem.get_contest().get_id(), pid)

    def emit_error(text):
        logger.error(with_color('Problem {}: {}'.format(pid, text), Fore.RED))

    def emit_warning(text):
        logger.warning('Problem {}: {}'.format(pid, text))

    def emit_info(text):
        logger.info('Problem {}: {}'.format(pid, text))
    if config.etc_config.skip_existing_problems:
        if os.path.exists(problem_dir_path):
            emit_info(f'Skipped preparation because the directory already exists: {problem_dir_path}')
            return
    emit_info('{} is used for template'.format(template_code_path))
    try:
        content = atcoder_client.download_problem_content(problem)
    except InputFormatDetectionError as e:
        emit_error('Failed to download input format.')
        raise e
    except SampleDetectionError as e:
        emit_error('Failed to download samples.')
        raise e
    if (len(content.get_samples()) == 0):
        emit_info('No samples.')
    else:
        os.makedirs(problem_dir_path, exist_ok=True)
        create_examples(content.get_samples(), problem_dir_path, config.etc_config.in_example_format, config.etc_config.out_example_format)
        emit_info('Created examples.')
    code_file_path = os.path.join(problem_dir_path, 'main.{}'.format(lang.extension))
    if os.path.exists(code_file_path):
        backup_id = 1
        while True:
            backup_name = '{}.{}'.format(code_file_path, backup_id)
            if (not os.path.exists(backup_name)):
                new_path = backup_name
                shutil.copy(code_file_path, backup_name)
                break
            backup_id += 1
        emit_info("Backup for existing code '{}' -> '{}'".format(code_file_path, new_path))
    try:
        prediction_result = predict_format(content)
        emit_info(with_color('Format prediction succeeded', Fore.LIGHTGREEN_EX))
    except (NoPredictionResultError, MultiplePredictionResultsError) as e:
        prediction_result = FormatPredictionResult.empty_result()
        if isinstance(e, NoPredictionResultError):
            msg = 'No prediction -- Failed to understand the input format'
        else:
            msg = 'Too many prediction -- Failed to understand the input format'
        emit_warning(with_color(msg, Fore.LIGHTRED_EX))
    constants = predict_constants(content.original_html)
    code_generator = config.code_style_config.code_generator
    with open(template_code_path, 'r') as f:
        template = f.read()
    create_code(code_generator(CodeGenArgs(template, prediction_result.format, constants, config.code_style_config)), code_file_path)
    emit_info('Saved code to {}'.format(code_file_path))
    metadata_path = os.path.join(problem_dir_path, 'metadata.json')
    Metadata(problem, os.path.basename(code_file_path), config.etc_config.in_example_format.replace('{}', '*'), config.etc_config.out_example_format.replace('{}', '*'), lang, constants.judge_method, constants.timeout).save_to(metadata_path)
    emit_info('Saved metadata to {}'.format(metadata_path))
    if (config.postprocess_config.exec_cmd_on_problem_dir is not None):
        emit_info(_message_on_execution(problem_dir_path, config.postprocess_config.exec_cmd_on_problem_dir))
        config.postprocess_config.execute_on_problem_dir(problem_dir_path)
    output_splitter()