int
main(int argc, char *argv[])
{
    int error = 0;
    Context ctx;

    if (argc < 4) {
        fprintf(stderr, "Correct usage %s <config_file> <data_file> <engine>\n",
            argv[0]);
        return -1;
    }

    if (!_read_config(&ctx, argv[1]))
        return -1;

    ctx.f = fopen(argv[2], "r");
    if (!ctx.f) {
        fprintf(stderr, "Failed to open %s\n", argv[1]);
        return -1;
    }

    ctx.sml_engine = atoi(argv[3]);
    ctx.sml = _sml_new(ctx.sml_engine);
    ctx.reads = ctx.rights = ctx.predictions = 0;
    if (!ctx.sml || !_initialize_sml(&ctx)) {
        fprintf(stderr, "Failed to initialize sml\n");
        error = -1;
        goto end;
    }

    while (_read_data(&ctx)) {
        _do_prediction(&ctx);
        ctx.first_train = true;
        if ((error = sml_process(ctx.sml))) {
            fprintf(stderr, "sml_process error number %d\n", error);
            break;
        }

        ctx.first_train = false;
        if ((error = sml_process(ctx.sml))) {
            fprintf(stderr, "sml_process error number %d\n", error);
            break;
        }
    }

    sml_print_debug(ctx.sml, false);
    printf("Right guesses: %d of %d (%d games) \n", ctx.rights,
        ctx.predictions, ctx.reads);
    printf("Right predictions percentage:%f%%\n",
        ctx.rights * 100.0 / ctx.reads);
    printf("Total right predictions percentage:%f%%\n",
        ctx.rights * 100.0 / ctx.predictions);
    sml_free(ctx.sml);
    _free_players(ctx.players, ctx.num_players);

end:
    fclose(ctx.f);
    return error;
}
static bool
_read_config(Context *ctx, const char *filename)
{
    uint16_t i;
    FILE *f;
    size_t line_len;
    int num_players;

    f = fopen(filename, "r");
    if (!f) {
        fprintf(stderr, "Failed to open the config file: %s\n", filename);
        return false;
    }

    if (!_read_next_line(ctx->line, LINE_SIZE, f))
        goto config_error;

    num_players = atoi(ctx->line);
    if (num_players < MIN_PLAYERS) {
        fprintf(stderr, "%d is not enough players.\n", num_players);
        goto config_error;
    } else if (num_players > UINT16_MAX) {
        fprintf(stderr, "%d is not greater than %d.\n", num_players,
            UINT16_MAX);
        goto config_error;
    }

    ctx->num_players = num_players;

    printf("%d players:\n", ctx->num_players);
    ctx->players = calloc(ctx->num_players, sizeof(char *));
    for (i = 0; i < ctx->num_players; i++) {
        if (!_read_next_line(ctx->line, LINE_SIZE, f)) {
            _free_players(ctx->players, i);
            goto config_error;
        }

        line_len = strlen(ctx->line);
        ctx->line[line_len - 1] = 0;
        ctx->players[i] = malloc(strlen(ctx->line) + 100);
        strncpy(ctx->players[i], ctx->line, line_len);
        printf("\t%s\n", ctx->players[i]);
    }
    printf("\n");

    fclose(f);
    return true;

config_error:
    fclose(f);
    return false;
}