<commit_before>#ifndef TCFRAME_RUNNER_H
#define TCFRAME_RUNNER_H

#include "generator.hpp"
#include "macro.hpp"
#include "submitter.hpp"

#include <getopt.h>
#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::string;

namespace tcframe {

enum RunnerMode {
    GENERATION,
    SUBMISSION
};

template<typename TProblem>
class Runner {
public:
    Runner(int argc, char** argv)
            : argc(argc), argv(argv), mode(RunnerMode::GENERATION), isPorcelain(0) { }

    void setGenerator(BaseGenerator<TProblem>* generator) {
        this->generator = generator;
    }

    void applyCommandLineOptions() {
        option longopts[5] = {
                { "slug", required_argument, nullptr, 's'},
                { "tc-dir", required_argument, nullptr, 'd'},
                { "solution-command", required_argument, nullptr, 'c'},
                { "porcelain", no_argument, &isPorcelain, 1},
                { 0, 0, 0, 0 }
        };

        int c;
        while ((c = getopt_long(argc, argv, "", longopts, nullptr)) != -1) {
            switch (c) {
                case 's':
                    generator->setSlug(string(optarg));
                    break;
                case 'd':
                    generator->setTestCasesDir(string(optarg));
                    break;
                case 'c':
                    generator->setSolutionCommand(string(optarg));
                    break;
                case '?':
                case ':':
                    exit(1);
                default:
                    break;
            }
        }
    }

    int run() {
        if (argc > 1 && string(argv[1]) == "submit") {
            mode = RunnerMode::SUBMISSION;

            if (argc == 2) {
                submissionCommand = generator->getSolutionCommand();
                argc--;
                argv++;
            } else {
                submissionCommand = string(argv[2]);
                argc -= 2;
                argv += 2;
            }
        }

        generator->applyConfiguration();

        applyCommandLineOptions();

        if (mode == RunnerMode::GENERATION) {
            return generator->generate();
        } else {
            Submitter<TProblem>* submitter = new Submitter<TProblem>(generator);
            submitter->setPorcelain((bool) isPorcelain);
            return submitter->submit(submissionCommand);
        }
    }

private:
    int argc;
    char** argv;

    RunnerMode mode;
    string submissionCommand;

    int isPorcelain;

    BaseGenerator<TProblem>* generator;
};

}

#endif<commit_msg>Fix arguments handling for runner commands<commit_after>#ifndef TCFRAME_RUNNER_H
#define TCFRAME_RUNNER_H

#include "generator.hpp"
#include "macro.hpp"
#include "submitter.hpp"

#include <getopt.h>
#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::string;

namespace tcframe {

enum RunnerMode {
    GENERATION,
    SUBMISSION
};

template<typename TProblem>
class Runner {
public:
    Runner(int argc, char** argv)
            : argc(argc), argv(argv), mode(RunnerMode::GENERATION), isPorcelain(0) { }

    void setGenerator(BaseGenerator<TProblem>* generator) {
        this->generator = generator;
    }

    void applyCommandLineOptions() {
        option longopts[5] = {
                { "slug", required_argument, nullptr, 's'},
                { "tc-dir", required_argument, nullptr, 'd'},
                { "solution-command", required_argument, nullptr, 'c'},
                { "porcelain", no_argument, &isPorcelain, 1},
                { 0, 0, 0, 0 }
        };

        int c;
        while ((c = getopt_long(argc, argv, "", longopts, nullptr)) != -1) {
            switch (c) {
                case 's':
                    generator->setSlug(string(optarg));
                    break;
                case 'd':
                    generator->setTestCasesDir(string(optarg));
                    break;
                case 'c':
                    generator->setSolutionCommand(string(optarg));
                    break;
                case '?':
                case ':':
                    exit(1);
                default:
                    break;
            }
        }

        args.clear();
        for (int i = optind; i < argc; i++) {
            args.push_back(string(argv[i]));
        }
    }

    int run() {
        string program = argv[0];

        if (argc > 1) {
            if (string(argv[1]) == "submit") {
                mode = RunnerMode::SUBMISSION;
                argc--;
                argv++;
            } else if (argv[1][0] != '-') {
                cout << "Unknown runner command: " << string(argv[1]) << endl;
                return 1;
            }
        }

        generator->applyConfiguration();

        applyCommandLineOptions();

        if (mode == RunnerMode::GENERATION) {
            return generator->generate();
        } else {
            if (args.size() > 1) {
                cout << "Usage: " << program << " submit [ <submissionCommand> ]" << endl;
                return 1;
            }

            string submissionCommand;
            if (args.empty()) {
                submissionCommand = generator->getSolutionCommand();
            } else {
                submissionCommand = args[0];
            }

            Submitter<TProblem>* submitter = new Submitter<TProblem>(generator);
            submitter->setPorcelain((bool) isPorcelain);
            return submitter->submit(submissionCommand);
        }
    }

private:
    int argc;
    char** argv;
    vector<string> args;

    RunnerMode mode;

    int isPorcelain;

    BaseGenerator<TProblem>* generator;
};

}

#endif
{'fraction_non_alphanumeric': 0.1254839845124956, 'fraction_numerical': 0.00598380851812742, 'mean_word_length': 1.6273693943596856, 'pattern_counts': {'":': 0, '<': 36, '<?xml version=': 0, '>': 42, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5752426', 'n_tokens_mistral': 1680, 'n_tokens_neox': 1556, 'n_words': 338}