<commit_before>use super::make_request;
use super::{import_contest_mutation::*, ImportContestMutation};
use failure::Error;
use graphql_client::GraphQLQuery;
use juniper::http::GraphQLRequest;
use serde::{Deserialize, Serialize};
use std::convert::TryInto;
use std::fs;
use std::path::{Path, PathBuf};
use turingarena_core::archive::pack_archive;

#[derive(Debug, Serialize, Deserialize)]
struct ContestFile {
    /// Title of the contest
    title: String,

    /// Start time of the contest
    start: Option<String>,

    /// End time of the contest
    end: Option<String>,

    /// Users of the contest
    users: Vec<ContestUser>,

    /// Problems of the contest
    problems: Vec<String>,
}

#[derive(Debug, Serialize, Deserialize)]
struct ContestUser {
    /// Id of the user
    id: String,

    /// Name of the user
    name: String,

    /// Access token of the user
    token: String,

    /// Role of the user. Currently supported: user, admin
    role: Option<String>,
}

pub struct Importer {
    contest: ContestFile,
    path: PathBuf,
}

impl Importer {
    pub fn new<P: Into<PathBuf>>(path: P) -> Result<Self, Error> {
        let path = path.into();
        let metadata_path = path.join("turingarena.yaml");
        let metadata_data = fs::read(metadata_path)?;
        let contest = serde_yaml::from_slice::<ContestFile>(&metadata_data)?;

        Ok(Importer { contest, path })
    }

    fn contest(&self) -> ContestInput {
        let files = self.path.join("files");
        ContestInput {
            start_time: self.contest.start.as_ref().unwrap().clone(), // TODO: handle not specified date
            end_time: self.contest.end.as_ref().unwrap().clone(),
            archive_content: FileContentInput {
                base64: base64::encode(&pack_archive(files)),
            },
        }
    }

    fn problems(&self) -> Vec<ProblemInput> {
        let mut problems = Vec::new();

        for problem in &self.contest.problems {
            let path = self.path.join(problem);
            problems.push(ProblemInput {
                name: problem.clone(),
                archive_content: FileContentInput {
                    base64: base64::encode(&pack_archive(path)),
                },
            });
        }

        problems
    }

    fn users(&self) -> Vec<UserInput> {
        let mut users = Vec::new();

        for user in &self.contest.users {
            users.push(UserInput {
                id: user.id.clone(),
                token: user.token.clone(),
                display_name: user.name.clone(),
            });
        }

        users
    }
}

impl TryInto<GraphQLRequest> for Importer {
    type Error = Error;

    fn try_into(self) -> Result<GraphQLRequest, Self::Error> {
        let variables = Variables {
            contest: self.contest(),
            problems: self.problems(),
            users: self.users(),<commit_msg>Fix compilation error<commit_after>use super::make_request;
use super::{import_contest_mutation::*, ImportContestMutation};
use failure::Error;
use graphql_client::GraphQLQuery;
use juniper::http::GraphQLRequest;
use serde::{Deserialize, Serialize};
use std::convert::TryInto;
use std::fs;
use std::path::{Path, PathBuf};
use turingarena_core::archive::pack_archive;

#[derive(Debug, Serialize, Deserialize)]
struct ContestFile {
    /// Title of the contest
    title: String,

    /// Start time of the contest
    start: Option<String>,

    /// End time of the contest
    end: Option<String>,

    /// Users of the contest
    users: Vec<ContestUser>,

    /// Problems of the contest
    problems: Vec<String>,
}

#[derive(Debug, Serialize, Deserialize)]
struct ContestUser {
    /// Id of the user
    id: String,

    /// Name of the user
    name: String,

    /// Access token of the user
    token: String,

    /// Role of the user. Currently supported: user, admin
    role: Option<String>,
}

pub struct Importer {
    contest: ContestFile,
    path: PathBuf,
}

impl Importer {
    pub fn new<P: Into<PathBuf>>(path: P) -> Result<Self, Error> {
        let path = path.into();
        let metadata_path = path.join("turingarena.yaml");
        let metadata_data = fs::read(metadata_path)?;
        let contest = serde_yaml::from_slice::<ContestFile>(&metadata_data)?;

        Ok(Importer { contest, path })
    }

    fn contest(&self) -> ContestInput {
        let files = self.path.join("files");
        ContestInput {
            start_time: self.contest.start.as_ref().unwrap().clone(), // TODO: handle not specified date
            end_time: self.contest.end.as_ref().unwrap().clone(),
            archive_content: FileContentInput {
                base64: base64::encode(&pack_archive(files)),
            },
        }
    }

    fn problems(&self) -> Vec<ProblemInput> {
        let mut problems = Vec::new();

        for problem in &self.contest.problems {
            let path = self.path.join(problem);
            problems.push(ProblemInput {
                name: problem.clone(),
                archive_content: FileContentInput {
                    base64: base64::encode(&pack_archive(path)),
                },
            });
        }

        problems
    }

    fn users(&self) -> Vec<UserInput> {
        let mut users = Vec::new();

        for user in &self.contest.users {
            users.push(UserInput {
                id: user.id.clone(),
                token: user.token.clone(),
                display_name: user.name.clone(),
                admin: match user.role.as_ref() {
                    Some(role) => role == "admin",
                    _ => false,
                },
            });
        }

        users
    }
}

impl TryInto<GraphQLRequest> for Importer {
    type Error = Error;

    fn try_into(self) -> Result<GraphQLRequest, Self::Error> {
        let variables = Variables {
            contest: self.contest(),
            problems: self.problems(),
            users: self.users(),
{'fraction_non_alphanumeric': 0.12881583361288157, 'fraction_numerical': 0.0026836632002683663, 'mean_word_length': 2.202470461868958, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '232627', 'n_tokens_mistral': 1756, 'n_tokens_neox': 1707, 'n_words': 420}