
/**

This file has been automatically generated at 2026-04-15T13:45:15.903Z

Name:       Jutge API
Version:    2.0.0

Description:

Jutge API

Dependencies:

https://github.com/nlohmann/json
https://github.com/yhirose/cpp-httplib

Compilation:

g++ -std=c++20 program.cpp -l ssl -l crypto
g++ -I/opt/homebrew/include -std=c++20 program.cpp -l ssl -l crypto

**/



#ifndef JUTGE_API_CLIENT_H
#define JUTGE_API_CLIENT_H

// ensure https is available
#define CPPHTTPLIB_OPENSSL_SUPPORT

// includes
#include "httplib.h"
#include "json.hpp"
#include <fstream>
#include <map>
#include <optional>
#include <sstream>
#include <stdexcept>
#include <string>
#include <tuple>
#include <vector>

// extend JSON library to support std::optional
// see https://github.com/nlohmann/json?tab=readme-ov-file#how-do-i-convert-third-party-types
// and https://www.kdab.com/jsonify-with-nlohmann-json/

namespace nlohmann {

template <typename T>
struct adl_serializer<std::optional<T>> {
    static void to_json(json& j, const std::optional<T>& opt)
    {
        if (opt == std::nullopt) {
            j = nullptr;
        } else {
            j = *opt;
        }
    }

    static void from_json(const json& j, std::optional<T>& opt)
    {
        if (j.is_null()) {
            opt = std::nullopt;
        } else {
            opt = j.template get<T>();
        }
    }
};
}

namespace jutge_api_client {

using namespace std;
using json = nlohmann::json;

string JUTGE_API_SERVER = "https://api.jutge.org";

struct Meta {
    string token;
};

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Meta, token)

optional<Meta> meta = nullopt;

class UnauthorizedError : public runtime_error {
public:
    UnauthorizedError(const string& msg)
        : runtime_error(msg)
    {
    }
};

class InfoError : public runtime_error {
public:
    InfoError(const string& msg)
        : runtime_error(msg)
    {
    }
};

class NotFoundError : public runtime_error {
public:
    NotFoundError(const string& msg)
        : runtime_error(msg)
    {
    }
};

class InputError : public runtime_error {
public:
    InputError(const string& msg)
        : runtime_error(msg)
    {
    }
};

class ProcessingError : public runtime_error {
public:
    ProcessingError(const string& msg)
        : runtime_error(msg)
    {
    }
};

void throwError(const map<string, string>& error, const string& operation_id)
{
    // TODO: do something with operation_id
    string message = "Unknown error";
    auto it = error.find("message");
    if (it != error.end())
        message = it->second;

    if (error.at("name") == "UnauthorizedError") {
        throw UnauthorizedError(message);
    }
    if (error.at("name") == "InfoError") {
        throw InfoError(message);
    }
    if (error.at("name") == "NotFoundError") {
        throw NotFoundError(message);
    }
    if (error.at("name") == "InputError") {
        throw InputError(message);
    }
    throw std::runtime_error("Unknown error");
}

using Headers = map<string, string>;

struct Range {
    size_t start;
    size_t end;
};

struct Part {
    int id;
    Headers headers;
    string content;

    bool is_file()
    {
        const auto it = headers.find("Content-Disposition");
        return it != headers.end() && it->second.find(" filename=") != string::npos;
    }

    string get_filename()
    {
        const string& content_disposition = headers["Content-Disposition"];
        size_t pos1 = content_disposition.find(" filename");
        size_t pos2 = content_disposition.find("\"", pos1 + 1);
        size_t pos3 = content_disposition.find("\"", pos2 + 1);
        return content_disposition.substr(pos2 + 1, pos3 - pos2 - 1);
    }

    string get_name()
    {
        const string& content_disposition = headers["Content-Disposition"];
        size_t pos1 = content_disposition.find(" name");
        size_t pos2 = content_disposition.find("\"", pos1 + 1);
        size_t pos3 = content_disposition.find("\"", pos2 + 1);
        return content_disposition.substr(pos2 + 1, pos3 - pos2 - 1);
    }

    string get_content_type()
    {
        return headers["Content-Type"];
    }

    json get_json()
    {
        return json::parse(content);
    }
};

Headers get_headers(const string& body)
{
    Headers headers;
    size_t pos1 = 0;
    while (true) {
        size_t pos2 = body.find("\r\n", pos1);
        if (pos2 - pos1 == 0)
            break;
        string line = body.substr(pos1, pos2 - pos1);
        size_t pos = line.find(":");
        string key = line.substr(0, pos);
        string value = line.substr(pos + 2);
        headers[key] = value;
        pos1 = pos2 + 2;
    }
    return headers;
}

string get_boundary(const string& contentType)
{
    size_t pos1 = contentType.find("boundary=\"");
    size_t pos2 = contentType.find("\"", pos1 + 1);
    size_t pos3 = contentType.find("\"", pos2 + 1);
    return "--" + contentType.substr(pos2 + 1, pos3 - pos2 - 1);
}

vector<Part> get_parts(const httplib::Result& result)
{
    vector<Range> ranges;

    const auto it = result->headers.find("Content-Type");
    if (it == result->headers.end())
        return {};
    const string& boundary = get_boundary(it->second);

    const string& content = result->body;
    size_t pos = 0;
    while (true) {
        pos = content.find(boundary, pos);
        if (pos == string::npos)
            break;
        pos += boundary.size() + 2;
        size_t pos2 = content.find(boundary, pos);
        if (pos2 == string::npos)
            break;
        ranges.push_back({ pos, pos2 });
        pos = pos2;
    }

    vector<Part> parts;
    for (Range range : ranges) {
        Part part;
        part.id = parts.size() + 1;
        const string body = content.substr(range.start, range.end - range.start);
        part.headers = get_headers(body);
        size_t pos = body.find("\r\n\r\n");
        part.content = body.substr(pos + 4, body.size() - pos - 4 - 2);
        parts.push_back(part);
    }
    return parts;
}

using Blob = string;

using Files = vector<Blob>;

struct Download {
    Blob data;
    string name;
    string type;

    void write(string path)
    {
        ofstream file(path);
        file << data;
        file.close();
    }
};

using Downloads = vector<Download>;

tuple<json, Downloads> execute(const string& func, const json& ijson, const Files& ifiles)
{
    using namespace std;
    httplib::Client client(JUTGE_API_SERVER);

    json idata = {
        { "func", func },
        { "input", ijson },
    };
    if (meta)
        idata["meta"] = *meta;

    httplib::MultipartFormDataItems datas = {
        { "data", idata.dump(), "", "" },
        //{"file2", "{\n  \"world\", true\n}\n", "world.json", "application/json"},
    };
    for (int i = 0; i < ifiles.size(); ++i) {
        const string name = "file_" + to_string(i);
        datas.push_back({ name, ifiles[i], name, "" });
    }

    httplib::Headers headers;
    const char* jutge_domain = getenv("JUTGE_DOMAIN");
    if (jutge_domain) {
        headers.emplace("x-forwarded-host", jutge_domain);
    }
    const auto result = client.Post("/api", headers, datas);

    vector<Download> ofiles;
    json answer;

    vector<Part> parts = get_parts(result);
    for (Part part : parts) {
        if (part.is_file()) {
            const Download download = {
                part.content,
                part.get_filename(),
                part.get_content_type(),
            };
            ofiles.push_back(download);
        } else {
            answer = part.get_json();
        }
    }

    if (answer.contains("error")) {
        throwError(answer["error"], answer["operation_id"]);
    }
    return { answer["output"], ofiles };
}

} // end namespace jutge_api_client


// client

namespace jutge_api_client {

// models

struct CredentialsIn {
    std::string email;
    std::string password;
};

struct ExamCredentialsIn {
    std::string email;
    std::string password;
    std::string exam;
    std::string exam_password;
};

struct CredentialsOut {
    std::string token;
    std::string expiration;
    std::string user_uid;
    std::string error;
};

struct CredentialsWithUsernameIn {
    std::string username;
    std::string password;
};

struct Time {
    std::string full_time;
    int int_timestamp;
    float float_timestamp;
    std::string time;
    std::string date;
};

struct HomepageStats {
    int users;
    int problems;
    int submissions;
    int exams;
    int contests;
};

using ColorMapping = std::map<std::string, std::map<std::string, std::string>>;

struct ApiVersion {
    std::string version;
    std::string mode;
    std::string gitHash;
    std::string gitBranch;
    std::string gitDate;
};

struct RequestInformation {
    std::string url;
    std::string ip;
    std::string domain;
};

struct Language {
    std::string language_id;
    std::string eng_name;
    std::string own_name;
};

struct Country {
    std::string country_id;
    std::string eng_name;
};

struct Compiler {
    std::string compiler_id;
    std::string name;
    std::string language;
    std::string extension;
    std::optional<std::string> description;
    std::optional<std::string> version;
    std::optional<std::string> flags1;
    std::optional<std::string> flags2;
    std::optional<std::string> type;
    std::optional<std::string> warning;
    std::optional<std::string> status;
    std::optional<std::string> notes;
};

struct Driver {
    std::string driver_id;
};

struct Verdict {
    std::string verdict_id;
    std::string name;
    std::string description;
    std::string emoji;
};

struct Proglang {
    std::string proglang_id;
};

struct AllTables {
    std::map<std::string, Language> languages;
    std::map<std::string, Country> countries;
    std::map<std::string, Compiler> compilers;
    std::map<std::string, Driver> drivers;
    std::map<std::string, Verdict> verdicts;
    std::map<std::string, Proglang> proglangs;
};

struct ProblemSummary {
    std::string summary_1s;
    std::string summary_1p;
    std::string keywords;
    std::string model;
    float duration;
};

struct SolutionTags {
    std::string tags;
    std::string model;
    float duration;
};

struct BriefAbstractProblem {
    std::string problem_nm;
    std::optional<std::string> author;
    std::optional<std::string> author_email;
    std::optional<int> pub;
    std::optional<int> official;
    std::optional<std::string> compilers;
    std::optional<std::string> driver_id;
    std::optional<std::string> type;
    std::optional<std::string> deprecation;
    std::string created_at;
    std::string updated_at;
    std::optional<SolutionTags> solution_tags;
};

struct BriefProblem {
    std::string problem_id;
    std::string problem_nm;
    std::string language_id;
    std::string title;
    std::string original_language_id;
    std::optional<std::string> translator;
    std::optional<std::string> translator_email;
    std::optional<int> checked;
    std::optional<ProblemSummary> summary;
};

using BriefProblemDict = std::map<std::string, BriefProblem>;

struct AbstractProblem {
    std::string problem_nm;
    std::optional<std::string> author;
    std::optional<std::string> author_email;
    std::optional<int> pub;
    std::optional<int> official;
    std::optional<std::string> compilers;
    std::optional<std::string> driver_id;
    std::optional<std::string> type;
    std::optional<std::string> deprecation;
    std::string created_at;
    std::string updated_at;
    std::optional<SolutionTags> solution_tags;
    BriefProblemDict problems;
};

struct AbstractProblemSuppl {
    std::vector<std::string> compilers_with_ac;
    std::vector<std::string> proglangs_with_ac;
};

struct ProblemSuppl {
    std::vector<std::string> compilers_with_ac;
    std::vector<std::string> proglangs_with_ac;
    std::map<std::string, bool> official_solution_checks;
    json handler;
};

struct Problem {
    std::string problem_id;
    std::string problem_nm;
    std::string language_id;
    std::string title;
    std::string original_language_id;
    std::optional<std::string> translator;
    std::optional<std::string> translator_email;
    std::optional<int> checked;
    std::optional<ProblemSummary> summary;
    BriefAbstractProblem abstract_problem;
};

struct Testcase {
    std::string name;
    std::string input_b64;
    std::string correct_b64;
};

struct ProblemRich {
    std::string problem_id;
    std::string problem_nm;
    std::string language_id;
    std::string title;
    std::string original_language_id;
    std::optional<std::string> translator;
    std::optional<std::string> translator_email;
    std::optional<int> checked;
    std::optional<ProblemSummary> summary;
    BriefAbstractProblem abstract_problem;
    std::vector<Testcase> sample_testcases;
    std::string html_statement;
};

struct SearchResult {
    std::string problem_nm;
    float score;
};

using SearchResults = std::vector<SearchResult>;

struct AllKeys {
    std::vector<std::string> problems;
    std::vector<std::string> enrolled_courses;
    std::vector<std::string> available_courses;
    std::vector<std::string> lists;
};

struct Profile {
    std::string user_uid;
    std::string email;
    std::string name;
    std::optional<std::string> username;
    std::optional<std::string> nickname;
    std::optional<std::string> webpage;
    std::optional<std::string> description;
    std::optional<std::string> affiliation;
    std::optional<int> birth_year;
    int max_subsxhour;
    int max_subsxday;
    int administrator;
    int instructor;
    std::optional<std::string> parent_email;
    std::optional<std::string> country_id;
    std::string timezone_id;
    std::optional<std::string> compiler_id;
    std::optional<std::string> language_id;
};

struct NewProfile {
    std::string name;
    int birth_year;
    std::string nickname;
    std::string webpage;
    std::string affiliation;
    std::string description;
    std::string country_id;
    std::string timezone_id;
};

struct NewPassword {
    std::string oldPassword;
    std::string newPassword;
};

struct DateValue {
    int date;
    int value;
};

using HeatmapCalendar = std::vector<DateValue>;

using Distribution = std::map<std::string, int>;

struct AllDistributions {
    Distribution verdicts;
    Distribution compilers;
    Distribution proglangs;
    Distribution submissions_by_hour;
    Distribution submissions_by_weekday;
};

struct Dashboard {
    Distribution stats;
    HeatmapCalendar heatmap;
    AllDistributions distributions;
};

struct Submission {
    std::string problem_id;
    std::string submission_id;
    std::string compiler_id;
    std::optional<std::string> annotation;
    std::string state;
    std::string time_in;
    std::optional<std::string> veredict;
    std::optional<std::string> veredict_info;
    std::optional<std::string> veredict_publics;
    int ok_publics_but_wrong;
};

struct NewSubmissionIn {
    std::string problem_id;
    std::string compiler_id;
    std::string annotation;
};

struct NewSubmissionOut {
    std::string submission_id;
};

struct SubmissionAnalysis {
    std::string testcase;
    std::string execution;
    std::string verdict;
};

struct TestcaseAnalysis {
    std::string testcase;
    std::string execution;
    std::string verdict;
    std::string input_b64;
    std::string output_b64;
    std::string expected_b64;
};

struct GetGameResultIn {
    std::string problem_id;
    std::string submission_id;
};

struct MatchSchema {
    float seed;
    std::vector<float> status;
    std::vector<std::string> players;
    std::vector<float> scores;
};

struct ProblemSchema {
    std::string author;
    std::string description;
    std::string email;
    std::string gamename;
    std::string title;
    float version;
};

struct SubmissionSchema {
    std::string compiler_id;
    std::string description;
    std::string email;
    std::string problem_id;
};

struct GetGameResultOut {
    std::vector<MatchSchema> games;
    ProblemSchema problem;
    SubmissionSchema submission;
};

struct GetGameOutputIn {
    std::string problem_id;
    std::string submission_id;
    int game_id;
};

struct CodeMetrics {
    float comment_ratio;
    float cyclomatic_complexity;
    float fanout_external;
    float fanout_internal;
    float halstead_bugprop;
    float halstead_difficulty;
    float halstead_effort;
    float halstead_timerequired;
    float halstead_volume;
    float loc;
    float maintainability_index;
    float operands_sum;
    float operands_uniq;
    float operators_sum;
    float operators_uniq;
    float pylint;
    float tiobe;
    float tiobe_compiler;
    float tiobe_complexity;
    float tiobe_coverage;
    float tiobe_duplication;
    float tiobe_fanout;
    float tiobe_functional;
    float tiobe_security;
    float tiobe_standard;
};

struct PublicProfile {
    std::string email;
    std::string name;
    std::optional<std::string> username;
};

struct BriefCourse {
    std::string course_nm;
    std::optional<std::string> title;
    std::optional<std::string> description;
    std::optional<std::string> annotation;
    int pub;
    int official;
};

struct Course {
    std::string course_nm;
    std::optional<std::string> title;
    std::optional<std::string> description;
    std::optional<std::string> annotation;
    int pub;
    int official;
    PublicProfile owner;
    std::vector<std::string> lists;
};

struct ListItem {
    std::optional<std::string> problem_nm;
    std::optional<std::string> description;
};

struct BriefList {
    std::string list_nm;
    std::optional<std::string> title;
    std::optional<std::string> description;
    std::optional<std::string> annotation;
    int pub;
    int official;
};

struct List {
    std::string list_nm;
    std::optional<std::string> title;
    std::optional<std::string> description;
    std::optional<std::string> annotation;
    int pub;
    int official;
    std::vector<ListItem> items;
    PublicProfile owner;
};

struct ReadyExam {
    std::string exam_key;
    std::string title;
    std::string place;
    std::string description;
    std::string exp_time_start;
    int running_time;
    bool contest;
};

struct RunningExamProblem {
    std::string problem_nm;
    std::optional<std::string> icon;
    std::optional<std::string> caption;
    std::optional<int> weight;
};

struct RunningExamDocument {
    std::string document_nm;
    std::string title;
    std::string description;
};

struct RunningExam {
    std::string title;
    std::string description;
    std::string instructions;
    std::optional<std::string> time_start;
    std::string exp_time_start;
    int running_time;
    int contest;
    std::vector<RunningExamProblem> problems;
    std::vector<std::string> compilers;
    std::vector<RunningExamDocument> documents;
};

struct AbstractStatus {
    std::string problem_nm;
    int nb_submissions;
    int nb_pending_submissions;
    int nb_accepted_submissions;
    int nb_rejected_submissions;
    int nb_scored_submissions;
    std::string status;
};

struct Status {
    std::string problem_id;
    std::string problem_nm;
    int nb_submissions;
    int nb_pending_submissions;
    int nb_accepted_submissions;
    int nb_rejected_submissions;
    int nb_scored_submissions;
    std::string status;
};

struct Award {
    std::string award_id;
    std::string time;
    std::string type;
    std::string icon;
    std::string title;
    std::string info;
    std::optional<std::string> youtube;
    std::optional<Submission> submission;
};

struct BriefAward {
    std::string award_id;
    std::string time;
    std::string type;
    std::string icon;
    std::string title;
    std::string info;
    std::optional<std::string> youtube;
};

struct Document {
    std::string document_nm;
    std::string title;
    std::string description;
    std::string created_at;
    std::string updated_at;
};

struct DocumentCreation {
    std::string document_nm;
    std::string title;
    std::string description;
};

using DocumentUpdate = DocumentCreation;

struct InstructorBriefList {
    std::string list_nm;
    std::string title;
    std::string description;
    std::string annotation;
    int official;
    int pub;
    std::string created_at;
    std::string updated_at;
};

struct InstructorListItem {
    std::optional<std::string> problem_nm;
    std::optional<std::string> description;
};

using InstructorListItems = std::vector<InstructorListItem>;

struct InstructorList {
    std::string list_nm;
    std::string title;
    std::string description;
    std::string annotation;
    int official;
    int pub;
    std::string created_at;
    std::string updated_at;
    InstructorListItems items;
};

struct InstructorListCreation {
    std::string list_nm;
    std::string title;
    std::string description;
    std::string annotation;
    int official;
    int pub;
    InstructorListItems items;
};

using InstructorListUpdate = InstructorListCreation;

struct InstructorBriefCourse {
    std::string course_nm;
    std::string title;
    std::string description;
    std::string annotation;
    int official;
    int pub;
    std::string created_at;
    std::string updated_at;
};

struct CourseMembers {
    std::vector<std::string> invited;
    std::vector<std::string> enrolled;
    std::vector<std::string> pending;
};

struct InstructorCourse {
    std::string course_nm;
    std::string title;
    std::string description;
    std::string annotation;
    int official;
    int pub;
    std::string created_at;
    std::string updated_at;
    std::vector<std::string> lists;
    CourseMembers students;
    CourseMembers tutors;
};

struct StudentProfile {
    std::string name;
    std::string email;
};

struct InstructorCourseCreation {
    std::string course_nm;
    std::string title;
    std::string description;
    std::string annotation;
    int official;
    int pub;
    std::optional<std::vector<std::string>> lists;
    std::optional<CourseMembers> students;
    std::optional<CourseMembers> tutors;
};

struct InstructorCourseUpdate {
    std::string course_nm;
    std::optional<std::string> title;
    std::optional<std::string> description;
    std::optional<std::string> annotation;
    std::optional<int> official;
    std::optional<int> pub;
    std::optional<std::vector<std::string>> lists;
    std::optional<CourseMembers> students;
    std::optional<CourseMembers> tutors;
};

struct InstructorExamCourse {
    std::string course_nm;
    std::string title;
};

using InstructorExamDocument = RunningExamDocument;

struct InstructorExamCompiler {
    std::string compiler_id;
    std::string name;
};

struct InstructorExamProblem {
    std::string problem_nm;
    std::optional<float> weight;
    std::optional<std::string> icon;
    std::optional<std::string> caption;
};

struct InstructorExamStudent {
    std::string email;
    std::optional<std::string> name;
    std::optional<std::string> code;
    int restricted;
    std::optional<std::string> annotation;
    std::optional<std::string> result;
    int finished;
    int banned;
    std::optional<std::string> reason_ban;
    std::optional<int> inc;
    std::optional<std::string> reason_inc;
    int taken_exam;
    std::optional<std::string> emergency_password;
    int invited;
};

struct InstructorExamCreation {
    std::string exam_nm;
    std::string course_nm;
    std::string title;
    std::string exp_time_start;
};

struct InstructorExamUpdate {
    std::string exam_nm;
    std::string course_nm;
    std::string title;
    std::string place;
    std::string code;
    std::string description;
    std::optional<std::string> time_start;
    std::string exp_time_start;
    int running_time;
    int visible_submissions;
    std::optional<std::string> started_by;
    int contest;
    std::string instructions;
    std::optional<std::string> avatars;
    int anonymous;
};

struct InstructorNewExamStudent {
    std::string email;
    int invited;
    int restricted;
    std::string code;
    std::string emergency_password;
    std::string annotation;
};

struct InstructorExamSubmissionsOptions {
    std::string problems;
    bool include_source;
    bool include_pdf;
    bool include_metadata;
    bool only_last;
    float font_size;
    std::string layout;
    bool obscure_private_testcases_names;
};

struct Pack {
    std::string message;
    std::string href;
};

struct InstructorBriefExam {
    std::string exam_nm;
    std::string title;
    std::optional<std::string> place;
    std::optional<std::string> description;
    std::optional<std::string> code;
    std::optional<std::string> time_start;
    std::string exp_time_start;
    int running_time;
    int visible_submissions;
    std::optional<std::string> started_by;
    int contest;
    std::optional<std::string> instructions;
    std::optional<std::string> avatars;
    int anonymous;
    InstructorExamCourse course;
    std::string created_at;
    std::string updated_at;
};

struct InstructorExam {
    std::string exam_nm;
    std::string title;
    std::optional<std::string> place;
    std::optional<std::string> description;
    std::optional<std::string> code;
    std::optional<std::string> time_start;
    std::string exp_time_start;
    int running_time;
    int visible_submissions;
    std::optional<std::string> started_by;
    int contest;
    std::optional<std::string> instructions;
    std::optional<std::string> avatars;
    int anonymous;
    InstructorExamCourse course;
    std::string created_at;
    std::string updated_at;
    std::vector<RunningExamDocument> documents;
    std::vector<InstructorExamCompiler> compilers;
    std::vector<InstructorExamProblem> problems;
    std::vector<InstructorExamStudent> students;
};

struct ExamStatisticsEntry {
    int minute;
    int ok;
    int ko;
};

struct ExamStatistics {
    std::map<std::string, std::map<std::string, float>> submissions;
    std::map<std::string, std::map<std::string, float>> statuses;
    std::vector<ExamStatisticsEntry> timeline;
    std::map<std::string, std::map<std::string, float>> compilers;
    std::map<std::string, std::map<std::string, float>> proglangs;
};

struct RankingResult {
    std::string problem_nm;
    int submissions;
    std::optional<std::string> verdict;
    float score;
    float time;
    float penalty;
    float wrongs;
};

struct RankingRow {
    std::optional<int> position;
    std::string name;
    std::optional<std::string> avatar;
    float score;
    float time;
    bool invited;
    int submissions;
    std::vector<RankingResult> rankingResults;
};

using Ranking = std::vector<RankingRow>;

struct WebStream {
    std::string title;
    std::string id;
};

struct ProblemGenerationInfo {
    std::string title;
    std::string prompt;
    std::string model;
};

struct Deprecation {
    std::string problem_nm;
    std::optional<std::string> reason;
};

struct SharingSettings {
    std::string problem_nm;
    std::optional<std::string> passcode;
    bool shared_testcases;
    bool shared_solutions;
};

struct ProblemAnonymousSubmission {
    std::string time;
    std::string anonymous_user_id;
    std::string problem_id;
    std::string verdict;
    std::string compiler_id;
    std::string proglang;
};

struct ShareWithInp {
    std::string problem_nm;
    std::vector<std::string> emails;
    std::string text;
};

struct ProblemPopularityBucketEntry {
    float log2_bucket;
    float bucket_min;
    float bucket_max;
    float problem_count;
};

struct SubmissionQuery {
    std::string email;
    std::string problem_nm;
    std::string problem_id;
    std::string time;
    std::string ip;
    std::string verdict;
};

using SubmissionsQuery = std::vector<SubmissionQuery>;

using TagsDict = std::map<std::string, std::vector<std::string>>;

struct ChatMessage {
    std::string role;
    std::string content;
};

struct ChatPrompt {
    std::string model;
    std::string label;
    std::vector<ChatMessage> messages;
    bool addUsage;
};

struct LlmUsageEntry {
    std::string id;
    std::string created_at;
    std::string model;
    std::string label;
    float duration;
    float input_tokens;
    float output_tokens;
    std::string finish_reason;
};

struct CreateImageInput {
    std::string model;
    std::string label;
    std::string prompt;
    std::string size;
};

struct SubmitPlayerInput {
    std::string problem_id;
    std::string annotation;
    std::string source_code;
    std::string callback_url;
};

using SubmitPlayerOutput = NewSubmissionOut;

struct SubmitMatchInput {
    std::string problem_id;
    std::string annotation;
    std::vector<std::string> source_codes;
    std::string callback_url;
};

using SubmitMatchOutput = NewSubmissionOut;

struct GetGameResultOutput {
    std::string todo;
};

using GetMatchSubmissionInput = GetGameResultIn;

using GetMatchSubmissionOutput = GetGameResultOutput;

struct InstructorEntry {
    std::string username;
    std::string name;
    std::string email;
};

using InstructorEntries = std::vector<InstructorEntry>;

struct UserCreation {
    std::string email;
    std::string name;
    std::string username;
    std::string password;
    float administrator;
    float instructor;
};

struct UserEmailAndName {
    std::string email;
    std::string name;
};

using UsersEmailsAndNames = std::vector<UserEmailAndName>;

struct ProfileForAdmin {
    std::string user_id;
    std::string user_uid;
    std::string email;
    std::string name;
    std::optional<std::string> username;
    std::optional<std::string> nickname;
    std::optional<std::string> webpage;
    std::optional<std::string> description;
    std::optional<std::string> affiliation;
    std::optional<int> birth_year;
    int max_subsxhour;
    int max_subsxday;
    int administrator;
    int instructor;
    std::optional<std::string> parent_email;
    std::optional<std::string> country_id;
    std::string timezone_id;
    std::optional<std::string> compiler_id;
    std::optional<std::string> language_id;
    int locked;
    int banned;
    int nb_bans;
    std::optional<std::string> reason;
    std::string creation_date;
};

struct DatabasesInfoItem {
    std::string name;
    float size;
    std::string mtime;
};

using DatabasesInfo = std::vector<DatabasesInfoItem>;

struct FreeDiskSpaceItem {
    std::string disk;
    std::string filesystem;
    std::string size;
    std::string used;
    std::string available;
    std::string use;
    std::string mounted;
};

using NullableFreeDiskSpaceItem = std::optional<FreeDiskSpaceItem>;

using FreeDiskSpace = std::map<std::string, NullableFreeDiskSpaceItem>;

struct RecentConnectedUsers {
    int latest_hour;
    int latest_day;
    int latest_week;
    int latest_month;
    int latest_year;
};

struct RecentSubmissions {
    int latest_01_minutes;
    int latest_05_minutes;
    int latest_15_minutes;
    int latest_60_minutes;
};

struct RecentLoadAverages {
    float latest_01_minutes;
    float latest_05_minutes;
    float latest_15_minutes;
};

struct SubmissionsHistograms {
    std::vector<int> latest_hour;
    std::vector<int> latest_day;
};

struct Zombies {
    int ies;
    int pendings;
};

struct AdminDashboard {
    DatabasesInfo databases_info;
    FreeDiskSpace free_disk_space;
    RecentLoadAverages recent_load_averages;
    RecentConnectedUsers recent_connected_users;
    RecentSubmissions recent_submissions;
    SubmissionsHistograms submissions_histograms;
    Zombies zombies;
};

struct UpcomingExam {
    std::string exam_nm;
    std::string title;
    std::string username;
    std::string email;
    std::string exp_time_start;
    int running_time;
    int students;
    std::string name;
    int contest;
};

using UpcomingExams = std::vector<UpcomingExam>;

struct SubmissionQueueItem {
    std::string submission_uid;
    std::string submission_id;
    std::string problem_id;
    std::string compiler_id;
    std::string time_in;
    std::optional<std::string> exam_id;
    std::optional<std::string> veredict;
    std::string user_id;
    std::string user__name;
    std::string problem__title;
};

using SubmissionQueueItems = std::vector<SubmissionQueueItem>;

struct QueueQuery {
    std::vector<std::string> verdicts;
    int limit;
};

struct UserRankingEntry {
    std::string user_id;
    std::optional<std::string> nickname;
    std::string email;
    std::string name;
    int problems;
};

using UserRanking = std::vector<UserRankingEntry>;

struct DateRange {
    std::string start;
    std::string end;
};

struct TwoFloats {
    float a;
    float b;
};

struct TwoInts {
    int a;
    int b;
};

struct Name {
    std::string name;
};

struct SomeType {
    std::string a;
    int b;
    bool c;
    bool d;
};


// serializers


            void to_json(json& j, const CredentialsIn& x) {
                j = json{
            {"email", x.email},
{"password", x.password}
                };
            }

            void from_json(const json& j, CredentialsIn& x) {
                j.at("email").get_to(x.email);
    j.at("password").get_to(x.password);
            }

            void to_json(json& j, const ExamCredentialsIn& x) {
                j = json{
            {"email", x.email},
{"password", x.password},
{"exam", x.exam},
{"exam_password", x.exam_password}
                };
            }

            void from_json(const json& j, ExamCredentialsIn& x) {
                j.at("email").get_to(x.email);
    j.at("password").get_to(x.password);
    j.at("exam").get_to(x.exam);
    j.at("exam_password").get_to(x.exam_password);
            }

            void to_json(json& j, const CredentialsOut& x) {
                j = json{
            {"token", x.token},
{"expiration", x.expiration},
{"user_uid", x.user_uid},
{"error", x.error}
                };
            }

            void from_json(const json& j, CredentialsOut& x) {
                j.at("token").get_to(x.token);
    j.at("expiration").get_to(x.expiration);
    j.at("user_uid").get_to(x.user_uid);
    j.at("error").get_to(x.error);
            }

            void to_json(json& j, const CredentialsWithUsernameIn& x) {
                j = json{
            {"username", x.username},
{"password", x.password}
                };
            }

            void from_json(const json& j, CredentialsWithUsernameIn& x) {
                j.at("username").get_to(x.username);
    j.at("password").get_to(x.password);
            }

            void to_json(json& j, const Time& x) {
                j = json{
            {"full_time", x.full_time},
{"int_timestamp", x.int_timestamp},
{"float_timestamp", x.float_timestamp},
{"time", x.time},
{"date", x.date}
                };
            }

            void from_json(const json& j, Time& x) {
                j.at("full_time").get_to(x.full_time);
    j.at("int_timestamp").get_to(x.int_timestamp);
    j.at("float_timestamp").get_to(x.float_timestamp);
    j.at("time").get_to(x.time);
    j.at("date").get_to(x.date);
            }

            void to_json(json& j, const HomepageStats& x) {
                j = json{
            {"users", x.users},
{"problems", x.problems},
{"submissions", x.submissions},
{"exams", x.exams},
{"contests", x.contests}
                };
            }

            void from_json(const json& j, HomepageStats& x) {
                j.at("users").get_to(x.users);
    j.at("problems").get_to(x.problems);
    j.at("submissions").get_to(x.submissions);
    j.at("exams").get_to(x.exams);
    j.at("contests").get_to(x.contests);
            }


            void to_json(json& j, const ApiVersion& x) {
                j = json{
            {"version", x.version},
{"mode", x.mode},
{"gitHash", x.gitHash},
{"gitBranch", x.gitBranch},
{"gitDate", x.gitDate}
                };
            }

            void from_json(const json& j, ApiVersion& x) {
                j.at("version").get_to(x.version);
    j.at("mode").get_to(x.mode);
    j.at("gitHash").get_to(x.gitHash);
    j.at("gitBranch").get_to(x.gitBranch);
    j.at("gitDate").get_to(x.gitDate);
            }

            void to_json(json& j, const RequestInformation& x) {
                j = json{
            {"url", x.url},
{"ip", x.ip},
{"domain", x.domain}
                };
            }

            void from_json(const json& j, RequestInformation& x) {
                j.at("url").get_to(x.url);
    j.at("ip").get_to(x.ip);
    j.at("domain").get_to(x.domain);
            }

            void to_json(json& j, const Language& x) {
                j = json{
            {"language_id", x.language_id},
{"eng_name", x.eng_name},
{"own_name", x.own_name}
                };
            }

            void from_json(const json& j, Language& x) {
                j.at("language_id").get_to(x.language_id);
    j.at("eng_name").get_to(x.eng_name);
    j.at("own_name").get_to(x.own_name);
            }

            void to_json(json& j, const Country& x) {
                j = json{
            {"country_id", x.country_id},
{"eng_name", x.eng_name}
                };
            }

            void from_json(const json& j, Country& x) {
                j.at("country_id").get_to(x.country_id);
    j.at("eng_name").get_to(x.eng_name);
            }

            void to_json(json& j, const Compiler& x) {
                j = json{
            {"compiler_id", x.compiler_id},
{"name", x.name},
{"language", x.language},
{"extension", x.extension},
{"description", x.description},
{"version", x.version},
{"flags1", x.flags1},
{"flags2", x.flags2},
{"type", x.type},
{"warning", x.warning},
{"status", x.status},
{"notes", x.notes}
                };
            }

            void from_json(const json& j, Compiler& x) {
                j.at("compiler_id").get_to(x.compiler_id);
    j.at("name").get_to(x.name);
    j.at("language").get_to(x.language);
    j.at("extension").get_to(x.extension);
    j.at("description").get_to(x.description);
    j.at("version").get_to(x.version);
    j.at("flags1").get_to(x.flags1);
    j.at("flags2").get_to(x.flags2);
    j.at("type").get_to(x.type);
    j.at("warning").get_to(x.warning);
    j.at("status").get_to(x.status);
    j.at("notes").get_to(x.notes);
            }

            void to_json(json& j, const Driver& x) {
                j = json{
            {"driver_id", x.driver_id}
                };
            }

            void from_json(const json& j, Driver& x) {
                j.at("driver_id").get_to(x.driver_id);
            }

            void to_json(json& j, const Verdict& x) {
                j = json{
            {"verdict_id", x.verdict_id},
{"name", x.name},
{"description", x.description},
{"emoji", x.emoji}
                };
            }

            void from_json(const json& j, Verdict& x) {
                j.at("verdict_id").get_to(x.verdict_id);
    j.at("name").get_to(x.name);
    j.at("description").get_to(x.description);
    j.at("emoji").get_to(x.emoji);
            }

            void to_json(json& j, const Proglang& x) {
                j = json{
            {"proglang_id", x.proglang_id}
                };
            }

            void from_json(const json& j, Proglang& x) {
                j.at("proglang_id").get_to(x.proglang_id);
            }

            void to_json(json& j, const AllTables& x) {
                j = json{
            {"languages", x.languages},
{"countries", x.countries},
{"compilers", x.compilers},
{"drivers", x.drivers},
{"verdicts", x.verdicts},
{"proglangs", x.proglangs}
                };
            }

            void from_json(const json& j, AllTables& x) {
                j.at("languages").get_to(x.languages);
    j.at("countries").get_to(x.countries);
    j.at("compilers").get_to(x.compilers);
    j.at("drivers").get_to(x.drivers);
    j.at("verdicts").get_to(x.verdicts);
    j.at("proglangs").get_to(x.proglangs);
            }

            void to_json(json& j, const ProblemSummary& x) {
                j = json{
            {"summary_1s", x.summary_1s},
{"summary_1p", x.summary_1p},
{"keywords", x.keywords},
{"model", x.model},
{"duration", x.duration}
                };
            }

            void from_json(const json& j, ProblemSummary& x) {
                j.at("summary_1s").get_to(x.summary_1s);
    j.at("summary_1p").get_to(x.summary_1p);
    j.at("keywords").get_to(x.keywords);
    j.at("model").get_to(x.model);
    j.at("duration").get_to(x.duration);
            }

            void to_json(json& j, const SolutionTags& x) {
                j = json{
            {"tags", x.tags},
{"model", x.model},
{"duration", x.duration}
                };
            }

            void from_json(const json& j, SolutionTags& x) {
                j.at("tags").get_to(x.tags);
    j.at("model").get_to(x.model);
    j.at("duration").get_to(x.duration);
            }

            void to_json(json& j, const BriefAbstractProblem& x) {
                j = json{
            {"problem_nm", x.problem_nm},
{"author", x.author},
{"author_email", x.author_email},
{"public", x.pub},
{"official", x.official},
{"compilers", x.compilers},
{"driver_id", x.driver_id},
{"type", x.type},
{"deprecation", x.deprecation},
{"created_at", x.created_at},
{"updated_at", x.updated_at},
{"solution_tags", x.solution_tags}
                };
            }

            void from_json(const json& j, BriefAbstractProblem& x) {
                j.at("problem_nm").get_to(x.problem_nm);
    j.at("author").get_to(x.author);
    j.at("author_email").get_to(x.author_email);
    j.at("public").get_to(x.pub);
    j.at("official").get_to(x.official);
    j.at("compilers").get_to(x.compilers);
    j.at("driver_id").get_to(x.driver_id);
    j.at("type").get_to(x.type);
    j.at("deprecation").get_to(x.deprecation);
    j.at("created_at").get_to(x.created_at);
    j.at("updated_at").get_to(x.updated_at);
    j.at("solution_tags").get_to(x.solution_tags);
            }

            void to_json(json& j, const BriefProblem& x) {
                j = json{
            {"problem_id", x.problem_id},
{"problem_nm", x.problem_nm},
{"language_id", x.language_id},
{"title", x.title},
{"original_language_id", x.original_language_id},
{"translator", x.translator},
{"translator_email", x.translator_email},
{"checked", x.checked},
{"summary", x.summary}
                };
            }

            void from_json(const json& j, BriefProblem& x) {
                j.at("problem_id").get_to(x.problem_id);
    j.at("problem_nm").get_to(x.problem_nm);
    j.at("language_id").get_to(x.language_id);
    j.at("title").get_to(x.title);
    j.at("original_language_id").get_to(x.original_language_id);
    j.at("translator").get_to(x.translator);
    j.at("translator_email").get_to(x.translator_email);
    j.at("checked").get_to(x.checked);
    j.at("summary").get_to(x.summary);
            }


            void to_json(json& j, const AbstractProblem& x) {
                j = json{
            {"problem_nm", x.problem_nm},
{"author", x.author},
{"author_email", x.author_email},
{"public", x.pub},
{"official", x.official},
{"compilers", x.compilers},
{"driver_id", x.driver_id},
{"type", x.type},
{"deprecation", x.deprecation},
{"created_at", x.created_at},
{"updated_at", x.updated_at},
{"solution_tags", x.solution_tags},
{"problems", x.problems}
                };
            }

            void from_json(const json& j, AbstractProblem& x) {
                j.at("problem_nm").get_to(x.problem_nm);
    j.at("author").get_to(x.author);
    j.at("author_email").get_to(x.author_email);
    j.at("public").get_to(x.pub);
    j.at("official").get_to(x.official);
    j.at("compilers").get_to(x.compilers);
    j.at("driver_id").get_to(x.driver_id);
    j.at("type").get_to(x.type);
    j.at("deprecation").get_to(x.deprecation);
    j.at("created_at").get_to(x.created_at);
    j.at("updated_at").get_to(x.updated_at);
    j.at("solution_tags").get_to(x.solution_tags);
    j.at("problems").get_to(x.problems);
            }

            void to_json(json& j, const AbstractProblemSuppl& x) {
                j = json{
            {"compilers_with_ac", x.compilers_with_ac},
{"proglangs_with_ac", x.proglangs_with_ac}
                };
            }

            void from_json(const json& j, AbstractProblemSuppl& x) {
                j.at("compilers_with_ac").get_to(x.compilers_with_ac);
    j.at("proglangs_with_ac").get_to(x.proglangs_with_ac);
            }

            void to_json(json& j, const ProblemSuppl& x) {
                j = json{
            {"compilers_with_ac", x.compilers_with_ac},
{"proglangs_with_ac", x.proglangs_with_ac},
{"official_solution_checks", x.official_solution_checks},
{"handler", x.handler}
                };
            }

            void from_json(const json& j, ProblemSuppl& x) {
                j.at("compilers_with_ac").get_to(x.compilers_with_ac);
    j.at("proglangs_with_ac").get_to(x.proglangs_with_ac);
    j.at("official_solution_checks").get_to(x.official_solution_checks);
    j.at("handler").get_to(x.handler);
            }

            void to_json(json& j, const Problem& x) {
                j = json{
            {"problem_id", x.problem_id},
{"problem_nm", x.problem_nm},
{"language_id", x.language_id},
{"title", x.title},
{"original_language_id", x.original_language_id},
{"translator", x.translator},
{"translator_email", x.translator_email},
{"checked", x.checked},
{"summary", x.summary},
{"abstract_problem", x.abstract_problem}
                };
            }

            void from_json(const json& j, Problem& x) {
                j.at("problem_id").get_to(x.problem_id);
    j.at("problem_nm").get_to(x.problem_nm);
    j.at("language_id").get_to(x.language_id);
    j.at("title").get_to(x.title);
    j.at("original_language_id").get_to(x.original_language_id);
    j.at("translator").get_to(x.translator);
    j.at("translator_email").get_to(x.translator_email);
    j.at("checked").get_to(x.checked);
    j.at("summary").get_to(x.summary);
    j.at("abstract_problem").get_to(x.abstract_problem);
            }

            void to_json(json& j, const Testcase& x) {
                j = json{
            {"name", x.name},
{"input_b64", x.input_b64},
{"correct_b64", x.correct_b64}
                };
            }

            void from_json(const json& j, Testcase& x) {
                j.at("name").get_to(x.name);
    j.at("input_b64").get_to(x.input_b64);
    j.at("correct_b64").get_to(x.correct_b64);
            }

            void to_json(json& j, const ProblemRich& x) {
                j = json{
            {"problem_id", x.problem_id},
{"problem_nm", x.problem_nm},
{"language_id", x.language_id},
{"title", x.title},
{"original_language_id", x.original_language_id},
{"translator", x.translator},
{"translator_email", x.translator_email},
{"checked", x.checked},
{"summary", x.summary},
{"abstract_problem", x.abstract_problem},
{"sample_testcases", x.sample_testcases},
{"html_statement", x.html_statement}
                };
            }

            void from_json(const json& j, ProblemRich& x) {
                j.at("problem_id").get_to(x.problem_id);
    j.at("problem_nm").get_to(x.problem_nm);
    j.at("language_id").get_to(x.language_id);
    j.at("title").get_to(x.title);
    j.at("original_language_id").get_to(x.original_language_id);
    j.at("translator").get_to(x.translator);
    j.at("translator_email").get_to(x.translator_email);
    j.at("checked").get_to(x.checked);
    j.at("summary").get_to(x.summary);
    j.at("abstract_problem").get_to(x.abstract_problem);
    j.at("sample_testcases").get_to(x.sample_testcases);
    j.at("html_statement").get_to(x.html_statement);
            }

            void to_json(json& j, const SearchResult& x) {
                j = json{
            {"problem_nm", x.problem_nm},
{"score", x.score}
                };
            }

            void from_json(const json& j, SearchResult& x) {
                j.at("problem_nm").get_to(x.problem_nm);
    j.at("score").get_to(x.score);
            }


            void to_json(json& j, const AllKeys& x) {
                j = json{
            {"problems", x.problems},
{"enrolled_courses", x.enrolled_courses},
{"available_courses", x.available_courses},
{"lists", x.lists}
                };
            }

            void from_json(const json& j, AllKeys& x) {
                j.at("problems").get_to(x.problems);
    j.at("enrolled_courses").get_to(x.enrolled_courses);
    j.at("available_courses").get_to(x.available_courses);
    j.at("lists").get_to(x.lists);
            }

            void to_json(json& j, const Profile& x) {
                j = json{
            {"user_uid", x.user_uid},
{"email", x.email},
{"name", x.name},
{"username", x.username},
{"nickname", x.nickname},
{"webpage", x.webpage},
{"description", x.description},
{"affiliation", x.affiliation},
{"birth_year", x.birth_year},
{"max_subsxhour", x.max_subsxhour},
{"max_subsxday", x.max_subsxday},
{"administrator", x.administrator},
{"instructor", x.instructor},
{"parent_email", x.parent_email},
{"country_id", x.country_id},
{"timezone_id", x.timezone_id},
{"compiler_id", x.compiler_id},
{"language_id", x.language_id}
                };
            }

            void from_json(const json& j, Profile& x) {
                j.at("user_uid").get_to(x.user_uid);
    j.at("email").get_to(x.email);
    j.at("name").get_to(x.name);
    j.at("username").get_to(x.username);
    j.at("nickname").get_to(x.nickname);
    j.at("webpage").get_to(x.webpage);
    j.at("description").get_to(x.description);
    j.at("affiliation").get_to(x.affiliation);
    j.at("birth_year").get_to(x.birth_year);
    j.at("max_subsxhour").get_to(x.max_subsxhour);
    j.at("max_subsxday").get_to(x.max_subsxday);
    j.at("administrator").get_to(x.administrator);
    j.at("instructor").get_to(x.instructor);
    j.at("parent_email").get_to(x.parent_email);
    j.at("country_id").get_to(x.country_id);
    j.at("timezone_id").get_to(x.timezone_id);
    j.at("compiler_id").get_to(x.compiler_id);
    j.at("language_id").get_to(x.language_id);
            }

            void to_json(json& j, const NewProfile& x) {
                j = json{
            {"name", x.name},
{"birth_year", x.birth_year},
{"nickname", x.nickname},
{"webpage", x.webpage},
{"affiliation", x.affiliation},
{"description", x.description},
{"country_id", x.country_id},
{"timezone_id", x.timezone_id}
                };
            }

            void from_json(const json& j, NewProfile& x) {
                j.at("name").get_to(x.name);
    j.at("birth_year").get_to(x.birth_year);
    j.at("nickname").get_to(x.nickname);
    j.at("webpage").get_to(x.webpage);
    j.at("affiliation").get_to(x.affiliation);
    j.at("description").get_to(x.description);
    j.at("country_id").get_to(x.country_id);
    j.at("timezone_id").get_to(x.timezone_id);
            }

            void to_json(json& j, const NewPassword& x) {
                j = json{
            {"oldPassword", x.oldPassword},
{"newPassword", x.newPassword}
                };
            }

            void from_json(const json& j, NewPassword& x) {
                j.at("oldPassword").get_to(x.oldPassword);
    j.at("newPassword").get_to(x.newPassword);
            }

            void to_json(json& j, const DateValue& x) {
                j = json{
            {"date", x.date},
{"value", x.value}
                };
            }

            void from_json(const json& j, DateValue& x) {
                j.at("date").get_to(x.date);
    j.at("value").get_to(x.value);
            }



            void to_json(json& j, const AllDistributions& x) {
                j = json{
            {"verdicts", x.verdicts},
{"compilers", x.compilers},
{"proglangs", x.proglangs},
{"submissions_by_hour", x.submissions_by_hour},
{"submissions_by_weekday", x.submissions_by_weekday}
                };
            }

            void from_json(const json& j, AllDistributions& x) {
                j.at("verdicts").get_to(x.verdicts);
    j.at("compilers").get_to(x.compilers);
    j.at("proglangs").get_to(x.proglangs);
    j.at("submissions_by_hour").get_to(x.submissions_by_hour);
    j.at("submissions_by_weekday").get_to(x.submissions_by_weekday);
            }

            void to_json(json& j, const Dashboard& x) {
                j = json{
            {"stats", x.stats},
{"heatmap", x.heatmap},
{"distributions", x.distributions}
                };
            }

            void from_json(const json& j, Dashboard& x) {
                j.at("stats").get_to(x.stats);
    j.at("heatmap").get_to(x.heatmap);
    j.at("distributions").get_to(x.distributions);
            }

            void to_json(json& j, const Submission& x) {
                j = json{
            {"problem_id", x.problem_id},
{"submission_id", x.submission_id},
{"compiler_id", x.compiler_id},
{"annotation", x.annotation},
{"state", x.state},
{"time_in", x.time_in},
{"veredict", x.veredict},
{"veredict_info", x.veredict_info},
{"veredict_publics", x.veredict_publics},
{"ok_publics_but_wrong", x.ok_publics_but_wrong}
                };
            }

            void from_json(const json& j, Submission& x) {
                j.at("problem_id").get_to(x.problem_id);
    j.at("submission_id").get_to(x.submission_id);
    j.at("compiler_id").get_to(x.compiler_id);
    j.at("annotation").get_to(x.annotation);
    j.at("state").get_to(x.state);
    j.at("time_in").get_to(x.time_in);
    j.at("veredict").get_to(x.veredict);
    j.at("veredict_info").get_to(x.veredict_info);
    j.at("veredict_publics").get_to(x.veredict_publics);
    j.at("ok_publics_but_wrong").get_to(x.ok_publics_but_wrong);
            }

            void to_json(json& j, const NewSubmissionIn& x) {
                j = json{
            {"problem_id", x.problem_id},
{"compiler_id", x.compiler_id},
{"annotation", x.annotation}
                };
            }

            void from_json(const json& j, NewSubmissionIn& x) {
                j.at("problem_id").get_to(x.problem_id);
    j.at("compiler_id").get_to(x.compiler_id);
    j.at("annotation").get_to(x.annotation);
            }

            void to_json(json& j, const NewSubmissionOut& x) {
                j = json{
            {"submission_id", x.submission_id}
                };
            }

            void from_json(const json& j, NewSubmissionOut& x) {
                j.at("submission_id").get_to(x.submission_id);
            }

            void to_json(json& j, const SubmissionAnalysis& x) {
                j = json{
            {"testcase", x.testcase},
{"execution", x.execution},
{"verdict", x.verdict}
                };
            }

            void from_json(const json& j, SubmissionAnalysis& x) {
                j.at("testcase").get_to(x.testcase);
    j.at("execution").get_to(x.execution);
    j.at("verdict").get_to(x.verdict);
            }

            void to_json(json& j, const TestcaseAnalysis& x) {
                j = json{
            {"testcase", x.testcase},
{"execution", x.execution},
{"verdict", x.verdict},
{"input_b64", x.input_b64},
{"output_b64", x.output_b64},
{"expected_b64", x.expected_b64}
                };
            }

            void from_json(const json& j, TestcaseAnalysis& x) {
                j.at("testcase").get_to(x.testcase);
    j.at("execution").get_to(x.execution);
    j.at("verdict").get_to(x.verdict);
    j.at("input_b64").get_to(x.input_b64);
    j.at("output_b64").get_to(x.output_b64);
    j.at("expected_b64").get_to(x.expected_b64);
            }

            void to_json(json& j, const GetGameResultIn& x) {
                j = json{
            {"problem_id", x.problem_id},
{"submission_id", x.submission_id}
                };
            }

            void from_json(const json& j, GetGameResultIn& x) {
                j.at("problem_id").get_to(x.problem_id);
    j.at("submission_id").get_to(x.submission_id);
            }

            void to_json(json& j, const MatchSchema& x) {
                j = json{
            {"seed", x.seed},
{"status", x.status},
{"players", x.players},
{"scores", x.scores}
                };
            }

            void from_json(const json& j, MatchSchema& x) {
                j.at("seed").get_to(x.seed);
    j.at("status").get_to(x.status);
    j.at("players").get_to(x.players);
    j.at("scores").get_to(x.scores);
            }

            void to_json(json& j, const ProblemSchema& x) {
                j = json{
            {"author", x.author},
{"description", x.description},
{"email", x.email},
{"gamename", x.gamename},
{"title", x.title},
{"version", x.version}
                };
            }

            void from_json(const json& j, ProblemSchema& x) {
                j.at("author").get_to(x.author);
    j.at("description").get_to(x.description);
    j.at("email").get_to(x.email);
    j.at("gamename").get_to(x.gamename);
    j.at("title").get_to(x.title);
    j.at("version").get_to(x.version);
            }

            void to_json(json& j, const SubmissionSchema& x) {
                j = json{
            {"compiler_id", x.compiler_id},
{"description", x.description},
{"email", x.email},
{"problem_id", x.problem_id}
                };
            }

            void from_json(const json& j, SubmissionSchema& x) {
                j.at("compiler_id").get_to(x.compiler_id);
    j.at("description").get_to(x.description);
    j.at("email").get_to(x.email);
    j.at("problem_id").get_to(x.problem_id);
            }

            void to_json(json& j, const GetGameResultOut& x) {
                j = json{
            {"games", x.games},
{"problem", x.problem},
{"submission", x.submission}
                };
            }

            void from_json(const json& j, GetGameResultOut& x) {
                j.at("games").get_to(x.games);
    j.at("problem").get_to(x.problem);
    j.at("submission").get_to(x.submission);
            }

            void to_json(json& j, const GetGameOutputIn& x) {
                j = json{
            {"problem_id", x.problem_id},
{"submission_id", x.submission_id},
{"game_id", x.game_id}
                };
            }

            void from_json(const json& j, GetGameOutputIn& x) {
                j.at("problem_id").get_to(x.problem_id);
    j.at("submission_id").get_to(x.submission_id);
    j.at("game_id").get_to(x.game_id);
            }

            void to_json(json& j, const CodeMetrics& x) {
                j = json{
            {"comment_ratio", x.comment_ratio},
{"cyclomatic_complexity", x.cyclomatic_complexity},
{"fanout_external", x.fanout_external},
{"fanout_internal", x.fanout_internal},
{"halstead_bugprop", x.halstead_bugprop},
{"halstead_difficulty", x.halstead_difficulty},
{"halstead_effort", x.halstead_effort},
{"halstead_timerequired", x.halstead_timerequired},
{"halstead_volume", x.halstead_volume},
{"loc", x.loc},
{"maintainability_index", x.maintainability_index},
{"operands_sum", x.operands_sum},
{"operands_uniq", x.operands_uniq},
{"operators_sum", x.operators_sum},
{"operators_uniq", x.operators_uniq},
{"pylint", x.pylint},
{"tiobe", x.tiobe},
{"tiobe_compiler", x.tiobe_compiler},
{"tiobe_complexity", x.tiobe_complexity},
{"tiobe_coverage", x.tiobe_coverage},
{"tiobe_duplication", x.tiobe_duplication},
{"tiobe_fanout", x.tiobe_fanout},
{"tiobe_functional", x.tiobe_functional},
{"tiobe_security", x.tiobe_security},
{"tiobe_standard", x.tiobe_standard}
                };
            }

            void from_json(const json& j, CodeMetrics& x) {
                j.at("comment_ratio").get_to(x.comment_ratio);
    j.at("cyclomatic_complexity").get_to(x.cyclomatic_complexity);
    j.at("fanout_external").get_to(x.fanout_external);
    j.at("fanout_internal").get_to(x.fanout_internal);
    j.at("halstead_bugprop").get_to(x.halstead_bugprop);
    j.at("halstead_difficulty").get_to(x.halstead_difficulty);
    j.at("halstead_effort").get_to(x.halstead_effort);
    j.at("halstead_timerequired").get_to(x.halstead_timerequired);
    j.at("halstead_volume").get_to(x.halstead_volume);
    j.at("loc").get_to(x.loc);
    j.at("maintainability_index").get_to(x.maintainability_index);
    j.at("operands_sum").get_to(x.operands_sum);
    j.at("operands_uniq").get_to(x.operands_uniq);
    j.at("operators_sum").get_to(x.operators_sum);
    j.at("operators_uniq").get_to(x.operators_uniq);
    j.at("pylint").get_to(x.pylint);
    j.at("tiobe").get_to(x.tiobe);
    j.at("tiobe_compiler").get_to(x.tiobe_compiler);
    j.at("tiobe_complexity").get_to(x.tiobe_complexity);
    j.at("tiobe_coverage").get_to(x.tiobe_coverage);
    j.at("tiobe_duplication").get_to(x.tiobe_duplication);
    j.at("tiobe_fanout").get_to(x.tiobe_fanout);
    j.at("tiobe_functional").get_to(x.tiobe_functional);
    j.at("tiobe_security").get_to(x.tiobe_security);
    j.at("tiobe_standard").get_to(x.tiobe_standard);
            }

            void to_json(json& j, const PublicProfile& x) {
                j = json{
            {"email", x.email},
{"name", x.name},
{"username", x.username}
                };
            }

            void from_json(const json& j, PublicProfile& x) {
                j.at("email").get_to(x.email);
    j.at("name").get_to(x.name);
    j.at("username").get_to(x.username);
            }

            void to_json(json& j, const BriefCourse& x) {
                j = json{
            {"course_nm", x.course_nm},
{"title", x.title},
{"description", x.description},
{"annotation", x.annotation},
{"public", x.pub},
{"official", x.official}
                };
            }

            void from_json(const json& j, BriefCourse& x) {
                j.at("course_nm").get_to(x.course_nm);
    j.at("title").get_to(x.title);
    j.at("description").get_to(x.description);
    j.at("annotation").get_to(x.annotation);
    j.at("public").get_to(x.pub);
    j.at("official").get_to(x.official);
            }

            void to_json(json& j, const Course& x) {
                j = json{
            {"course_nm", x.course_nm},
{"title", x.title},
{"description", x.description},
{"annotation", x.annotation},
{"public", x.pub},
{"official", x.official},
{"owner", x.owner},
{"lists", x.lists}
                };
            }

            void from_json(const json& j, Course& x) {
                j.at("course_nm").get_to(x.course_nm);
    j.at("title").get_to(x.title);
    j.at("description").get_to(x.description);
    j.at("annotation").get_to(x.annotation);
    j.at("public").get_to(x.pub);
    j.at("official").get_to(x.official);
    j.at("owner").get_to(x.owner);
    j.at("lists").get_to(x.lists);
            }

            void to_json(json& j, const ListItem& x) {
                j = json{
            {"problem_nm", x.problem_nm},
{"description", x.description}
                };
            }

            void from_json(const json& j, ListItem& x) {
                j.at("problem_nm").get_to(x.problem_nm);
    j.at("description").get_to(x.description);
            }

            void to_json(json& j, const BriefList& x) {
                j = json{
            {"list_nm", x.list_nm},
{"title", x.title},
{"description", x.description},
{"annotation", x.annotation},
{"public", x.pub},
{"official", x.official}
                };
            }

            void from_json(const json& j, BriefList& x) {
                j.at("list_nm").get_to(x.list_nm);
    j.at("title").get_to(x.title);
    j.at("description").get_to(x.description);
    j.at("annotation").get_to(x.annotation);
    j.at("public").get_to(x.pub);
    j.at("official").get_to(x.official);
            }

            void to_json(json& j, const List& x) {
                j = json{
            {"list_nm", x.list_nm},
{"title", x.title},
{"description", x.description},
{"annotation", x.annotation},
{"public", x.pub},
{"official", x.official},
{"items", x.items},
{"owner", x.owner}
                };
            }

            void from_json(const json& j, List& x) {
                j.at("list_nm").get_to(x.list_nm);
    j.at("title").get_to(x.title);
    j.at("description").get_to(x.description);
    j.at("annotation").get_to(x.annotation);
    j.at("public").get_to(x.pub);
    j.at("official").get_to(x.official);
    j.at("items").get_to(x.items);
    j.at("owner").get_to(x.owner);
            }

            void to_json(json& j, const ReadyExam& x) {
                j = json{
            {"exam_key", x.exam_key},
{"title", x.title},
{"place", x.place},
{"description", x.description},
{"exp_time_start", x.exp_time_start},
{"running_time", x.running_time},
{"contest", x.contest}
                };
            }

            void from_json(const json& j, ReadyExam& x) {
                j.at("exam_key").get_to(x.exam_key);
    j.at("title").get_to(x.title);
    j.at("place").get_to(x.place);
    j.at("description").get_to(x.description);
    j.at("exp_time_start").get_to(x.exp_time_start);
    j.at("running_time").get_to(x.running_time);
    j.at("contest").get_to(x.contest);
            }

            void to_json(json& j, const RunningExamProblem& x) {
                j = json{
            {"problem_nm", x.problem_nm},
{"icon", x.icon},
{"caption", x.caption},
{"weight", x.weight}
                };
            }

            void from_json(const json& j, RunningExamProblem& x) {
                j.at("problem_nm").get_to(x.problem_nm);
    j.at("icon").get_to(x.icon);
    j.at("caption").get_to(x.caption);
    j.at("weight").get_to(x.weight);
            }

            void to_json(json& j, const RunningExamDocument& x) {
                j = json{
            {"document_nm", x.document_nm},
{"title", x.title},
{"description", x.description}
                };
            }

            void from_json(const json& j, RunningExamDocument& x) {
                j.at("document_nm").get_to(x.document_nm);
    j.at("title").get_to(x.title);
    j.at("description").get_to(x.description);
            }

            void to_json(json& j, const RunningExam& x) {
                j = json{
            {"title", x.title},
{"description", x.description},
{"instructions", x.instructions},
{"time_start", x.time_start},
{"exp_time_start", x.exp_time_start},
{"running_time", x.running_time},
{"contest", x.contest},
{"problems", x.problems},
{"compilers", x.compilers},
{"documents", x.documents}
                };
            }

            void from_json(const json& j, RunningExam& x) {
                j.at("title").get_to(x.title);
    j.at("description").get_to(x.description);
    j.at("instructions").get_to(x.instructions);
    j.at("time_start").get_to(x.time_start);
    j.at("exp_time_start").get_to(x.exp_time_start);
    j.at("running_time").get_to(x.running_time);
    j.at("contest").get_to(x.contest);
    j.at("problems").get_to(x.problems);
    j.at("compilers").get_to(x.compilers);
    j.at("documents").get_to(x.documents);
            }

            void to_json(json& j, const AbstractStatus& x) {
                j = json{
            {"problem_nm", x.problem_nm},
{"nb_submissions", x.nb_submissions},
{"nb_pending_submissions", x.nb_pending_submissions},
{"nb_accepted_submissions", x.nb_accepted_submissions},
{"nb_rejected_submissions", x.nb_rejected_submissions},
{"nb_scored_submissions", x.nb_scored_submissions},
{"status", x.status}
                };
            }

            void from_json(const json& j, AbstractStatus& x) {
                j.at("problem_nm").get_to(x.problem_nm);
    j.at("nb_submissions").get_to(x.nb_submissions);
    j.at("nb_pending_submissions").get_to(x.nb_pending_submissions);
    j.at("nb_accepted_submissions").get_to(x.nb_accepted_submissions);
    j.at("nb_rejected_submissions").get_to(x.nb_rejected_submissions);
    j.at("nb_scored_submissions").get_to(x.nb_scored_submissions);
    j.at("status").get_to(x.status);
            }

            void to_json(json& j, const Status& x) {
                j = json{
            {"problem_id", x.problem_id},
{"problem_nm", x.problem_nm},
{"nb_submissions", x.nb_submissions},
{"nb_pending_submissions", x.nb_pending_submissions},
{"nb_accepted_submissions", x.nb_accepted_submissions},
{"nb_rejected_submissions", x.nb_rejected_submissions},
{"nb_scored_submissions", x.nb_scored_submissions},
{"status", x.status}
                };
            }

            void from_json(const json& j, Status& x) {
                j.at("problem_id").get_to(x.problem_id);
    j.at("problem_nm").get_to(x.problem_nm);
    j.at("nb_submissions").get_to(x.nb_submissions);
    j.at("nb_pending_submissions").get_to(x.nb_pending_submissions);
    j.at("nb_accepted_submissions").get_to(x.nb_accepted_submissions);
    j.at("nb_rejected_submissions").get_to(x.nb_rejected_submissions);
    j.at("nb_scored_submissions").get_to(x.nb_scored_submissions);
    j.at("status").get_to(x.status);
            }

            void to_json(json& j, const Award& x) {
                j = json{
            {"award_id", x.award_id},
{"time", x.time},
{"type", x.type},
{"icon", x.icon},
{"title", x.title},
{"info", x.info},
{"youtube", x.youtube},
{"submission", x.submission}
                };
            }

            void from_json(const json& j, Award& x) {
                j.at("award_id").get_to(x.award_id);
    j.at("time").get_to(x.time);
    j.at("type").get_to(x.type);
    j.at("icon").get_to(x.icon);
    j.at("title").get_to(x.title);
    j.at("info").get_to(x.info);
    j.at("youtube").get_to(x.youtube);
    j.at("submission").get_to(x.submission);
            }

            void to_json(json& j, const BriefAward& x) {
                j = json{
            {"award_id", x.award_id},
{"time", x.time},
{"type", x.type},
{"icon", x.icon},
{"title", x.title},
{"info", x.info},
{"youtube", x.youtube}
                };
            }

            void from_json(const json& j, BriefAward& x) {
                j.at("award_id").get_to(x.award_id);
    j.at("time").get_to(x.time);
    j.at("type").get_to(x.type);
    j.at("icon").get_to(x.icon);
    j.at("title").get_to(x.title);
    j.at("info").get_to(x.info);
    j.at("youtube").get_to(x.youtube);
            }

            void to_json(json& j, const Document& x) {
                j = json{
            {"document_nm", x.document_nm},
{"title", x.title},
{"description", x.description},
{"created_at", x.created_at},
{"updated_at", x.updated_at}
                };
            }

            void from_json(const json& j, Document& x) {
                j.at("document_nm").get_to(x.document_nm);
    j.at("title").get_to(x.title);
    j.at("description").get_to(x.description);
    j.at("created_at").get_to(x.created_at);
    j.at("updated_at").get_to(x.updated_at);
            }

            void to_json(json& j, const DocumentCreation& x) {
                j = json{
            {"document_nm", x.document_nm},
{"title", x.title},
{"description", x.description}
                };
            }

            void from_json(const json& j, DocumentCreation& x) {
                j.at("document_nm").get_to(x.document_nm);
    j.at("title").get_to(x.title);
    j.at("description").get_to(x.description);
            }


            void to_json(json& j, const InstructorBriefList& x) {
                j = json{
            {"list_nm", x.list_nm},
{"title", x.title},
{"description", x.description},
{"annotation", x.annotation},
{"official", x.official},
{"public", x.pub},
{"created_at", x.created_at},
{"updated_at", x.updated_at}
                };
            }

            void from_json(const json& j, InstructorBriefList& x) {
                j.at("list_nm").get_to(x.list_nm);
    j.at("title").get_to(x.title);
    j.at("description").get_to(x.description);
    j.at("annotation").get_to(x.annotation);
    j.at("official").get_to(x.official);
    j.at("public").get_to(x.pub);
    j.at("created_at").get_to(x.created_at);
    j.at("updated_at").get_to(x.updated_at);
            }

            void to_json(json& j, const InstructorListItem& x) {
                j = json{
            {"problem_nm", x.problem_nm},
{"description", x.description}
                };
            }

            void from_json(const json& j, InstructorListItem& x) {
                j.at("problem_nm").get_to(x.problem_nm);
    j.at("description").get_to(x.description);
            }


            void to_json(json& j, const InstructorList& x) {
                j = json{
            {"list_nm", x.list_nm},
{"title", x.title},
{"description", x.description},
{"annotation", x.annotation},
{"official", x.official},
{"public", x.pub},
{"created_at", x.created_at},
{"updated_at", x.updated_at},
{"items", x.items}
                };
            }

            void from_json(const json& j, InstructorList& x) {
                j.at("list_nm").get_to(x.list_nm);
    j.at("title").get_to(x.title);
    j.at("description").get_to(x.description);
    j.at("annotation").get_to(x.annotation);
    j.at("official").get_to(x.official);
    j.at("public").get_to(x.pub);
    j.at("created_at").get_to(x.created_at);
    j.at("updated_at").get_to(x.updated_at);
    j.at("items").get_to(x.items);
            }

            void to_json(json& j, const InstructorListCreation& x) {
                j = json{
            {"list_nm", x.list_nm},
{"title", x.title},
{"description", x.description},
{"annotation", x.annotation},
{"official", x.official},
{"public", x.pub},
{"items", x.items}
                };
            }

            void from_json(const json& j, InstructorListCreation& x) {
                j.at("list_nm").get_to(x.list_nm);
    j.at("title").get_to(x.title);
    j.at("description").get_to(x.description);
    j.at("annotation").get_to(x.annotation);
    j.at("official").get_to(x.official);
    j.at("public").get_to(x.pub);
    j.at("items").get_to(x.items);
            }


            void to_json(json& j, const InstructorBriefCourse& x) {
                j = json{
            {"course_nm", x.course_nm},
{"title", x.title},
{"description", x.description},
{"annotation", x.annotation},
{"official", x.official},
{"public", x.pub},
{"created_at", x.created_at},
{"updated_at", x.updated_at}
                };
            }

            void from_json(const json& j, InstructorBriefCourse& x) {
                j.at("course_nm").get_to(x.course_nm);
    j.at("title").get_to(x.title);
    j.at("description").get_to(x.description);
    j.at("annotation").get_to(x.annotation);
    j.at("official").get_to(x.official);
    j.at("public").get_to(x.pub);
    j.at("created_at").get_to(x.created_at);
    j.at("updated_at").get_to(x.updated_at);
            }

            void to_json(json& j, const CourseMembers& x) {
                j = json{
            {"invited", x.invited},
{"enrolled", x.enrolled},
{"pending", x.pending}
                };
            }

            void from_json(const json& j, CourseMembers& x) {
                j.at("invited").get_to(x.invited);
    j.at("enrolled").get_to(x.enrolled);
    j.at("pending").get_to(x.pending);
            }

            void to_json(json& j, const InstructorCourse& x) {
                j = json{
            {"course_nm", x.course_nm},
{"title", x.title},
{"description", x.description},
{"annotation", x.annotation},
{"official", x.official},
{"public", x.pub},
{"created_at", x.created_at},
{"updated_at", x.updated_at},
{"lists", x.lists},
{"students", x.students},
{"tutors", x.tutors}
                };
            }

            void from_json(const json& j, InstructorCourse& x) {
                j.at("course_nm").get_to(x.course_nm);
    j.at("title").get_to(x.title);
    j.at("description").get_to(x.description);
    j.at("annotation").get_to(x.annotation);
    j.at("official").get_to(x.official);
    j.at("public").get_to(x.pub);
    j.at("created_at").get_to(x.created_at);
    j.at("updated_at").get_to(x.updated_at);
    j.at("lists").get_to(x.lists);
    j.at("students").get_to(x.students);
    j.at("tutors").get_to(x.tutors);
            }

            void to_json(json& j, const StudentProfile& x) {
                j = json{
            {"name", x.name},
{"email", x.email}
                };
            }

            void from_json(const json& j, StudentProfile& x) {
                j.at("name").get_to(x.name);
    j.at("email").get_to(x.email);
            }

            void to_json(json& j, const InstructorCourseCreation& x) {
                j = json{
            {"course_nm", x.course_nm},
{"title", x.title},
{"description", x.description},
{"annotation", x.annotation},
{"official", x.official},
{"public", x.pub},
{"lists", x.lists},
{"students", x.students},
{"tutors", x.tutors}
                };
            }

            void from_json(const json& j, InstructorCourseCreation& x) {
                j.at("course_nm").get_to(x.course_nm);
    j.at("title").get_to(x.title);
    j.at("description").get_to(x.description);
    j.at("annotation").get_to(x.annotation);
    j.at("official").get_to(x.official);
    j.at("public").get_to(x.pub);
    j.at("lists").get_to(x.lists);
    j.at("students").get_to(x.students);
    j.at("tutors").get_to(x.tutors);
            }

            void to_json(json& j, const InstructorCourseUpdate& x) {
                j = json{
            {"course_nm", x.course_nm},
{"title", x.title},
{"description", x.description},
{"annotation", x.annotation},
{"official", x.official},
{"public", x.pub},
{"lists", x.lists},
{"students", x.students},
{"tutors", x.tutors}
                };
            }

            void from_json(const json& j, InstructorCourseUpdate& x) {
                j.at("course_nm").get_to(x.course_nm);
    j.at("title").get_to(x.title);
    j.at("description").get_to(x.description);
    j.at("annotation").get_to(x.annotation);
    j.at("official").get_to(x.official);
    j.at("public").get_to(x.pub);
    j.at("lists").get_to(x.lists);
    j.at("students").get_to(x.students);
    j.at("tutors").get_to(x.tutors);
            }

            void to_json(json& j, const InstructorExamCourse& x) {
                j = json{
            {"course_nm", x.course_nm},
{"title", x.title}
                };
            }

            void from_json(const json& j, InstructorExamCourse& x) {
                j.at("course_nm").get_to(x.course_nm);
    j.at("title").get_to(x.title);
            }


            void to_json(json& j, const InstructorExamCompiler& x) {
                j = json{
            {"compiler_id", x.compiler_id},
{"name", x.name}
                };
            }

            void from_json(const json& j, InstructorExamCompiler& x) {
                j.at("compiler_id").get_to(x.compiler_id);
    j.at("name").get_to(x.name);
            }

            void to_json(json& j, const InstructorExamProblem& x) {
                j = json{
            {"problem_nm", x.problem_nm},
{"weight", x.weight},
{"icon", x.icon},
{"caption", x.caption}
                };
            }

            void from_json(const json& j, InstructorExamProblem& x) {
                j.at("problem_nm").get_to(x.problem_nm);
    j.at("weight").get_to(x.weight);
    j.at("icon").get_to(x.icon);
    j.at("caption").get_to(x.caption);
            }

            void to_json(json& j, const InstructorExamStudent& x) {
                j = json{
            {"email", x.email},
{"name", x.name},
{"code", x.code},
{"restricted", x.restricted},
{"annotation", x.annotation},
{"result", x.result},
{"finished", x.finished},
{"banned", x.banned},
{"reason_ban", x.reason_ban},
{"inc", x.inc},
{"reason_inc", x.reason_inc},
{"taken_exam", x.taken_exam},
{"emergency_password", x.emergency_password},
{"invited", x.invited}
                };
            }

            void from_json(const json& j, InstructorExamStudent& x) {
                j.at("email").get_to(x.email);
    j.at("name").get_to(x.name);
    j.at("code").get_to(x.code);
    j.at("restricted").get_to(x.restricted);
    j.at("annotation").get_to(x.annotation);
    j.at("result").get_to(x.result);
    j.at("finished").get_to(x.finished);
    j.at("banned").get_to(x.banned);
    j.at("reason_ban").get_to(x.reason_ban);
    j.at("inc").get_to(x.inc);
    j.at("reason_inc").get_to(x.reason_inc);
    j.at("taken_exam").get_to(x.taken_exam);
    j.at("emergency_password").get_to(x.emergency_password);
    j.at("invited").get_to(x.invited);
            }

            void to_json(json& j, const InstructorExamCreation& x) {
                j = json{
            {"exam_nm", x.exam_nm},
{"course_nm", x.course_nm},
{"title", x.title},
{"exp_time_start", x.exp_time_start}
                };
            }

            void from_json(const json& j, InstructorExamCreation& x) {
                j.at("exam_nm").get_to(x.exam_nm);
    j.at("course_nm").get_to(x.course_nm);
    j.at("title").get_to(x.title);
    j.at("exp_time_start").get_to(x.exp_time_start);
            }

            void to_json(json& j, const InstructorExamUpdate& x) {
                j = json{
            {"exam_nm", x.exam_nm},
{"course_nm", x.course_nm},
{"title", x.title},
{"place", x.place},
{"code", x.code},
{"description", x.description},
{"time_start", x.time_start},
{"exp_time_start", x.exp_time_start},
{"running_time", x.running_time},
{"visible_submissions", x.visible_submissions},
{"started_by", x.started_by},
{"contest", x.contest},
{"instructions", x.instructions},
{"avatars", x.avatars},
{"anonymous", x.anonymous}
                };
            }

            void from_json(const json& j, InstructorExamUpdate& x) {
                j.at("exam_nm").get_to(x.exam_nm);
    j.at("course_nm").get_to(x.course_nm);
    j.at("title").get_to(x.title);
    j.at("place").get_to(x.place);
    j.at("code").get_to(x.code);
    j.at("description").get_to(x.description);
    j.at("time_start").get_to(x.time_start);
    j.at("exp_time_start").get_to(x.exp_time_start);
    j.at("running_time").get_to(x.running_time);
    j.at("visible_submissions").get_to(x.visible_submissions);
    j.at("started_by").get_to(x.started_by);
    j.at("contest").get_to(x.contest);
    j.at("instructions").get_to(x.instructions);
    j.at("avatars").get_to(x.avatars);
    j.at("anonymous").get_to(x.anonymous);
            }

            void to_json(json& j, const InstructorNewExamStudent& x) {
                j = json{
            {"email", x.email},
{"invited", x.invited},
{"restricted", x.restricted},
{"code", x.code},
{"emergency_password", x.emergency_password},
{"annotation", x.annotation}
                };
            }

            void from_json(const json& j, InstructorNewExamStudent& x) {
                j.at("email").get_to(x.email);
    j.at("invited").get_to(x.invited);
    j.at("restricted").get_to(x.restricted);
    j.at("code").get_to(x.code);
    j.at("emergency_password").get_to(x.emergency_password);
    j.at("annotation").get_to(x.annotation);
            }

            void to_json(json& j, const InstructorExamSubmissionsOptions& x) {
                j = json{
            {"problems", x.problems},
{"include_source", x.include_source},
{"include_pdf", x.include_pdf},
{"include_metadata", x.include_metadata},
{"only_last", x.only_last},
{"font_size", x.font_size},
{"layout", x.layout},
{"obscure_private_testcases_names", x.obscure_private_testcases_names}
                };
            }

            void from_json(const json& j, InstructorExamSubmissionsOptions& x) {
                j.at("problems").get_to(x.problems);
    j.at("include_source").get_to(x.include_source);
    j.at("include_pdf").get_to(x.include_pdf);
    j.at("include_metadata").get_to(x.include_metadata);
    j.at("only_last").get_to(x.only_last);
    j.at("font_size").get_to(x.font_size);
    j.at("layout").get_to(x.layout);
    j.at("obscure_private_testcases_names").get_to(x.obscure_private_testcases_names);
            }

            void to_json(json& j, const Pack& x) {
                j = json{
            {"message", x.message},
{"href", x.href}
                };
            }

            void from_json(const json& j, Pack& x) {
                j.at("message").get_to(x.message);
    j.at("href").get_to(x.href);
            }

            void to_json(json& j, const InstructorBriefExam& x) {
                j = json{
            {"exam_nm", x.exam_nm},
{"title", x.title},
{"place", x.place},
{"description", x.description},
{"code", x.code},
{"time_start", x.time_start},
{"exp_time_start", x.exp_time_start},
{"running_time", x.running_time},
{"visible_submissions", x.visible_submissions},
{"started_by", x.started_by},
{"contest", x.contest},
{"instructions", x.instructions},
{"avatars", x.avatars},
{"anonymous", x.anonymous},
{"course", x.course},
{"created_at", x.created_at},
{"updated_at", x.updated_at}
                };
            }

            void from_json(const json& j, InstructorBriefExam& x) {
                j.at("exam_nm").get_to(x.exam_nm);
    j.at("title").get_to(x.title);
    j.at("place").get_to(x.place);
    j.at("description").get_to(x.description);
    j.at("code").get_to(x.code);
    j.at("time_start").get_to(x.time_start);
    j.at("exp_time_start").get_to(x.exp_time_start);
    j.at("running_time").get_to(x.running_time);
    j.at("visible_submissions").get_to(x.visible_submissions);
    j.at("started_by").get_to(x.started_by);
    j.at("contest").get_to(x.contest);
    j.at("instructions").get_to(x.instructions);
    j.at("avatars").get_to(x.avatars);
    j.at("anonymous").get_to(x.anonymous);
    j.at("course").get_to(x.course);
    j.at("created_at").get_to(x.created_at);
    j.at("updated_at").get_to(x.updated_at);
            }

            void to_json(json& j, const InstructorExam& x) {
                j = json{
            {"exam_nm", x.exam_nm},
{"title", x.title},
{"place", x.place},
{"description", x.description},
{"code", x.code},
{"time_start", x.time_start},
{"exp_time_start", x.exp_time_start},
{"running_time", x.running_time},
{"visible_submissions", x.visible_submissions},
{"started_by", x.started_by},
{"contest", x.contest},
{"instructions", x.instructions},
{"avatars", x.avatars},
{"anonymous", x.anonymous},
{"course", x.course},
{"created_at", x.created_at},
{"updated_at", x.updated_at},
{"documents", x.documents},
{"compilers", x.compilers},
{"problems", x.problems},
{"students", x.students}
                };
            }

            void from_json(const json& j, InstructorExam& x) {
                j.at("exam_nm").get_to(x.exam_nm);
    j.at("title").get_to(x.title);
    j.at("place").get_to(x.place);
    j.at("description").get_to(x.description);
    j.at("code").get_to(x.code);
    j.at("time_start").get_to(x.time_start);
    j.at("exp_time_start").get_to(x.exp_time_start);
    j.at("running_time").get_to(x.running_time);
    j.at("visible_submissions").get_to(x.visible_submissions);
    j.at("started_by").get_to(x.started_by);
    j.at("contest").get_to(x.contest);
    j.at("instructions").get_to(x.instructions);
    j.at("avatars").get_to(x.avatars);
    j.at("anonymous").get_to(x.anonymous);
    j.at("course").get_to(x.course);
    j.at("created_at").get_to(x.created_at);
    j.at("updated_at").get_to(x.updated_at);
    j.at("documents").get_to(x.documents);
    j.at("compilers").get_to(x.compilers);
    j.at("problems").get_to(x.problems);
    j.at("students").get_to(x.students);
            }

            void to_json(json& j, const ExamStatisticsEntry& x) {
                j = json{
            {"minute", x.minute},
{"ok", x.ok},
{"ko", x.ko}
                };
            }

            void from_json(const json& j, ExamStatisticsEntry& x) {
                j.at("minute").get_to(x.minute);
    j.at("ok").get_to(x.ok);
    j.at("ko").get_to(x.ko);
            }

            void to_json(json& j, const ExamStatistics& x) {
                j = json{
            {"submissions", x.submissions},
{"statuses", x.statuses},
{"timeline", x.timeline},
{"compilers", x.compilers},
{"proglangs", x.proglangs}
                };
            }

            void from_json(const json& j, ExamStatistics& x) {
                j.at("submissions").get_to(x.submissions);
    j.at("statuses").get_to(x.statuses);
    j.at("timeline").get_to(x.timeline);
    j.at("compilers").get_to(x.compilers);
    j.at("proglangs").get_to(x.proglangs);
            }

            void to_json(json& j, const RankingResult& x) {
                j = json{
            {"problem_nm", x.problem_nm},
{"submissions", x.submissions},
{"verdict", x.verdict},
{"score", x.score},
{"time", x.time},
{"penalty", x.penalty},
{"wrongs", x.wrongs}
                };
            }

            void from_json(const json& j, RankingResult& x) {
                j.at("problem_nm").get_to(x.problem_nm);
    j.at("submissions").get_to(x.submissions);
    j.at("verdict").get_to(x.verdict);
    j.at("score").get_to(x.score);
    j.at("time").get_to(x.time);
    j.at("penalty").get_to(x.penalty);
    j.at("wrongs").get_to(x.wrongs);
            }

            void to_json(json& j, const RankingRow& x) {
                j = json{
            {"position", x.position},
{"name", x.name},
{"avatar", x.avatar},
{"score", x.score},
{"time", x.time},
{"invited", x.invited},
{"submissions", x.submissions},
{"rankingResults", x.rankingResults}
                };
            }

            void from_json(const json& j, RankingRow& x) {
                j.at("position").get_to(x.position);
    j.at("name").get_to(x.name);
    j.at("avatar").get_to(x.avatar);
    j.at("score").get_to(x.score);
    j.at("time").get_to(x.time);
    j.at("invited").get_to(x.invited);
    j.at("submissions").get_to(x.submissions);
    j.at("rankingResults").get_to(x.rankingResults);
            }


            void to_json(json& j, const WebStream& x) {
                j = json{
            {"title", x.title},
{"id", x.id}
                };
            }

            void from_json(const json& j, WebStream& x) {
                j.at("title").get_to(x.title);
    j.at("id").get_to(x.id);
            }

            void to_json(json& j, const ProblemGenerationInfo& x) {
                j = json{
            {"title", x.title},
{"prompt", x.prompt},
{"model", x.model}
                };
            }

            void from_json(const json& j, ProblemGenerationInfo& x) {
                j.at("title").get_to(x.title);
    j.at("prompt").get_to(x.prompt);
    j.at("model").get_to(x.model);
            }

            void to_json(json& j, const Deprecation& x) {
                j = json{
            {"problem_nm", x.problem_nm},
{"reason", x.reason}
                };
            }

            void from_json(const json& j, Deprecation& x) {
                j.at("problem_nm").get_to(x.problem_nm);
    j.at("reason").get_to(x.reason);
            }

            void to_json(json& j, const SharingSettings& x) {
                j = json{
            {"problem_nm", x.problem_nm},
{"passcode", x.passcode},
{"shared_testcases", x.shared_testcases},
{"shared_solutions", x.shared_solutions}
                };
            }

            void from_json(const json& j, SharingSettings& x) {
                j.at("problem_nm").get_to(x.problem_nm);
    j.at("passcode").get_to(x.passcode);
    j.at("shared_testcases").get_to(x.shared_testcases);
    j.at("shared_solutions").get_to(x.shared_solutions);
            }

            void to_json(json& j, const ProblemAnonymousSubmission& x) {
                j = json{
            {"time", x.time},
{"anonymous_user_id", x.anonymous_user_id},
{"problem_id", x.problem_id},
{"verdict", x.verdict},
{"compiler_id", x.compiler_id},
{"proglang", x.proglang}
                };
            }

            void from_json(const json& j, ProblemAnonymousSubmission& x) {
                j.at("time").get_to(x.time);
    j.at("anonymous_user_id").get_to(x.anonymous_user_id);
    j.at("problem_id").get_to(x.problem_id);
    j.at("verdict").get_to(x.verdict);
    j.at("compiler_id").get_to(x.compiler_id);
    j.at("proglang").get_to(x.proglang);
            }

            void to_json(json& j, const ShareWithInp& x) {
                j = json{
            {"problem_nm", x.problem_nm},
{"emails", x.emails},
{"text", x.text}
                };
            }

            void from_json(const json& j, ShareWithInp& x) {
                j.at("problem_nm").get_to(x.problem_nm);
    j.at("emails").get_to(x.emails);
    j.at("text").get_to(x.text);
            }

            void to_json(json& j, const ProblemPopularityBucketEntry& x) {
                j = json{
            {"log2_bucket", x.log2_bucket},
{"bucket_min", x.bucket_min},
{"bucket_max", x.bucket_max},
{"problem_count", x.problem_count}
                };
            }

            void from_json(const json& j, ProblemPopularityBucketEntry& x) {
                j.at("log2_bucket").get_to(x.log2_bucket);
    j.at("bucket_min").get_to(x.bucket_min);
    j.at("bucket_max").get_to(x.bucket_max);
    j.at("problem_count").get_to(x.problem_count);
            }

            void to_json(json& j, const SubmissionQuery& x) {
                j = json{
            {"email", x.email},
{"problem_nm", x.problem_nm},
{"problem_id", x.problem_id},
{"time", x.time},
{"ip", x.ip},
{"verdict", x.verdict}
                };
            }

            void from_json(const json& j, SubmissionQuery& x) {
                j.at("email").get_to(x.email);
    j.at("problem_nm").get_to(x.problem_nm);
    j.at("problem_id").get_to(x.problem_id);
    j.at("time").get_to(x.time);
    j.at("ip").get_to(x.ip);
    j.at("verdict").get_to(x.verdict);
            }



            void to_json(json& j, const ChatMessage& x) {
                j = json{
            {"role", x.role},
{"content", x.content}
                };
            }

            void from_json(const json& j, ChatMessage& x) {
                j.at("role").get_to(x.role);
    j.at("content").get_to(x.content);
            }

            void to_json(json& j, const ChatPrompt& x) {
                j = json{
            {"model", x.model},
{"label", x.label},
{"messages", x.messages},
{"addUsage", x.addUsage}
                };
            }

            void from_json(const json& j, ChatPrompt& x) {
                j.at("model").get_to(x.model);
    j.at("label").get_to(x.label);
    j.at("messages").get_to(x.messages);
    j.at("addUsage").get_to(x.addUsage);
            }

            void to_json(json& j, const LlmUsageEntry& x) {
                j = json{
            {"id", x.id},
{"created_at", x.created_at},
{"model", x.model},
{"label", x.label},
{"duration", x.duration},
{"input_tokens", x.input_tokens},
{"output_tokens", x.output_tokens},
{"finish_reason", x.finish_reason}
                };
            }

            void from_json(const json& j, LlmUsageEntry& x) {
                j.at("id").get_to(x.id);
    j.at("created_at").get_to(x.created_at);
    j.at("model").get_to(x.model);
    j.at("label").get_to(x.label);
    j.at("duration").get_to(x.duration);
    j.at("input_tokens").get_to(x.input_tokens);
    j.at("output_tokens").get_to(x.output_tokens);
    j.at("finish_reason").get_to(x.finish_reason);
            }

            void to_json(json& j, const CreateImageInput& x) {
                j = json{
            {"model", x.model},
{"label", x.label},
{"prompt", x.prompt},
{"size", x.size}
                };
            }

            void from_json(const json& j, CreateImageInput& x) {
                j.at("model").get_to(x.model);
    j.at("label").get_to(x.label);
    j.at("prompt").get_to(x.prompt);
    j.at("size").get_to(x.size);
            }

            void to_json(json& j, const SubmitPlayerInput& x) {
                j = json{
            {"problem_id", x.problem_id},
{"annotation", x.annotation},
{"source_code", x.source_code},
{"callback_url", x.callback_url}
                };
            }

            void from_json(const json& j, SubmitPlayerInput& x) {
                j.at("problem_id").get_to(x.problem_id);
    j.at("annotation").get_to(x.annotation);
    j.at("source_code").get_to(x.source_code);
    j.at("callback_url").get_to(x.callback_url);
            }


            void to_json(json& j, const SubmitMatchInput& x) {
                j = json{
            {"problem_id", x.problem_id},
{"annotation", x.annotation},
{"source_codes", x.source_codes},
{"callback_url", x.callback_url}
                };
            }

            void from_json(const json& j, SubmitMatchInput& x) {
                j.at("problem_id").get_to(x.problem_id);
    j.at("annotation").get_to(x.annotation);
    j.at("source_codes").get_to(x.source_codes);
    j.at("callback_url").get_to(x.callback_url);
            }


            void to_json(json& j, const GetGameResultOutput& x) {
                j = json{
            {"todo", x.todo}
                };
            }

            void from_json(const json& j, GetGameResultOutput& x) {
                j.at("todo").get_to(x.todo);
            }



            void to_json(json& j, const InstructorEntry& x) {
                j = json{
            {"username", x.username},
{"name", x.name},
{"email", x.email}
                };
            }

            void from_json(const json& j, InstructorEntry& x) {
                j.at("username").get_to(x.username);
    j.at("name").get_to(x.name);
    j.at("email").get_to(x.email);
            }


            void to_json(json& j, const UserCreation& x) {
                j = json{
            {"email", x.email},
{"name", x.name},
{"username", x.username},
{"password", x.password},
{"administrator", x.administrator},
{"instructor", x.instructor}
                };
            }

            void from_json(const json& j, UserCreation& x) {
                j.at("email").get_to(x.email);
    j.at("name").get_to(x.name);
    j.at("username").get_to(x.username);
    j.at("password").get_to(x.password);
    j.at("administrator").get_to(x.administrator);
    j.at("instructor").get_to(x.instructor);
            }

            void to_json(json& j, const UserEmailAndName& x) {
                j = json{
            {"email", x.email},
{"name", x.name}
                };
            }

            void from_json(const json& j, UserEmailAndName& x) {
                j.at("email").get_to(x.email);
    j.at("name").get_to(x.name);
            }


            void to_json(json& j, const ProfileForAdmin& x) {
                j = json{
            {"user_id", x.user_id},
{"user_uid", x.user_uid},
{"email", x.email},
{"name", x.name},
{"username", x.username},
{"nickname", x.nickname},
{"webpage", x.webpage},
{"description", x.description},
{"affiliation", x.affiliation},
{"birth_year", x.birth_year},
{"max_subsxhour", x.max_subsxhour},
{"max_subsxday", x.max_subsxday},
{"administrator", x.administrator},
{"instructor", x.instructor},
{"parent_email", x.parent_email},
{"country_id", x.country_id},
{"timezone_id", x.timezone_id},
{"compiler_id", x.compiler_id},
{"language_id", x.language_id},
{"locked", x.locked},
{"banned", x.banned},
{"nb_bans", x.nb_bans},
{"reason", x.reason},
{"creation_date", x.creation_date}
                };
            }

            void from_json(const json& j, ProfileForAdmin& x) {
                j.at("user_id").get_to(x.user_id);
    j.at("user_uid").get_to(x.user_uid);
    j.at("email").get_to(x.email);
    j.at("name").get_to(x.name);
    j.at("username").get_to(x.username);
    j.at("nickname").get_to(x.nickname);
    j.at("webpage").get_to(x.webpage);
    j.at("description").get_to(x.description);
    j.at("affiliation").get_to(x.affiliation);
    j.at("birth_year").get_to(x.birth_year);
    j.at("max_subsxhour").get_to(x.max_subsxhour);
    j.at("max_subsxday").get_to(x.max_subsxday);
    j.at("administrator").get_to(x.administrator);
    j.at("instructor").get_to(x.instructor);
    j.at("parent_email").get_to(x.parent_email);
    j.at("country_id").get_to(x.country_id);
    j.at("timezone_id").get_to(x.timezone_id);
    j.at("compiler_id").get_to(x.compiler_id);
    j.at("language_id").get_to(x.language_id);
    j.at("locked").get_to(x.locked);
    j.at("banned").get_to(x.banned);
    j.at("nb_bans").get_to(x.nb_bans);
    j.at("reason").get_to(x.reason);
    j.at("creation_date").get_to(x.creation_date);
            }

            void to_json(json& j, const DatabasesInfoItem& x) {
                j = json{
            {"name", x.name},
{"size", x.size},
{"mtime", x.mtime}
                };
            }

            void from_json(const json& j, DatabasesInfoItem& x) {
                j.at("name").get_to(x.name);
    j.at("size").get_to(x.size);
    j.at("mtime").get_to(x.mtime);
            }


            void to_json(json& j, const FreeDiskSpaceItem& x) {
                j = json{
            {"disk", x.disk},
{"filesystem", x.filesystem},
{"size", x.size},
{"used", x.used},
{"available", x.available},
{"use", x.use},
{"mounted", x.mounted}
                };
            }

            void from_json(const json& j, FreeDiskSpaceItem& x) {
                j.at("disk").get_to(x.disk);
    j.at("filesystem").get_to(x.filesystem);
    j.at("size").get_to(x.size);
    j.at("used").get_to(x.used);
    j.at("available").get_to(x.available);
    j.at("use").get_to(x.use);
    j.at("mounted").get_to(x.mounted);
            }



            void to_json(json& j, const RecentConnectedUsers& x) {
                j = json{
            {"latest_hour", x.latest_hour},
{"latest_day", x.latest_day},
{"latest_week", x.latest_week},
{"latest_month", x.latest_month},
{"latest_year", x.latest_year}
                };
            }

            void from_json(const json& j, RecentConnectedUsers& x) {
                j.at("latest_hour").get_to(x.latest_hour);
    j.at("latest_day").get_to(x.latest_day);
    j.at("latest_week").get_to(x.latest_week);
    j.at("latest_month").get_to(x.latest_month);
    j.at("latest_year").get_to(x.latest_year);
            }

            void to_json(json& j, const RecentSubmissions& x) {
                j = json{
            {"latest_01_minutes", x.latest_01_minutes},
{"latest_05_minutes", x.latest_05_minutes},
{"latest_15_minutes", x.latest_15_minutes},
{"latest_60_minutes", x.latest_60_minutes}
                };
            }

            void from_json(const json& j, RecentSubmissions& x) {
                j.at("latest_01_minutes").get_to(x.latest_01_minutes);
    j.at("latest_05_minutes").get_to(x.latest_05_minutes);
    j.at("latest_15_minutes").get_to(x.latest_15_minutes);
    j.at("latest_60_minutes").get_to(x.latest_60_minutes);
            }

            void to_json(json& j, const RecentLoadAverages& x) {
                j = json{
            {"latest_01_minutes", x.latest_01_minutes},
{"latest_05_minutes", x.latest_05_minutes},
{"latest_15_minutes", x.latest_15_minutes}
                };
            }

            void from_json(const json& j, RecentLoadAverages& x) {
                j.at("latest_01_minutes").get_to(x.latest_01_minutes);
    j.at("latest_05_minutes").get_to(x.latest_05_minutes);
    j.at("latest_15_minutes").get_to(x.latest_15_minutes);
            }

            void to_json(json& j, const SubmissionsHistograms& x) {
                j = json{
            {"latest_hour", x.latest_hour},
{"latest_day", x.latest_day}
                };
            }

            void from_json(const json& j, SubmissionsHistograms& x) {
                j.at("latest_hour").get_to(x.latest_hour);
    j.at("latest_day").get_to(x.latest_day);
            }

            void to_json(json& j, const Zombies& x) {
                j = json{
            {"ies", x.ies},
{"pendings", x.pendings}
                };
            }

            void from_json(const json& j, Zombies& x) {
                j.at("ies").get_to(x.ies);
    j.at("pendings").get_to(x.pendings);
            }

            void to_json(json& j, const AdminDashboard& x) {
                j = json{
            {"databases_info", x.databases_info},
{"free_disk_space", x.free_disk_space},
{"recent_load_averages", x.recent_load_averages},
{"recent_connected_users", x.recent_connected_users},
{"recent_submissions", x.recent_submissions},
{"submissions_histograms", x.submissions_histograms},
{"zombies", x.zombies}
                };
            }

            void from_json(const json& j, AdminDashboard& x) {
                j.at("databases_info").get_to(x.databases_info);
    j.at("free_disk_space").get_to(x.free_disk_space);
    j.at("recent_load_averages").get_to(x.recent_load_averages);
    j.at("recent_connected_users").get_to(x.recent_connected_users);
    j.at("recent_submissions").get_to(x.recent_submissions);
    j.at("submissions_histograms").get_to(x.submissions_histograms);
    j.at("zombies").get_to(x.zombies);
            }

            void to_json(json& j, const UpcomingExam& x) {
                j = json{
            {"exam_nm", x.exam_nm},
{"title", x.title},
{"username", x.username},
{"email", x.email},
{"exp_time_start", x.exp_time_start},
{"running_time", x.running_time},
{"students", x.students},
{"name", x.name},
{"contest", x.contest}
                };
            }

            void from_json(const json& j, UpcomingExam& x) {
                j.at("exam_nm").get_to(x.exam_nm);
    j.at("title").get_to(x.title);
    j.at("username").get_to(x.username);
    j.at("email").get_to(x.email);
    j.at("exp_time_start").get_to(x.exp_time_start);
    j.at("running_time").get_to(x.running_time);
    j.at("students").get_to(x.students);
    j.at("name").get_to(x.name);
    j.at("contest").get_to(x.contest);
            }


            void to_json(json& j, const SubmissionQueueItem& x) {
                j = json{
            {"submission_uid", x.submission_uid},
{"submission_id", x.submission_id},
{"problem_id", x.problem_id},
{"compiler_id", x.compiler_id},
{"time_in", x.time_in},
{"exam_id", x.exam_id},
{"veredict", x.veredict},
{"user_id", x.user_id},
{"user__name", x.user__name},
{"problem__title", x.problem__title}
                };
            }

            void from_json(const json& j, SubmissionQueueItem& x) {
                j.at("submission_uid").get_to(x.submission_uid);
    j.at("submission_id").get_to(x.submission_id);
    j.at("problem_id").get_to(x.problem_id);
    j.at("compiler_id").get_to(x.compiler_id);
    j.at("time_in").get_to(x.time_in);
    j.at("exam_id").get_to(x.exam_id);
    j.at("veredict").get_to(x.veredict);
    j.at("user_id").get_to(x.user_id);
    j.at("user__name").get_to(x.user__name);
    j.at("problem__title").get_to(x.problem__title);
            }


            void to_json(json& j, const QueueQuery& x) {
                j = json{
            {"verdicts", x.verdicts},
{"limit", x.limit}
                };
            }

            void from_json(const json& j, QueueQuery& x) {
                j.at("verdicts").get_to(x.verdicts);
    j.at("limit").get_to(x.limit);
            }

            void to_json(json& j, const UserRankingEntry& x) {
                j = json{
            {"user_id", x.user_id},
{"nickname", x.nickname},
{"email", x.email},
{"name", x.name},
{"problems", x.problems}
                };
            }

            void from_json(const json& j, UserRankingEntry& x) {
                j.at("user_id").get_to(x.user_id);
    j.at("nickname").get_to(x.nickname);
    j.at("email").get_to(x.email);
    j.at("name").get_to(x.name);
    j.at("problems").get_to(x.problems);
            }


            void to_json(json& j, const DateRange& x) {
                j = json{
            {"start", x.start},
{"end", x.end}
                };
            }

            void from_json(const json& j, DateRange& x) {
                j.at("start").get_to(x.start);
    j.at("end").get_to(x.end);
            }

            void to_json(json& j, const TwoFloats& x) {
                j = json{
            {"a", x.a},
{"b", x.b}
                };
            }

            void from_json(const json& j, TwoFloats& x) {
                j.at("a").get_to(x.a);
    j.at("b").get_to(x.b);
            }

            void to_json(json& j, const TwoInts& x) {
                j = json{
            {"a", x.a},
{"b", x.b}
                };
            }

            void from_json(const json& j, TwoInts& x) {
                j.at("a").get_to(x.a);
    j.at("b").get_to(x.b);
            }

            void to_json(json& j, const Name& x) {
                j = json{
            {"name", x.name}
                };
            }

            void from_json(const json& j, Name& x) {
                j.at("name").get_to(x.name);
            }

            void to_json(json& j, const SomeType& x) {
                j = json{
            {"a", x.a},
{"b", x.b},
{"c", x.c},
{"d", x.d}
                };
            }

            void from_json(const json& j, SomeType& x) {
                j.at("a").get_to(x.a);
    j.at("b").get_to(x.b);
    j.at("c").get_to(x.c);
    j.at("d").get_to(x.d);
            }

// modules



/**
    Module to download clients.
*/
namespace clients {


Download python() {
    /**
    Get Python client.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("clients.python", ijson, {});
    return ofiles[0];
}

Download typescript() {
    /**
    Get TypeScript client.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("clients.typescript", ijson, {});
    return ofiles[0];
}

Download javascript() {
    /**
    Get JavaScript client.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("clients.javascript", ijson, {});
    return ofiles[0];
}

Download java() {
    /**
    Get Java client.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("clients.java", ijson, {});
    return ofiles[0];
}

Download cpp() {
    /**
    Get Cpp client.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("clients.cpp", ijson, {});
    return ofiles[0];
}

Download php() {
    /**
    Get PHP client.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("clients.php", ijson, {});
    return ofiles[0];
}

}


/**
    Module to provide authentication functions.
*/
namespace auth {


CredentialsOut login(const CredentialsIn& data) {
    /**
    Login: Get an access token.

    🔐 Authenticated        

    Returns a token on success. Throws UnauthorizedError on failure.
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("auth.login", ijson, {});
    return ojson;
}

void logout() {
    /**
    Logout: Discard the access token.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("auth.logout", ijson, {});
    return ;
}

CredentialsOut login_exam(const ExamCredentialsIn& data) {
    /**
    Login to an exam: Get an access token for an exam.

    🔐 Authenticated        

    Returns a token on success. Throws UnauthorizedError on failure.
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("auth.loginExam", ijson, {});
    return ojson;
}

CredentialsOut login_with_username(const CredentialsWithUsernameIn& data) {
    /**
    Login: Get an access token.

    🔐 Authenticated        

    Returns a token on success. Throws UnauthorizedError on failure. Created for backward compatibility, do not use.
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("auth.loginWithUsername", ijson, {});
    return ojson;
}

}


/**
    Module with miscellaneous endpoints
*/
namespace misc {


ApiVersion get_api_version() {
    /**
    Get version information of the API.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("misc.getApiVersion", ijson, {});
    return ojson;
}

RequestInformation get_request_information() {
    /**
    Get requestion information.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("misc.getRequestInformation", ijson, {});
    return ojson;
}

std::string get_fortune() {
    /**
    Get a fortune message.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("misc.getFortune", ijson, {});
    return ojson;
}

Time get_time() {
    /**
    Get server time.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("misc.getTime", ijson, {});
    return ojson;
}

HomepageStats get_homepage_stats() {
    /**
    Get homepage stats.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("misc.getHomepageStats", ijson, {});
    return ojson;
}

Download get_logo() {
    /**
    Get Jutge.org logo as a PNG file.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("misc.getLogo", ijson, {});
    return ofiles[0];
}

std::vector<std::string> get_avatar_packs() {
    /**
    Returns all packs of avatars.

    🔐 Authenticated        

    Avatars are used in exams and contests to identify students or participants.
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("misc.getAvatarPacks", ijson, {});
    return ojson;
}

TagsDict get_exam_icons() {
    /**
    Returns all exam icons.

    🔐 Authenticated        

    Exam icon are used in exams and contests to identify problems.
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("misc.getExamIcons", ijson, {});
    return ojson;
}

ColorMapping get_colors() {
    /**
    Returns color mappings using colornames notation.

    🔐 Authenticated        

    Color mappings may be used to colorize keys in the frontends. Color names are as defined in https://github.com/timoxley/colornames
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("misc.getColors", ijson, {});
    return ojson;
}

ColorMapping get_hex_colors() {
    /**
    Returns color mappings using hexadecimal color notation.

    🔐 Authenticated        

    Color mappings may be used to colorize keys in the frontends. 
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("misc.getHexColors", ijson, {});
    return ojson;
}

std::map<std::string, std::string> get_demos_for_compiler(const std::string& compiler_id) {
    /**
    Returns code demos for a given compiler as a dictionary of base64 codes indexed by problem_nm.

    🔐 Authenticated        
    **/
    
    const json ijson = compiler_id;
    const auto [ojson, ofiles] = execute("misc.getDemosForCompiler", ijson, {});
    return ojson;
}

}


/**
    Module with quite static tables
*/
namespace tables {


AllTables get() {
    /**
    Returns all tables.

    🔐 Authenticated        

    Returns all compilers, countries, drivers, languages, proglangs, and verdicts in a single request. This data does not change often, so you should only request it once per session.
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("tables.get", ijson, {});
    return ojson;
}

std::map<std::string, Language> get_languages() {
    /**
    Returns all languages.

    🔐 Authenticated        

    Returns all languages as a dictionary of objects, indexed by id.
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("tables.getLanguages", ijson, {});
    return ojson;
}

std::map<std::string, Country> get_countries() {
    /**
    Returns all countries.

    🔐 Authenticated        

    Returns all countries as a dictionary of objects, indexed by id.
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("tables.getCountries", ijson, {});
    return ojson;
}

std::map<std::string, Compiler> get_compilers() {
    /**
    Returns all compilers.

    🔐 Authenticated        

    Returns all compilers as a dictionary of objects, indexed by id.
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("tables.getCompilers", ijson, {});
    return ojson;
}

std::map<std::string, Driver> get_drivers() {
    /**
    Returns all drivers.

    🔐 Authenticated        

    Returns all drivers as a dictionary of objects, indexed by id.
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("tables.getDrivers", ijson, {});
    return ojson;
}

std::map<std::string, Verdict> get_verdicts() {
    /**
    Returns all verdicts.

    🔐 Authenticated        

    Returns all verdicts as a dictionary of objects, indexed by id.
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("tables.getVerdicts", ijson, {});
    return ojson;
}

std::map<std::string, Proglang> get_proglangs() {
    /**
    Returns all proglangs.

    🔐 Authenticated        

    Returns all proglangs (porgramming languages) as a dictionary of objects, indexed by id.
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("tables.getProglangs", ijson, {});
    return ojson;
}

}


/**
    Module with endpoints related to problems.

There are two types of problems: *abstract problems* and *problems*. An abstract
problem is a group of problems. A problem is an instance of an abstract problem
in a particular language. Abstract problems are identified by a `problem_nm` (such
as 'P68688'), while problems are identified by a `problem_id` including its
`language_id` (such as 'P68688_en'). Abstract problems have a list of problems,
while problems have an abstract problem. Abstract problems have an author, while
problems have a translator.

Available problems depend on the actor issuing the request. For example, non
authenticated users can only access public problems, while authenticated
users can potentially access more problems.

*/
namespace problems {


std::map<std::string, AbstractProblem> get_all_abstract_problems() {
    /**
    Get all available abstract problems.

    🔐 Authenticated        

    Includes problems.
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("problems.getAllAbstractProblems", ijson, {});
    return ojson;
}

std::map<std::string, AbstractProblem> get_abstract_problems(const std::string& problem_nms) {
    /**
    Get available abstract problems whose keys are in `problem_nms`.

    🔐 Authenticated        

    Includes problems.
    **/
    
    const json ijson = problem_nms;
    const auto [ojson, ofiles] = execute("problems.getAbstractProblems", ijson, {});
    return ojson;
}

std::map<std::string, AbstractProblem> get_abstract_problems_in_list(const std::string& list_key) {
    /**
    Get available abstract problems that belong to a list.

    🔐 Authenticated        

    Includes problems.
    **/
    
    const json ijson = list_key;
    const auto [ojson, ofiles] = execute("problems.getAbstractProblemsInList", ijson, {});
    return ojson;
}

AbstractProblem get_abstract_problem(const std::string& problem_nm) {
    /**
    Get an abstract problem.

    🔐 Authenticated        

    Includes problems
    **/
    
    const json ijson = problem_nm;
    const auto [ojson, ofiles] = execute("problems.getAbstractProblem", ijson, {});
    return ojson;
}

AbstractProblemSuppl get_abstract_problem_suppl(const std::string& problem_nm) {
    /**
    Get supplementary information of an abstract problem.

    🔐 Authenticated        

    Includes accepted compilers and accepted proglangs
    **/
    
    const json ijson = problem_nm;
    const auto [ojson, ofiles] = execute("problems.getAbstractProblemSuppl", ijson, {});
    return ojson;
}

Problem get_problem(const std::string& problem_id) {
    /**
    Get a problem.

    🔐 Authenticated        

    Includes abstract problem.
    **/
    
    const json ijson = problem_id;
    const auto [ojson, ofiles] = execute("problems.getProblem", ijson, {});
    return ojson;
}

ProblemSuppl get_problem_suppl(const std::string& problem_id) {
    /**
    Get supplementary information of a problem.

    🔐 Authenticated        

    Includes accepted compilers, accepted proglangs, official solutions
checks and handler specifications
    **/
    
    const json ijson = problem_id;
    const auto [ojson, ofiles] = execute("problems.getProblemSuppl", ijson, {});
    return ojson;
}

std::vector<Testcase> get_sample_testcases(const std::string& problem_id) {
    /**
    Get sample testcases of a problem.

    🔐 Authenticated        
    **/
    
    const json ijson = problem_id;
    const auto [ojson, ofiles] = execute("problems.getSampleTestcases", ijson, {});
    return ojson;
}

std::vector<Testcase> get_public_testcases(const std::string& problem_id) {
    /**
    Get public testcases of a problem.

    🔐 Authenticated        

    Public testcases are like sample testcases, but are not meant to be shown in the problem statatement, because of their long length.
    **/
    
    const json ijson = problem_id;
    const auto [ojson, ofiles] = execute("problems.getPublicTestcases", ijson, {});
    return ojson;
}

Download get_zip_statement(const std::string& problem_id) {
    /**
    Get ZIP archive of a problem. This includes its statements, templates and public testcases.

    🔐 Authenticated        
    **/
    
    const json ijson = problem_id;
    const auto [ojson, ofiles] = execute("problems.getZipStatement", ijson, {});
    return ofiles[0];
}

Download get_pdf_statement(const std::string& problem_id) {
    /**
    Get PDF statement of a problem.

    🔐 Authenticated        
    **/
    
    const json ijson = problem_id;
    const auto [ojson, ofiles] = execute("problems.getPdfStatement", ijson, {});
    return ofiles[0];
}

std::string get_html_statement(const std::string& problem_id) {
    /**
    Get Html statement of a problem.

    🔐 Authenticated        
    **/
    
    const json ijson = problem_id;
    const auto [ojson, ofiles] = execute("problems.getHtmlStatement", ijson, {});
    return ojson;
}

std::string get_text_statement(const std::string& problem_id) {
    /**
    Get Text statement of a problem.

    🔐 Authenticated        
    **/
    
    const json ijson = problem_id;
    const auto [ojson, ofiles] = execute("problems.getTextStatement", ijson, {});
    return ojson;
}

std::string get_markdown_statement(const std::string& problem_id) {
    /**
    Get Markdown statement of a problem.

    🔐 Authenticated        
    **/
    
    const json ijson = problem_id;
    const auto [ojson, ofiles] = execute("problems.getMarkdownStatement", ijson, {});
    return ojson;
}

std::string get_short_html_statement(const std::string& problem_id) {
    /**
    Get short Html statement of a problem (does not include title or author).

    🔐 Authenticated        
    **/
    
    const json ijson = problem_id;
    const auto [ojson, ofiles] = execute("problems.getShortHtmlStatement", ijson, {});
    return ojson;
}

std::string get_short_text_statement(const std::string& problem_id) {
    /**
    Get short Text statement of a problem (does not include title or author).

    🔐 Authenticated        
    **/
    
    const json ijson = problem_id;
    const auto [ojson, ofiles] = execute("problems.getShortTextStatement", ijson, {});
    return ojson;
}

std::string get_short_markdown_statement(const std::string& problem_id) {
    /**
    Get short Markdown statement of a problem (does not include title or author).

    🔐 Authenticated        
    **/
    
    const json ijson = problem_id;
    const auto [ojson, ofiles] = execute("problems.getShortMarkdownStatement", ijson, {});
    return ojson;
}

std::vector<std::string> get_templates(const std::string& problem_id) {
    /**
    Get list of template files of a problem (`main.*`, `code.*`, `public.tar`, etc.).

    🔐 Authenticated        
    **/
    
    const json ijson = problem_id;
    const auto [ojson, ofiles] = execute("problems.getTemplates", ijson, {});
    return ojson;
}

Download get_template(const std::string& problem_id, const std::string& template) {
    /**
    Get a template file of a problem.

    🔐 Authenticated        
    **/
    
    const json ijson = { {"problem_id", problem_id}, {"template", template} };
    const auto [ojson, ofiles] = execute("problems.getTemplate", ijson, {});
    return ofiles[0];
}

SearchResults semantic_search(const std::string& query, const float& limit) {
    /**
    Get results for a semantic search for statement problems. The array is sorted by score (better at the top).

    🔐 Authenticated        
    **/
    
    const json ijson = { {"query", query}, {"limit", limit} };
    const auto [ojson, ofiles] = execute("problems.semanticSearch", ijson, {});
    return ojson;
}

SearchResults full_text_search(const std::string& query, const float& limit) {
    /**
    Get results for a full text search for statement problems. The array is sorted by score (better at the top). Queries are matched against titles and statements and can use boolean operators.

    🔐 Authenticated        
    **/
    
    const json ijson = { {"query", query}, {"limit", limit} };
    const auto [ojson, ofiles] = execute("problems.fullTextSearch", ijson, {});
    return ojson;
}

std::map<std::string, std::string> get_solutions(const std::string& problem_id) {
    /**
    Get solutions for a problem.

    🔐 Authenticated        

    The keys are the proglangs and the values are the solutions in base64. Pemission is granted to admin, ownerof the problem and instructor when shared solutions are enabled.
    **/
    
    const json ijson = problem_id;
    const auto [ojson, ofiles] = execute("problems.getSolutions", ijson, {});
    return ojson;
}

}


/**
    These operations are available to all users, provided they are authenticated.
*/
namespace student {



/**
    This module exposes all valid keys for problems, courses and lists that a user can access.
*/
namespace keys {


AllKeys get() {
    /**
    Get problem, courses (as enrolled and available) and list keys.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.keys.get", ijson, {});
    return ojson;
}

std::vector<std::string> get_problems() {
    /**
    Get problem keys.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.keys.getProblems", ijson, {});
    return ojson;
}

std::vector<std::string> get_enrolled_courses() {
    /**
    Get enrolled course keys.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.keys.getEnrolledCourses", ijson, {});
    return ojson;
}

std::vector<std::string> get_available_courses() {
    /**
    Get available course keys.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.keys.getAvailableCourses", ijson, {});
    return ojson;
}

std::vector<std::string> get_lists() {
    /**
    Get list keys.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.keys.getLists", ijson, {});
    return ojson;
}

}


/**
    This module exposes the user profile.
*/
namespace profile {


Profile get() {
    /**
    Get the profile.

    🔐 Authenticated        

    In case of exams, some fields are not nullified to avoid cheating.
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.profile.get", ijson, {});
    return ojson;
}

Download get_avatar() {
    /**
    Returns the avatar as a PNG file.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.profile.getAvatar", ijson, {});
    return ofiles[0];
}

void update(const NewProfile& data) {
    /**
    Update the profile

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("student.profile.update", ijson, {});
    return ;
}

void update_avatar(const Blob& ifile) {
    /**
    Update the avatar with new PNG.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.profile.updateAvatar", ijson, {ifile});
    return ;
}

void update_password(const NewPassword& data) {
    /**
    Update password.

    🔐 Authenticated        

    Receives the old password and the new one, and changes the password if the old one is correct and the new one strong enough.
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("student.profile.updatePassword", ijson, {});
    return ;
}

}


namespace dashboard {


int get_absolute_ranking() {
    /**
    Get the ranking of the user over all users in the system.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.dashboard.getAbsoluteRanking", ijson, {});
    return ojson;
}

AllDistributions get_all_distributions() {
    /**
    Get all distributions.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.dashboard.getAllDistributions", ijson, {});
    return ojson;
}

Distribution get_compilers_distribution() {
    /**
    Get compilers distribution.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.dashboard.getCompilersDistribution", ijson, {});
    return ojson;
}

Dashboard get_dashboard() {
    /**
    Get dashboard.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.dashboard.getDashboard", ijson, {});
    return ojson;
}

HeatmapCalendar get_heatmap_calendar() {
    /**
    Get heatmap calendar of submissions.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.dashboard.getHeatmapCalendar", ijson, {});
    return ojson;
}

Distribution get_proglangs_distribution() {
    /**
    Get programming languages distribution.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.dashboard.getProglangsDistribution", ijson, {});
    return ojson;
}

Distribution get_stats() {
    /**
    Get dashboard stats.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.dashboard.getStats", ijson, {});
    return ojson;
}

std::string get_level() {
    /**
    Get fancy Jutge level.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.dashboard.getLevel", ijson, {});
    return ojson;
}

Distribution get_submissions_by_hour() {
    /**
    Get submissions by hour distribution.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.dashboard.getSubmissionsByHour", ijson, {});
    return ojson;
}

Distribution get_submissions_by_week_day() {
    /**
    Get submissions by weekday distribution.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.dashboard.getSubmissionsByWeekDay", ijson, {});
    return ojson;
}

Distribution get_verdicts_distribution() {
    /**
    Get verdicts distribution.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.dashboard.getVerdictsDistribution", ijson, {});
    return ojson;
}

}


namespace submissions {


std::map<std::string, std::map<std::string, Submission>> index_for_abstract_problem(const std::string& problem_nm) {
    /**
    Get index of all submissions for an abstract problem.

    🔐 Authenticated        

    Grouped by problem.
    **/
    
    const json ijson = problem_nm;
    const auto [ojson, ofiles] = execute("student.submissions.indexForAbstractProblem", ijson, {});
    return ojson;
}

std::map<std::string, Submission> index_for_problem(const std::string& problem_id) {
    /**
    Get index of all submissions for a problem.

    🔐 Authenticated        
    **/
    
    const json ijson = problem_id;
    const auto [ojson, ofiles] = execute("student.submissions.indexForProblem", ijson, {});
    return ojson;
}

std::vector<Submission> get_all() {
    /**
    Get all submissions.

    🔐 Authenticated        

    Flat array of submissions in chronological order.
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.submissions.getAll", ijson, {});
    return ojson;
}

std::string submit(const std::string& problem_id, const std::string& compiler_id, const std::string& code, const std::string& annotation) {
    /**
    Submit a solution to the Judge, easy interface.

    🔐 Authenticated        
    **/
    
    const json ijson = { {"problem_id", problem_id}, {"compiler_id", compiler_id}, {"code", code}, {"annotation", annotation} };
    const auto [ojson, ofiles] = execute("student.submissions.submit", ijson, {});
    return ojson;
}

NewSubmissionOut submit_full(const NewSubmissionIn& data, const std::vector<Blob>& ifiles) {
    /**
    Submit a solution to the Judge, full interface.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("student.submissions.submitFull", ijson, ifiles);
    return ojson;
}

Submission get(const GetGameResultIn& data) {
    /**
    Get a submission.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("student.submissions.get", ijson, {});
    return ojson;
}

std::string get_code_as_b64(const GetGameResultIn& data) {
    /**
    Get code for a submission as a string in base64.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("student.submissions.getCodeAsB64", ijson, {});
    return ojson;
}

std::optional<CodeMetrics> get_code_metrics(const GetGameResultIn& data) {
    /**
    Get code metrics for a submission.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("student.submissions.getCodeMetrics", ijson, {});
    return ojson;
}

std::vector<std::string> get_awards(const GetGameResultIn& data) {
    /**
    Get list of awards ids for a submission.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("student.submissions.getAwards", ijson, {});
    return ojson;
}

std::vector<SubmissionAnalysis> get_analysis(const GetGameResultIn& data) {
    /**
    Get analysis of a submission.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("student.submissions.getAnalysis", ijson, {});
    return ojson;
}

TestcaseAnalysis get_testcase_analysis(const std::string& problem_id, const std::string& submission_id, const std::string& testcase) {
    /**
    Get a (public) testcase analysis of a submission.

    🔐 Authenticated        
    **/
    
    const json ijson = { {"problem_id", problem_id}, {"submission_id", submission_id}, {"testcase", testcase} };
    const auto [ojson, ofiles] = execute("student.submissions.getTestcaseAnalysis", ijson, {});
    return ojson;
}

GetGameResultOut get_game_result(const GetGameResultIn& data) {
    /**
    Get the result of a game submission.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("student.submissions.getGameResult", ijson, {});
    return ojson;
}

std::string get_game_output(const GetGameOutputIn& data) {
    /**
    Get the output of a game in a game submission.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("student.submissions.getGameOutput", ijson, {});
    return ojson;
}

}


namespace courses {


std::map<std::string, BriefCourse> index_available() {
    /**
    Get index of all available courses.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.courses.indexAvailable", ijson, {});
    return ojson;
}

std::map<std::string, BriefCourse> index_enrolled() {
    /**
    Get index of all enrolled courses.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.courses.indexEnrolled", ijson, {});
    return ojson;
}

Course get_available(const std::string& course_key) {
    /**
    Get an available course.

    🔐 Authenticated        

    Includes owner and lists.
    **/
    
    const json ijson = course_key;
    const auto [ojson, ofiles] = execute("student.courses.getAvailable", ijson, {});
    return ojson;
}

Course get_enrolled(const std::string& course_key) {
    /**
    Get an enrolled course.

    🔐 Authenticated        

    Includes owner and lists.
    **/
    
    const json ijson = course_key;
    const auto [ojson, ofiles] = execute("student.courses.getEnrolled", ijson, {});
    return ojson;
}

void enroll(const std::string& course_key) {
    /**
    Enroll in an available course.

    🔐 Authenticated        
    **/
    
    const json ijson = course_key;
    const auto [ojson, ofiles] = execute("student.courses.enroll", ijson, {});
    return ;
}

void unenroll(const std::string& course_key) {
    /**
    Unenroll from an enrolled course.

    🔐 Authenticated        
    **/
    
    const json ijson = course_key;
    const auto [ojson, ofiles] = execute("student.courses.unenroll", ijson, {});
    return ;
}

}


namespace lists {


std::map<std::string, BriefList> get_all() {
    /**
    Get all lists.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.lists.getAll", ijson, {});
    return ojson;
}

List get(const std::string& list_key) {
    /**
    Get a list.

    🔐 Authenticated        

    Includes items, owner.
    **/
    
    const json ijson = list_key;
    const auto [ojson, ofiles] = execute("student.lists.get", ijson, {});
    return ojson;
}

}


/**
    ‼️ The state of this module is UNDER CONSTRUCTION. It is not ready for production use. The output of some function is capped if the exam has not started yet.
*/
namespace exam {


std::vector<ReadyExam> get_ready_exams() {
    /**
    Get list of ready exams.

    🔐 Authenticated        

    An exam is ready if the current time is between its expected start time minus two days and its expected end time plus two days. Exams are sorted by their distance to the current time and by title order in case of ties.
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.exam.getReadyExams", ijson, {});
    return ojson;
}

RunningExam get() {
    /**
    Get current exam.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.exam.get", ijson, {});
    return ojson;
}

RunningExamDocument get_document(const std::string& document_nm) {
    /**
    Get a document in an exam.

    🔐 Authenticated        
    **/
    
    const json ijson = document_nm;
    const auto [ojson, ofiles] = execute("student.exam.getDocument", ijson, {});
    return ojson;
}

Download get_document_pdf(const std::string& document_nm) {
    /**
    Get PDF of a document in an exam.

    🔐 Authenticated        
    **/
    
    const json ijson = document_nm;
    const auto [ojson, ofiles] = execute("student.exam.getDocumentPdf", ijson, {});
    return ofiles[0];
}

Ranking get_ranking() {
    /**
    Get ranking of the current contest.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.exam.getRanking", ijson, {});
    return ojson;
}

}


namespace statuses {


std::map<std::string, AbstractStatus> get_all() {
    /**
    Get statuses for all abstract problems.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.statuses.getAll", ijson, {});
    return ojson;
}

AbstractStatus get_for_abstract_problem(const std::string& problem_nm) {
    /**
    Get status for an abstract problem.

    🔐 Authenticated        
    **/
    
    const json ijson = problem_nm;
    const auto [ojson, ofiles] = execute("student.statuses.getForAbstractProblem", ijson, {});
    return ojson;
}

Status get_for_problem(const std::string& problem_id) {
    /**
    Get status for a problem.

    🔐 Authenticated        
    **/
    
    const json ijson = problem_id;
    const auto [ojson, ofiles] = execute("student.statuses.getForProblem", ijson, {});
    return ojson;
}

}


/**
    This module is not yet finished.
*/
namespace awards {


std::map<std::string, BriefAward> get_all() {
    /**
    Get all awards.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("student.awards.getAll", ijson, {});
    return ojson;
}

Award get(const std::string& award_id) {
    /**
    Get an award.

    🔐 Authenticated        
    **/
    
    const json ijson = award_id;
    const auto [ojson, ofiles] = execute("student.awards.get", ijson, {});
    return ojson;
}

}

}


/**
    This module is meant to be used by instructors
*/
namespace instructor {



namespace documents {


std::map<std::string, Document> index() {
    /**
    Get index of all documents.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("instructor.documents.index", ijson, {});
    return ojson;
}

Document get(const std::string& document_nm) {
    /**
    Get a document.

    🔐 Authenticated        

    The PDF file is not included in the response.
    **/
    
    const json ijson = document_nm;
    const auto [ojson, ofiles] = execute("instructor.documents.get", ijson, {});
    return ojson;
}

Download get_pdf(const std::string& document_nm) {
    /**
    Get PDF of a document.

    🔐 Authenticated        
    **/
    
    const json ijson = document_nm;
    const auto [ojson, ofiles] = execute("instructor.documents.getPdf", ijson, {});
    return ofiles[0];
}

void create(const DocumentCreation& data, const Blob& ifile) {
    /**
    Create a new document.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("instructor.documents.create", ijson, {ifile});
    return ;
}

void update(const DocumentCreation& data, const Blob& ifile) {
    /**
    Update a document.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("instructor.documents.update", ijson, {ifile});
    return ;
}

void remove(const std::string& document_nm) {
    /**
    Remove a document.

    🔐 Authenticated        
    **/
    
    const json ijson = document_nm;
    const auto [ojson, ofiles] = execute("instructor.documents.remove", ijson, {});
    return ;
}

}


namespace lists {


std::map<std::string, InstructorBriefList> index() {
    /**
    Get index of all lists.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("instructor.lists.index", ijson, {});
    return ojson;
}

InstructorList get(const std::string& list_nm) {
    /**
    Get a list.

    🔐 Authenticated        
    **/
    
    const json ijson = list_nm;
    const auto [ojson, ofiles] = execute("instructor.lists.get", ijson, {});
    return ojson;
}

void create(const InstructorListCreation& data) {
    /**
    Create a new list.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("instructor.lists.create", ijson, {});
    return ;
}

void update(const InstructorListCreation& data) {
    /**
    Update an existing list.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("instructor.lists.update", ijson, {});
    return ;
}

void remove(const std::string& list_nm) {
    /**
    Delete an existing list.

    🔐 Authenticated        
    **/
    
    const json ijson = list_nm;
    const auto [ojson, ofiles] = execute("instructor.lists.remove", ijson, {});
    return ;
}

std::vector<std::string> get_archived() {
    /**
    Get the list of lists that are archived.

    🔐 Authenticated        

    At some point, endpoints related to archiving lists should change as the archive bit will be an attribute of each list.
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("instructor.lists.getArchived", ijson, {});
    return ojson;
}

void archive(const std::string& list_nm) {
    /**
    Archive a list.

    🔐 Authenticated        
    **/
    
    const json ijson = list_nm;
    const auto [ojson, ofiles] = execute("instructor.lists.archive", ijson, {});
    return ;
}

void unarchive(const std::string& list_nm) {
    /**
    Unarchive a list.

    🔐 Authenticated        
    **/
    
    const json ijson = list_nm;
    const auto [ojson, ofiles] = execute("instructor.lists.unarchive", ijson, {});
    return ;
}

}


/**
    
This module manages the courses that an instructor is teaching. It allows the instructor to manage the course, including getting and updating its lists, students and tutors. It can also send invites to pending students and tutors.

The course name is a unique slug for the course. It is used to reference the course in the system.

The course title is the human-readable title of the course.

The course description is a human-readable description of the course.

Students and tutors are managed in three lists: invited, enrolled and pending. These contains the emails of these users. Invited students and tutors are those who have been invited to the course. Enrolled students and tutors are those who have accepted the invitation and are part of the course. Pending students and tutors are those who have been invited to join the course but have not yet accepted. Enrolled and pending students and tutors are managed by the system and cannot not be modified directly.

*/
namespace courses {


std::map<std::string, InstructorBriefCourse> index() {
    /**
    Get index of all courses.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("instructor.courses.index", ijson, {});
    return ojson;
}

InstructorCourse get(const std::string& course_nm) {
    /**
    Get a course.

    🔐 Authenticated        
    **/
    
    const json ijson = course_nm;
    const auto [ojson, ofiles] = execute("instructor.courses.get", ijson, {});
    return ojson;
}

void create(const InstructorCourseCreation& data) {
    /**
    Create a new course.

    🔐 Authenticated        

    Only invited students and tutors are taken into account. Enrolled and pending students and tutors are ignored, as these are managed by the system.
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("instructor.courses.create", ijson, {});
    return ;
}

void update(const InstructorCourseUpdate& data) {
    /**
    Update an existing course.

    🔐 Authenticated        

    Only invited students and tutors are taken into account. Enrolled and pending students and tutors are ignored, as these are managed by the system.
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("instructor.courses.update", ijson, {});
    return ;
}

void remove(const std::string& course_nm) {
    /**
    Delete an existing course.

    🔐 Authenticated        

    A course should not be deleted. Ask a system administrator to remove it if you really need it.
    **/
    
    const json ijson = course_nm;
    const auto [ojson, ofiles] = execute("instructor.courses.remove", ijson, {});
    return ;
}

void send_invite_to_students(const std::string& course_nm) {
    /**
    Send invite email to pending students in the course.

    🔐 Authenticated        

    Please do not abuse.
    **/
    
    const json ijson = course_nm;
    const auto [ojson, ofiles] = execute("instructor.courses.sendInviteToStudents", ijson, {});
    return ;
}

void send_invite_to_tutors(const std::string& course_nm) {
    /**
    Send invite email to pending tutors in the course.

    🔐 Authenticated        

    Please do not abuse.
    **/
    
    const json ijson = course_nm;
    const auto [ojson, ofiles] = execute("instructor.courses.sendInviteToTutors", ijson, {});
    return ;
}

std::map<std::string, StudentProfile> get_student_profiles(const std::string& course_nm) {
    /**
    Get the profiles of the students enrolled in the course.

    🔐 Authenticated        
    **/
    
    const json ijson = course_nm;
    const auto [ojson, ofiles] = execute("instructor.courses.getStudentProfiles", ijson, {});
    return ojson;
}

std::map<std::string, StudentProfile> get_tutor_profiles(const std::string& course_nm) {
    /**
    Get the profiles of the tutors enrolled in the course.

    🔐 Authenticated        
    **/
    
    const json ijson = course_nm;
    const auto [ojson, ofiles] = execute("instructor.courses.getTutorProfiles", ijson, {});
    return ojson;
}

std::vector<std::string> get_archived() {
    /**
    Get the list of courses that are archived.

    🔐 Authenticated        

    At some point, endpoints related to archiving courses should change as the archive bit will be an attribute of each course.
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("instructor.courses.getArchived", ijson, {});
    return ojson;
}

void archive(const std::string& course_nm) {
    /**
    Archive a course.

    🔐 Authenticated        
    **/
    
    const json ijson = course_nm;
    const auto [ojson, ofiles] = execute("instructor.courses.archive", ijson, {});
    return ;
}

void unarchive(const std::string& course_nm) {
    /**
    Unarchive a course.

    🔐 Authenticated        
    **/
    
    const json ijson = course_nm;
    const auto [ojson, ofiles] = execute("instructor.courses.unarchive", ijson, {});
    return ;
}

}


/**
    

This module manages the exams that an instructor is teaching. It allows the instructor to manage the exam, including getting and updating its documents, problems, students and submissions.

Exams objects are quite complex. Thus, this interface is also a bit complex. Each part of an exam can be get or updated in a separate endpoint. The main endpoint is the get endpoint, which returns the full exam object.


*/
namespace exams {


std::map<std::string, InstructorBriefExam> index() {
    /**
    Get index of all exams.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("instructor.exams.index", ijson, {});
    return ojson;
}

InstructorExam get(const std::string& exam_nm) {
    /**
    Get an exam.

    🔐 Authenticated        
    **/
    
    const json ijson = exam_nm;
    const auto [ojson, ofiles] = execute("instructor.exams.get", ijson, {});
    return ojson;
}

std::vector<RunningExamDocument> get_documents(const std::string& exam_nm) {
    /**
    Get documents of an exam.

    🔐 Authenticated        
    **/
    
    const json ijson = exam_nm;
    const auto [ojson, ofiles] = execute("instructor.exams.getDocuments", ijson, {});
    return ojson;
}

std::vector<InstructorExamProblem> get_problems(const std::string& exam_nm) {
    /**
    Get problems of an exam.

    🔐 Authenticated        
    **/
    
    const json ijson = exam_nm;
    const auto [ojson, ofiles] = execute("instructor.exams.getProblems", ijson, {});
    return ojson;
}

std::vector<InstructorExamStudent> get_students(const std::string& exam_nm) {
    /**
    Get students of an exam.

    🔐 Authenticated        
    **/
    
    const json ijson = exam_nm;
    const auto [ojson, ofiles] = execute("instructor.exams.getStudents", ijson, {});
    return ojson;
}

InstructorExamStudent get_student(const std::string& exam_nm, const std::string& email) {
    /**
    Get an student of an exam.

    🔐 Authenticated        
    **/
    
    const json ijson = { {"exam_nm", exam_nm}, {"email", email} };
    const auto [ojson, ofiles] = execute("instructor.exams.getStudent", ijson, {});
    return ojson;
}

WebStream get_submissions(const std::string& exam_nm, const InstructorExamSubmissionsOptions& options) {
    /**
    Get submissions of an exam as a webstream.

    🔐 Authenticated        

    Meant for real-time streaming of submissions, most instructors will possibly prefer getSubmissionsPack.
    **/
    
    const json ijson = { {"exam_nm", exam_nm}, {"options", options} };
    const auto [ojson, ofiles] = execute("instructor.exams.getSubmissions", ijson, {});
    return ojson;
}

Pack get_submissions_pack(const std::string& exam_nm, const InstructorExamSubmissionsOptions& options) {
    /**
    Get submissions of an exam as a pack.

    🔐 Authenticated        

    This endpoint will prepare the pack in the background and return a link to download it later. Packs take some time to be prepared, and are deleted after 24 hours. This is the preferred endpoint for most instructors, as it is simpler to use than getSubmissions. 
    **/
    
    const json ijson = { {"exam_nm", exam_nm}, {"options", options} };
    const auto [ojson, ofiles] = execute("instructor.exams.getSubmissionsPack", ijson, {});
    return ojson;
}

ExamStatistics get_statistics(const std::string& exam_nm) {
    /**
    Get statistics of an exam.

    🔐 Authenticated        
    **/
    
    const json ijson = exam_nm;
    const auto [ojson, ofiles] = execute("instructor.exams.getStatistics", ijson, {});
    return ojson;
}

void create(const InstructorExamCreation& data) {
    /**
    Create a new exam.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("instructor.exams.create", ijson, {});
    return ;
}

void update(const InstructorExamUpdate& data) {
    /**
    Update an existing exam.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("instructor.exams.update", ijson, {});
    return ;
}

void update_documents(const std::string& exam_nm, const std::vector<std::string>& document_nms) {
    /**
    Update documents of an exam.

    🔐 Authenticated        
    **/
    
    const json ijson = { {"exam_nm", exam_nm}, {"document_nms", document_nms} };
    const auto [ojson, ofiles] = execute("instructor.exams.updateDocuments", ijson, {});
    return ;
}

void update_compilers(const std::string& exam_nm, const std::vector<std::string>& compiler_ids) {
    /**
    Update compilers of an exam.

    🔐 Authenticated        
    **/
    
    const json ijson = { {"exam_nm", exam_nm}, {"compiler_ids", compiler_ids} };
    const auto [ojson, ofiles] = execute("instructor.exams.updateCompilers", ijson, {});
    return ;
}

void update_problems(const std::string& exam_nm, const std::vector<InstructorExamProblem>& problems) {
    /**
    Update problems of an exam.

    🔐 Authenticated        
    **/
    
    const json ijson = { {"exam_nm", exam_nm}, {"problems", problems} };
    const auto [ojson, ofiles] = execute("instructor.exams.updateProblems", ijson, {});
    return ;
}

void update_students(const std::string& exam_nm, const std::vector<InstructorExamStudent>& students) {
    /**
    Update students of an exam.

    🔐 Authenticated        
    **/
    
    const json ijson = { {"exam_nm", exam_nm}, {"students", students} };
    const auto [ojson, ofiles] = execute("instructor.exams.updateStudents", ijson, {});
    return ;
}

void add_students(const std::string& exam_nm, const std::vector<InstructorExamStudent>& students) {
    /**
    Add students to an exam.

    🔐 Authenticated        
    **/
    
    const json ijson = { {"exam_nm", exam_nm}, {"students", students} };
    const auto [ojson, ofiles] = execute("instructor.exams.addStudents", ijson, {});
    return ;
}

void remove_students(const std::string& exam_nm, const std::vector<std::string>& emails) {
    /**
    Remove students from an exam.

    🔐 Authenticated        
    **/
    
    const json ijson = { {"exam_nm", exam_nm}, {"emails", emails} };
    const auto [ojson, ofiles] = execute("instructor.exams.removeStudents", ijson, {});
    return ;
}

void remove(const std::string& exam_nm) {
    /**
    Delete an existing exam.

    🔐 Authenticated        

    Note: An exam can only be deleted if it has not started.
    **/
    
    const json ijson = exam_nm;
    const auto [ojson, ofiles] = execute("instructor.exams.remove", ijson, {});
    return ;
}

std::vector<std::string> get_archived() {
    /**
    Get the list of exams that are archived.

    🔐 Authenticated        

    At some point, endpoints related to archiving exams should change as the archive bit will be an attribute of each exam.
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("instructor.exams.getArchived", ijson, {});
    return ojson;
}

void archive(const std::string& exam_nm) {
    /**
    Archive an exam.

    🔐 Authenticated        
    **/
    
    const json ijson = exam_nm;
    const auto [ojson, ofiles] = execute("instructor.exams.archive", ijson, {});
    return ;
}

void unarchive(const std::string& exam_nm) {
    /**
    Unarchive an exam.

    🔐 Authenticated        
    **/
    
    const json ijson = exam_nm;
    const auto [ojson, ofiles] = execute("instructor.exams.unarchive", ijson, {});
    return ;
}

Ranking get_ranking(const std::string& exam_nm) {
    /**
    Get the ranking.

    🔐 Authenticated        

    Under development.
    **/
    
    const json ijson = exam_nm;
    const auto [ojson, ofiles] = execute("instructor.exams.getRanking", ijson, {});
    return ojson;
}

}


namespace problems {


std::vector<std::string> get_own_problems() {
    /**
    Get the list of own problems.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("instructor.problems.getOwnProblems", ijson, {});
    return ojson;
}

void set_sharing_settings(const SharingSettings& data) {
    /**
    Set the sharing settings of a problem.

    🔐 Authenticated        

    
        Without a passcode, the problem is visible to all users.
        With a passcode, the problem is only visible to users with the correct passcode.
        With shared testcases, the testcases are shared with instructors. 
        With shared solutions, the solutions are shared with instructors. 
        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("instructor.problems.setSharingSettings", ijson, {});
    return ;
}

SharingSettings get_sharing_settings(const std::string& problem_nm) {
    /**
    Get the sharing settings of a problem.

    🔐 Authenticated        
    **/
    
    const json ijson = problem_nm;
    const auto [ojson, ofiles] = execute("instructor.problems.getSharingSettings", ijson, {});
    return ojson;
}

std::vector<SharingSettings> get_all_sharing_settings() {
    /**
    Get the sharing settings of all problems.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("instructor.problems.getAllSharingSettings", ijson, {});
    return ojson;
}

void share_with(const ShareWithInp& data) {
    /**
    Share a problem with users.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("instructor.problems.shareWith", ijson, {});
    return ;
}

void set_deprecation(const Deprecation& data) {
    /**
    Set the deprecation of a problem.

    🔐 Authenticated        

    If the reason is null or empty, the problem is undeprecated.
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("instructor.problems.setDeprecation", ijson, {});
    return ;
}

std::vector<ProblemPopularityBucketEntry> get_problem_popularity_buckets() {
    /**
    Get the popularity buckets for all problems.

    🔐 Authenticated        

    The buckets are sorted by the number of problems in each bucket by total number of submissions. The data is refreshed every hour.
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("instructor.problems.getProblemPopularityBuckets", ijson, {});
    return ojson;
}

std::vector<ProblemAnonymousSubmission> get_anonymous_submissions(const std::string& problem_nm) {
    /**
    Get anonymous submissions for an abstract problem.

    🔐 Authenticated        

    This function is useful to produce statistics about the submissions for an abstract problem. The user ids are anonymized using a nonce.
    **/
    
    const json ijson = problem_nm;
    const auto [ojson, ofiles] = execute("instructor.problems.getAnonymousSubmissions", ijson, {});
    return ojson;
}

Download download(const std::string& problem_nm) {
    /**
    Download a problem as a ZIP file.

    🔐 Authenticated        
    **/
    
    const json ijson = problem_nm;
    const auto [ojson, ofiles] = execute("instructor.problems.download", ijson, {});
    return ofiles[0];
}

WebStream create(const std::string& passcode, const Blob& ifile) {
    /**
    Create a problem from a ZIP archive.

    🔐 Authenticated        

    This endpoint uses terminal web streaming: It returns an id from which the problem feedback is streamed over <URL>/api/webstreams/<id>.
    **/
    
    const json ijson = passcode;
    const auto [ojson, ofiles] = execute("instructor.problems.create", ijson, {ifile});
    return ojson;
}

WebStream update(const std::string& problem_nm, const Blob& ifile) {
    /**
    Update a problem from a ZIP archive.

    🔐 Authenticated        

    This endpoint uses terminal web streaming: It returns an id from which the problem feedback is streamed over <URL>/api/webstreams/<id>.
    **/
    
    const json ijson = problem_nm;
    const auto [ojson, ofiles] = execute("instructor.problems.update", ijson, {ifile});
    return ojson;
}

void remove(const std::string& problem_nm) {
    /**
    Remove a problem.

    🔐 Authenticated        

    A problem can only be removed if it has few submissions.
    **/
    
    const json ijson = problem_nm;
    const auto [ojson, ofiles] = execute("instructor.problems.remove", ijson, {});
    return ;
}

}


namespace queries {


SubmissionsQuery get_course_problem_submissions(const std::string& course_nm, const std::string& problem_nm) {
    /**
    Get submissions for a problem in a course.

    🔐 Authenticated        

    Returns a list of submissions for a given problem for all students of a given course. Each submission includes the email, time, problem name, problem id, verdict, and IP address. The list is ordered by email and time. Known as ricard01 in the past.
    **/
    
    const json ijson = { {"course_nm", course_nm}, {"problem_nm", problem_nm} };
    const auto [ojson, ofiles] = execute("instructor.queries.getCourseProblemSubmissions", ijson, {});
    return ojson;
}

SubmissionsQuery get_course_list_submissions(const std::string& course_nm, const std::string& list_nm) {
    /**
    Get submissions for all problems in a list in a course.

    🔐 Authenticated        

    Returns a list of submissions for all problems in a given list for all students of a given course. Each submission includes the email, time, problem name, problem id, verdict, and IP address. The list is ordered by email, problem id and time. Known as ricard02 in the past.
    **/
    
    const json ijson = { {"course_nm", course_nm}, {"list_nm", list_nm} };
    const auto [ojson, ofiles] = execute("instructor.queries.getCourseListSubmissions", ijson, {});
    return ojson;
}

}


namespace tags {


std::vector<std::string> index() {
    /**
    Get list of all tags.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("instructor.tags.index", ijson, {});
    return ojson;
}

TagsDict get_dict() {
    /**
    Get all tags with their problems.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("instructor.tags.getDict", ijson, {});
    return ojson;
}

std::vector<std::string> get(const std::string& tag) {
    /**
    Get all problems with a given tag.

    🔐 Authenticated        
    **/
    
    const json ijson = tag;
    const auto [ojson, ofiles] = execute("instructor.tags.get", ijson, {});
    return ojson;
}

}


namespace jutgeai {


std::vector<std::string> supported_models() {
    /**
    Get the list of supported models.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("instructor.jutgeai.supportedModels", ijson, {});
    return ojson;
}

std::vector<std::string> supported_image_models() {
    /**
    Get the list of supported image models.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("instructor.jutgeai.supportedImageModels", ijson, {});
    return ojson;
}

WebStream chat(const ChatPrompt& data) {
    /**
    Chat with an AI model using a list of messages.

    🔐 Authenticated        

    Send a conversation (list of system|user|assistant messages) and get the next assistant reply. Models are listed in the `supportedModels` endpoint. This endpoint uses terminal web streaming: It returns an id from which the chat is streamed over <URL>/api/webstreams/<id>. If `addUsage` is true, the usage of the model will be added at the end of the response as a JSON object between `---USAGE_JSON_START---` and `---USAGE_JSON_END---`.
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("instructor.jutgeai.chat", ijson, {});
    return ojson;
}

Download create_image(const CreateImageInput& data) {
    /**
    Create an image using an AI image model.

    🔐 Authenticated        

    Some models only accept certain sizes and aspect ratios.
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("instructor.jutgeai.createImage", ijson, {});
    return ofiles[0];
}

std::vector<LlmUsageEntry> get_llm_usage() {
    /**
    Get audit usage of LLM models.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("instructor.jutgeai.getLlmUsage", ijson, {});
    return ojson;
}

}

}


/**
    Module to allow playing Jutge.org games. All operations require the `competitions` user. This module is still under development and is not yet ready for production.
*/
namespace games {


std::vector<std::string> get_games() {
    /**
    Get list of problems that are games.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("games.getGames", ijson, {});
    return ojson;
}

std::string get_dummy(const std::string& problem_id) {
    /**
    Get dummy player for a game.

    🔐 Authenticated        
    **/
    
    const json ijson = problem_id;
    const auto [ojson, ofiles] = execute("games.getDummy", ijson, {});
    return ojson;
}

Download get_viewer(const std::string& problem_id) {
    /**
    Get a ZIP file with the viewer for a game.

    🔐 Authenticated        
    **/
    
    const json ijson = problem_id;
    const auto [ojson, ofiles] = execute("games.getViewer", ijson, {});
    return ofiles[0];
}

NewSubmissionOut submit_match(const SubmitMatchInput& data) {
    /**
    Submit a match for a game.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("games.submitMatch", ijson, {});
    return ojson;
}

}


/**
    Module with administration endpoints. Not meant for regular users. It still lacks lots of endpoints
*/
namespace admin {



namespace instructors {


InstructorEntries get() {
    /**
    Get instructors.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.instructors.get", ijson, {});
    return ojson;
}

void add(const std::string& email, const std::string& username) {
    /**
    Add an instructor.

    🔐 Authenticated        
    **/
    
    const json ijson = { {"email", email}, {"username", username} };
    const auto [ojson, ofiles] = execute("admin.instructors.add", ijson, {});
    return ;
}

void remove(const std::string& email) {
    /**
    Remove an instructor.

    🔐 Authenticated        
    **/
    
    const json ijson = email;
    const auto [ojson, ofiles] = execute("admin.instructors.remove", ijson, {});
    return ;
}

}


namespace users {


int count() {
    /**
    Count users

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.users.count", ijson, {});
    return ojson;
}

void create(const UserCreation& data) {
    /**
    Create a user

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("admin.users.create", ijson, {});
    return ;
}

void remove(const std::string& email) {
    /**
    Remove a user

    🔐 Authenticated        
    **/
    
    const json ijson = email;
    const auto [ojson, ofiles] = execute("admin.users.remove", ijson, {});
    return ;
}

void set_password(const std::string& email, const std::string& password, const std::string& message) {
    /**
    Set a password for a user

    🔐 Authenticated        
    **/
    
    const json ijson = { {"email", email}, {"password", password}, {"message", message} };
    const auto [ojson, ofiles] = execute("admin.users.setPassword", ijson, {});
    return ;
}

std::vector<ProfileForAdmin> get_profiles(const std::string& data) {
    /**
    Get all profiles of users whose email or name contains a specific string

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("admin.users.getProfiles", ijson, {});
    return ojson;
}

UsersEmailsAndNames get_all_with_email(const std::string& data) {
    /**
    Get all users (well, just email and name) whose email contains a specific string

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("admin.users.getAllWithEmail", ijson, {});
    return ojson;
}

std::vector<std::string> get_spam_users() {
    /**
    Get a list of emails of spam users

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.users.getSpamUsers", ijson, {});
    return ojson;
}

void remove_spam_users(const std::vector<std::string>& data) {
    /**
    Remove spam users

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("admin.users.removeSpamUsers", ijson, {});
    return ;
}

}


namespace dashboard {


AdminDashboard get_all() {
    /**
    Get all admin dashboard items.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.dashboard.getAll", ijson, {});
    return ojson;
}

DatabasesInfo get_databases_info() {
    /**
    Get database info.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.dashboard.getDatabasesInfo", ijson, {});
    return ojson;
}

FreeDiskSpace get_free_disk_space() {
    /**
    Get free disk space.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.dashboard.getFreeDiskSpace", ijson, {});
    return ojson;
}

RecentConnectedUsers get_recent_connected_users() {
    /**
    Get recent connected users.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.dashboard.getRecentConnectedUsers", ijson, {});
    return ojson;
}

RecentLoadAverages get_recent_load_averages() {
    /**
    Get recent load averages.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.dashboard.getRecentLoadAverages", ijson, {});
    return ojson;
}

RecentSubmissions get_recent_submissions() {
    /**
    Get recent submissions.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.dashboard.getRecentSubmissions", ijson, {});
    return ojson;
}

SubmissionsHistograms get_submissions_histograms() {
    /**
    Get submissions histograms.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.dashboard.getSubmissionsHistograms", ijson, {});
    return ojson;
}

Zombies get_zombies() {
    /**
    Get zombies.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.dashboard.getZombies", ijson, {});
    return ojson;
}

UpcomingExams get_upcoming_exams(const int& daysBefore, const int& daysAfter) {
    /**
    Get upcoming exams

    🔐 Authenticated        
    **/
    
    const json ijson = { {"daysBefore", daysBefore}, {"daysAfter", daysAfter} };
    const auto [ojson, ofiles] = execute("admin.dashboard.getUpcomingExams", ijson, {});
    return ojson;
}

json get_p_m2_status() {
    /**
    Get pm2 status

    🔐 Authenticated        

    This endpoint retrieves the status of PM2 processes as reported by `pm2 jlist`.
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.dashboard.getPM2Status", ijson, {});
    return ojson;
}

json get_docker_status() {
    /**
    Get docker status

    🔐 Authenticated        

    This endpoint retrieves the status of docker processes as reported by `docker ps --all`.
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.dashboard.getDockerStatus", ijson, {});
    return ojson;
}

}


namespace queue {


SubmissionQueueItems get_queue(const QueueQuery& data) {
    /**
    Get the lattest submissions from the queue in descending chronological order for a certain verdict.

    🔐 Authenticated        

    The `limit` parameter tells the number of submissions to retrieve. The `verdicts` parameter is an array of verdicts to filter the submissions. If no verdicts are provided, all submissions will be retrieved.
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("admin.queue.getQueue", ijson, {});
    return ojson;
}

}


namespace tasks {


void purge_auth_tokens() {
    /**
    Purge expired access tokens.

    🔐 Authenticated        

    Purge expired access tokens (call it from time to time, it does not hurt)
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.tasks.purgeAuthTokens", ijson, {});
    return ;
}

void clear_caches() {
    /**
    Clear all memoization caches.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.tasks.clearCaches", ijson, {});
    return ;
}

void fatalize_i_es() {
    /**
    Fatalize IE submissions.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.tasks.fatalizeIEs", ijson, {});
    return ;
}

void fatalize_pendings() {
    /**
    Fatalize pending submissions.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.tasks.fatalizePendings", ijson, {});
    return ;
}

void resubmit_i_es() {
    /**
    Resubmit IE submissions.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.tasks.resubmitIEs", ijson, {});
    return ;
}

void resubmit_pendings() {
    /**
    Resubmit pending submissions.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.tasks.resubmitPendings", ijson, {});
    return ;
}

Download get_full_text_search_database() {
    /**
    Get full text search database status.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.tasks.getFullTextSearchDatabase", ijson, {});
    return ofiles[0];
}

void update_semantic_search_database(const std::string& data, const Blob& ifile) {
    /**
    Update semantic search database.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("admin.tasks.updateSemanticSearchDatabase", ijson, {ifile});
    return ;
}

}


namespace stats {


std::map<std::string, float> get_counters() {
    /**
    Get counters.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.stats.getCounters", ijson, {});
    return ojson;
}

std::map<std::string, float> get_distribution_of_verdicts() {
    /**
    Get distribution of verdicts.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.stats.getDistributionOfVerdicts", ijson, {});
    return ojson;
}

std::vector<std::map<std::string, float>> get_distribution_of_verdicts_by_year() {
    /**
    Get distribution of verdicts by year.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.stats.getDistributionOfVerdictsByYear", ijson, {});
    return ojson;
}

std::map<std::string, float> get_distribution_of_compilers() {
    /**
    Get distribution of compilers.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.stats.getDistributionOfCompilers", ijson, {});
    return ojson;
}

std::map<std::string, float> get_distribution_of_proglangs() {
    /**
    Get distribution of proglangs.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.stats.getDistributionOfProglangs", ijson, {});
    return ojson;
}

std::map<std::string, float> get_distribution_of_users_by_year() {
    /**
    Get distribution of registered users by year.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.stats.getDistributionOfUsersByYear", ijson, {});
    return ojson;
}

std::map<std::string, float> get_distribution_of_users_by_country() {
    /**
    Get distribution of registered users by country.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.stats.getDistributionOfUsersByCountry", ijson, {});
    return ojson;
}

std::map<std::string, float> get_distribution_of_users_by_submissions(const int& data) {
    /**
    Get distribution of registered users by submissions using a custom bucket size.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("admin.stats.getDistributionOfUsersBySubmissions", ijson, {});
    return ojson;
}

UserRanking get_ranking_of_users(const int& limit) {
    /**
    Get ranking of users.

    🔐 Authenticated    
    ❌ Warning: Input type is not correct    
    **/
    
    const json ijson = limit;
    const auto [ojson, ofiles] = execute("admin.stats.getRankingOfUsers", ijson, {});
    return ojson;
}

std::map<std::string, float> get_distribution_of_submissions_by_hour() {
    /**
    Get distribution of submissions by hour.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.stats.getDistributionOfSubmissionsByHour", ijson, {});
    return ojson;
}

std::map<std::string, float> get_distribution_of_submissions_by_proglang() {
    /**
    Get distribution of submissions by proglang.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.stats.getDistributionOfSubmissionsByProglang", ijson, {});
    return ojson;
}

std::map<std::string, float> get_distribution_of_submissions_by_compiler() {
    /**
    Get distribution of submissions by compiler.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.stats.getDistributionOfSubmissionsByCompiler", ijson, {});
    return ojson;
}

std::map<std::string, float> get_distribution_of_submissions_by_weekday() {
    /**
    Get distribution of submissions by weekday.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.stats.getDistributionOfSubmissionsByWeekday", ijson, {});
    return ojson;
}

std::map<std::string, float> get_distribution_of_submissions_by_year() {
    /**
    Get distribution of submissions by year.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.stats.getDistributionOfSubmissionsByYear", ijson, {});
    return ojson;
}

std::map<std::string, float> get_distribution_of_submissions_by_year_for_proglang(const std::string& proglang) {
    /**
    Get distribution of submissions by year for a proglang.

    🔐 Authenticated        
    **/
    
    const json ijson = proglang;
    const auto [ojson, ofiles] = execute("admin.stats.getDistributionOfSubmissionsByYearForProglang", ijson, {});
    return ojson;
}

std::map<std::string, float> get_distribution_of_submissions_by_day() {
    /**
    Get distribution of submissions by day.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.stats.getDistributionOfSubmissionsByDay", ijson, {});
    return ojson;
}

json get_heatmap_calendar_of_submissions(const DateRange& data) {
    /**
    Get heatmap calendar of submissions.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("admin.stats.getHeatmapCalendarOfSubmissions", ijson, {});
    return ojson;
}

std::map<std::string, float> get_distribution_of_domains() {
    /**
    Get distribution of domains of users' emails.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.stats.getDistributionOfDomains", ijson, {});
    return ojson;
}

}


namespace problems {


std::vector<std::string> get_solutions(const std::string& problem_id) {
    /**
    Get list of proglangs for which the problem has an official solution.

    🔐 Authenticated        
    **/
    
    const json ijson = problem_id;
    const auto [ojson, ofiles] = execute("admin.problems.getSolutions", ijson, {});
    return ojson;
}

std::string get_solution_as_b64(const std::string& problem_id, const std::string& proglang) {
    /**
    Get official solution for a problem in proglang as a string in base64.

    🔐 Authenticated        
    **/
    
    const json ijson = { {"problem_id", problem_id}, {"proglang", proglang} };
    const auto [ojson, ofiles] = execute("admin.problems.getSolutionAsB64", ijson, {});
    return ojson;
}

Download get_solution_as_file(const std::string& problem_id, const std::string& proglang) {
    /**
    Get official solution for a problem in proglang as a file.

    🔐 Authenticated        
    **/
    
    const json ijson = { {"problem_id", problem_id}, {"proglang", proglang} };
    const auto [ojson, ofiles] = execute("admin.problems.getSolutionAsFile", ijson, {});
    return ofiles[0];
}

std::optional<ProblemSummary> get_problem_summary(const std::string& problem_id) {
    /**
    Get summary for a problem.

    🔐 Authenticated        
    **/
    
    const json ijson = problem_id;
    const auto [ojson, ofiles] = execute("admin.problems.getProblemSummary", ijson, {});
    return ojson;
}

std::vector<std::string> get_problems_with_summary() {
    /**
    Get list of problems with summary.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.problems.getProblemsWithSummary", ijson, {});
    return ojson;
}

std::vector<std::string> get_problems_without_summary() {
    /**
    Get list of problems without summary.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.problems.getProblemsWithoutSummary", ijson, {});
    return ojson;
}

std::optional<SolutionTags> get_abstract_problem_solution_tags(const std::string& problem_nm) {
    /**
    Get solution tags for an abstract problem.

    🔐 Authenticated        
    **/
    
    const json ijson = { {"problem_nm", problem_nm} };
    const auto [ojson, ofiles] = execute("admin.problems.getAbstractProblemSolutionTags", ijson, {});
    return ojson;
}

std::vector<std::string> get_abstract_problems_with_solution_tags() {
    /**
    Get list of abstract problems with solution tags.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.problems.getAbstractProblemsWithSolutionTags", ijson, {});
    return ojson;
}

std::vector<std::string> get_abstract_problems_without_solution_tags() {
    /**
    Get list of abstract problems without solution tags.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("admin.problems.getAbstractProblemsWithoutSolutionTags", ijson, {});
    return ojson;
}

}

}


/**
    Module with testing endpoints. Not meant for regular users.
*/
namespace testing {



/**
    This module is intended for internal use and contains functions to check the actor of the query. General public should not rely on it.
*/
namespace check {


void check_user() {
    /**
    Checks that query actor is a user.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("testing.check.checkUser", ijson, {});
    return ;
}

void check_instructor() {
    /**
    Checks that query actor is an instructor.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("testing.check.checkInstructor", ijson, {});
    return ;
}

void check_admin() {
    /**
    Checks that query actor is an admin.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("testing.check.checkAdmin", ijson, {});
    return ;
}

void throw_error(const std::string& exception) {
    /**
    Throw an exception of the given type.

    🔐 Authenticated        
    **/
    
    const json ijson = exception;
    const auto [ojson, ofiles] = execute("testing.check.throwError", ijson, {});
    return ;
}

}


/**
    This module is intended for internal use. General users should not rely on it.
*/
namespace playground {


std::string upload(const Name& data, const Blob& ifile) {
    /**
    Upload a file.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("testing.playground.upload", ijson, {ifile});
    return ojson;
}

Download negate(const Blob& ifile) {
    /**
    Get negative of an image.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("testing.playground.negate", ijson, {ifile});
    return ofiles[0];
}

Download download(const Name& data) {
    /**
    Download a file.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("testing.playground.download", ijson, {});
    return ofiles[0];
}

std::tuple<std::string, Download> download2(const Name& data) {
    /**
    Download a file with a string.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("testing.playground.download2", ijson, {});
    return {ojson, ofiles[0]};
}

std::string ping() {
    /**
    Ping the server to get a pong string.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("testing.playground.ping", ijson, {});
    return ojson;
}

std::string to_upper_case(const std::string& s) {
    /**
    Returns the given string in uppercase.

    🔐 Authenticated        
    **/
    
    const json ijson = s;
    const auto [ojson, ofiles] = execute("testing.playground.toUpperCase", ijson, {});
    return ojson;
}

int add2i(const TwoInts& data) {
    /**
    Returns the sum of two integers.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("testing.playground.add2i", ijson, {});
    return ojson;
}

float add2f(const TwoFloats& data) {
    /**
    Returns the sum of two floats.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("testing.playground.add2f", ijson, {});
    return ojson;
}

TwoInts inc(const TwoInts& data) {
    /**
    increment two numbers.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("testing.playground.inc", ijson, {});
    return ojson;
}

int add3i(const int& a, const int& b, const int& c) {
    /**
    Returns the sum of three integers.

    🔐 Authenticated        
    **/
    
    const json ijson = { {"a", a}, {"b", b}, {"c", c} };
    const auto [ojson, ofiles] = execute("testing.playground.add3i", ijson, {});
    return ojson;
}

SomeType something(const SomeType& data) {
    /**
    Returns a type with defaults.

    🔐 Authenticated        
    **/
    
    const json ijson = data;
    const auto [ojson, ofiles] = execute("testing.playground.something", ijson, {});
    return ojson;
}

WebStream clock() {
    /**
    Get a webstream with clok data.

    🔐 Authenticated        
    **/
    
    const json ijson = {};
    const auto [ojson, ofiles] = execute("testing.playground.clock", ijson, {});
    return ojson;
}

}

}

// utilities


void login(string email, string password)
{
    const CredentialsIn credentials_in = { email, password };
    try {
        const CredentialsOut credentials_out = auth::login(credentials_in);
        meta = Meta { credentials_out.token };
    } catch (const exception& e) {
        cout << "login failed" << endl;
        exit(1);
    }
}

void logout()
{
    auth::logout();
    meta = nullopt;
}


} // end namespace jutge_api_client

#endif

