<commit_before>#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]

mod logger;
mod toml_file;
mod git;
mod changelog;
mod commit_analyzer;
mod cargo;
mod error;
mod github;
mod config;
mod utils;

extern crate rustc_serialize;
extern crate toml;
extern crate regex;
extern crate semver;
extern crate docopt;
extern crate git2;
extern crate clog;
extern crate hyper;
extern crate hubcaps;
extern crate url;
extern crate travis_after_all;
extern crate env_logger;

use docopt::Docopt;
use commit_analyzer::CommitType;
use config::ConfigBuilder;
use std::process;
use semver::Version;
use std::{env,fs};
use std::path::Path;
use std::error::Error;
use std::thread;
use std::time::Duration;
use travis_after_all::Build;
use utils::user_repo_from_url;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");
const USERAGENT: &'static str = concat!("semantic-rs/", env!("CARGO_PKG_VERSION"));
const USAGE: &'static str = "
semantic.rs 🚀

Usage:
  semantic-rs [options]
  semantic-rs --version

Options:
  -h --help              Show this screen.
  --version              Show version.
  -p PATH, --path=PATH   Specifies the repository path. [default: .]
  -w W, --write=W        Write changes to files (default: yes if CI is set, otherwise no).
  -r R, --release=R      Create release on GitHub and publish on crates.io (only in write mode) [default: yes].
  -b B, --branch=B       The branch on which releases should happen. [default: master].
";

macro_rules! print_exit {
    ($fmt:expr) => {{
        logger::stderr($fmt);
        process::exit(1);
    }};
    ($fmt:expr, $($arg:tt)*) => {{
        logger::stderr(format!($fmt, $($arg)*));
        process::exit(1);
    }};
}

#[derive(Debug, RustcDecodable)]
struct Args {
    flag_path: String,
    flag_write: Option<String>,
    flag_version: bool,
    flag_release: String,
    flag_branch: String,
}

fn string_to_bool(answer: &str) -> bool {
    match &answer.to_lowercase()[..] {
        "yes" | "true" | "1" => true,
        _ => false
    }
}

fn version_bump(version: &Version, bump: CommitType) -> Option<Version> {
    let mut version = version.clone();
    match bump {
        CommitType::Unknown => return None,
        CommitType::Patch => version.increment_patch(),
        CommitType::Minor => version.increment_minor(),
        CommitType::Major => version.increment_major(),
    }

    Some(version)
}

fn ci_env_set() -> bool {
    env::var("CI").is_ok()
}

fn current_branch(repo: &git2::Repository) -> Option<String> {
    if let Ok(branch) = env::var("TRAVIS_BRANCH") {
        return Some(branch)
    }

    let head = repo.head().expect("No HEAD found for repository");

    if head.is_branch() {
        let short = head.shorthand().expect("No branch name found");
        return Some(short.into());
    }

    None
}

fn is_release_branch(current: &str, release: &str) -> bool {
    if let Ok(pr) = env::var("TRAVIS_PULL_REQUEST") {
        if pr != "false" {
            return false;
        }
    }

    current == release
}

fn main() {
    env_logger::init().expect("Can't instantiate env logger");

    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());

    let mut config_builder = ConfigBuilder::new();

    if args.flag_version {
        println!("semantic.rs 🚀 -- v{}", VERSION);
        process::exit(0);
    }

    // If write mode is requested OR denied,
    // adhere to the user's wish,
    // otherwise we decide based on whether we are running in CI.
    let write_mode = match args.flag_write {
        None => ci_env_set(),
        Some(ref flag) => string_to_bool(flag)
    };

    // We can only release, if we are allowed to write
    let release_mode = write_mode && string_to_bool(&args.flag_release);

    config_builder.write(write_mode);
    config_builder.release(release_mode);
    config_builder.branch(args.flag_branch);

    println!("semantic.rs 🚀");

    logger::stdout("Analyzing your repository");
    let path = Path::new(&args.flag_path);
    let path = fs::canonicalize(path)
        .unwrap_or_else(|_| print_exit!("Path does not exist or a component is not a directory"));
    let repository_path = path.to_str()
        .unwrap_or_else(|| print_exit!("Path is not valid unicode"));

    let repo = match git2::Repository::open(repository_path) {
        Ok(repo) => repo,
        Err(e) => {
            logger::stderr(format!("Could not open the git repository: {:?}", e));
            process::exit(1);
        }
    };

    config_builder.repository_path(repository_path.to_owned());

    // extra scope scope to make sure borrow of `repo` is dropped
    {
        let signature = match git::get_signature(&repo) {
            Ok(sig) => sig,
            Err(e) => {
                logger::stderr(format!("Failed to get the committer's name and email address: {}", e.description()));
                logger::stderr(r"
A release commit needs a committer name and email address.
We tried fetching it from different locations, but couldn't find one.

Committer information is taken from the following environment variables, if set:

GIT_COMMITTER_NAME
GIT_COMMITTER_EMAIL

If none is set the normal git config is tried in the following order:

Local repository config
User config
Global config");
                process::exit(1);
            }
        };

        config_builder.signature(signature.to_owned());
    }

    // In case we are in write-mode AND release mode,
    // we will make sure we got all configuration settings
    if write_mode && release_mode {
        let remote_or_none = repo.find_remote("origin");
        match remote_or_none {
            Ok(remote) => {
                let url = remote.url().expect("Remote URL is not valid UTF-8").to_owned();
                let (user, repo_name) = user_repo_from_url(&url)
                    .unwrap_or_else(|e| print_exit!("Could not extract user and repository name from URL: {:?}", e));
                config_builder.user(user);
                config_builder.repository_name(repo_name);

                let gh_token = env::var("GH_TOKEN")
                    .unwrap_or_else(|err| print_exit!("GH_TOKEN not set: {:?}", err));

                let cargo_token = env::var("CARGO_TOKEN")
                    .unwrap_or_else(|err| print_exit!("CARGO_TOKEN not set: {:?}", err));

                config_builder.gh_token(gh_token);
                config_builder.cargo_token(cargo_token);
            },
            Err(err) => {
                logger::warn(format!("Could not determine the origin remote url: {:?}", err));
                logger::warn("semantic-rs can't push changes or create a release on GitHub");
            }
        }
    }

    config_builder.repository(repo);
    let config = config_builder.build();

    let branch = current_branch(&config.repository)
        .unwrap_or_else(|| print_exit!("Could not determine current branch."));

    if !is_release_branch(&branch, &config.branch) {
        println!("Current branch is '{}', releases are only done from branch '{}'", branch, config.branch);
        println!("No release done from a pull request either.");
        process::exit(0);
    }

    if config.release_mode && ci_env_set() {
        let build_run = Build::from_env()
            .unwrap_or_else(|e| print_exit!("CI mode, but can't check other builds. Error: {:?}", e));

        if !build_run.is_leader() {
            println!("Not the build leader. Nothing to do. Bye.");
            process::exit(0);
        }

        println!("I am the build leader. Waiting for other jobs to finish.");
        match build_run.wait_for_others() {
            Ok(()) => println!("Other jobs finished and succeeded. Doing my work now."),
            Err(travis_after_all::Error::FailedBuilds) => {
                print_exit!("Some builds failed. Stopping here.");
            },
            Err(e) => print_exit!("Waiting for other builds failed Reason: {:?}", e),
        }
    }

    let version = toml_file::read_from_file(&config.repository_path)
        .unwrap_or_else(|err| print_exit!("Reading `Cargo.toml` failed: {:?}", err));

    let version = Version::parse(&version).expect("Not a valid version");
    logger::stdout(format!("Current version: {}", version.to_string()));

    logger::stdout("Analyzing commits");

    let bump = git::version_bump_since_latest(&config.repository);
    if write_mode {
        logger::stdout(format!("Commits analyzed. Bump will be {:?}", bump));
    } else {
        logger::stdout(format!("Commits analyzed. Bump would be {:?}", bump));
    }
    let new_version = match version_bump(&version, bump) {
        Some(new_version) => new_version.to_string(),
        None => {
            logger::stdout("No version bump. Nothing to do.");
            process::exit(0);
        }
    };

    if !config.write_mode {
        logger::stdout(format!("New version would be: {}", new_version));
        logger::stdout("Would write the following Changelog:");
        let changelog = match changelog::generate(repository_path, &version.to_string(), &new_version) {
            Ok(log) => log,
            Err(err) => {
                logger::stderr(format!("Generating Changelog failed: {:?}", err));
                process::exit(1);
            }
        };
        logger::stdout("====================================");
        logger::stdout(changelog);
        logger::stdout("====================================");
        logger::stdout("Would create annotated git tag");
    } else {
        logger::stdout(format!("New version: {}", new_version));

        toml_file::write_new_version(repository_path, &new_version)
            .unwrap_or_else(|err| print_exit!("Writing `Cargo.toml` failed: {:?}", err));

        logger::stdout("Writing Changelog");
        changelog::write(repository_path, &version.to_string(), &new_version)
            .unwrap_or_else(|err| print_exit!("Writing Changelog failed: {:?}", err));

        if config.release_mode {
            logger::stdout("Updating lockfile");
            if !cargo::update_lockfile(repository_path) {
                print_exit!("`cargo fetch` failed. See above for the cargo error message.");
            }
        }

        logger::stdout("Package crate");
        if !cargo::package(repository_path) {
            print_exit!("`cargo package` failed. See above for the cargo error message.");
        }

        git::commit_files(&config, &new_version)
            .unwrap_or_else(|err| print_exit!("Committing files failed: {:?}", err));

        logger::stdout("Creating annotated git tag");
        let tag_message = changelog::generate(repository_path, &version.to_string(), &new_version)
            .unwrap_or_else(|err| print_exit!("Can't generate changelog: {:?}", err));

        let tag_name = format!("v{}", new_version);
        git::tag(&config, &tag_name, &tag_message)
            .unwrap_or_else(|err| print_exit!("Failed to create git tag: {:?}", err));

        if config.release_mode && config.can_push() {
            logger::stdout("Pushing new commit and tag");
            git::push(&config, &tag_name)
                .unwrap_or_else(|err| print_exit!("Failed to push git: {:?}", err));

            logger::stdout("Waiting a tiny bit, so GitHub can store the git tag");
            thread::sleep(Duration::from_secs(1));

            logger::stdout("Creating GitHub release");
            github::release(&config, &tag_name, &tag_message)
                .unwrap_or_else(|err| print_exit!("Failed to create GitHub release: {:?}", err));

            logger::stdout("Publishing crate on crates.io");
            if !cargo::publish(&config.repository_path, &config.cargo_token.as_ref().unwrap()) {
                print_exit!("Failed to publish on crates.io");
            }

            println!("{} v{} is released. 🚀🚀🚀", config.repository_name.unwrap(), new_version);
        }
    }
}
<commit_msg>refactor: Move release code into functions<commit_after>#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]

mod logger;
mod toml_file;
mod git;
mod changelog;
mod commit_analyzer;
mod cargo;
mod error;
mod github;
mod config;
mod utils;

extern crate rustc_serialize;
extern crate toml;
extern crate regex;
extern crate semver;
extern crate docopt;
extern crate git2;
extern crate clog;
extern crate hyper;
extern crate hubcaps;
extern crate url;
extern crate travis_after_all;
extern crate env_logger;

use docopt::Docopt;
use commit_analyzer::CommitType;
use config::ConfigBuilder;
use std::process;
use semver::Version;
use std::{env,fs};
use std::path::Path;
use std::error::Error;
use std::thread;
use std::time::Duration;
use travis_after_all::Build;
use utils::user_repo_from_url;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");
const USERAGENT: &'static str = concat!("semantic-rs/", env!("CARGO_PKG_VERSION"));
const USAGE: &'static str = "
semantic.rs 🚀

Usage:
  semantic-rs [options]
  semantic-rs --version

Options:
  -h --help              Show this screen.
  --version              Show version.
  -p PATH, --path=PATH   Specifies the repository path. [default: .]
  -w W, --write=W        Write changes to files (default: yes if CI is set, otherwise no).
  -r R, --release=R      Create release on GitHub and publish on crates.io (only in write mode) [default: yes].
  -b B, --branch=B       The branch on which releases should happen. [default: master].
";

macro_rules! print_exit {
    ($fmt:expr) => {{
        logger::stderr($fmt);
        process::exit(1);
    }};
    ($fmt:expr, $($arg:tt)*) => {{
        logger::stderr(format!($fmt, $($arg)*));
        process::exit(1);
    }};
}

#[derive(Debug, RustcDecodable)]
struct Args {
    flag_path: String,
    flag_write: Option<String>,
    flag_version: bool,
    flag_release: String,
    flag_branch: String,
}

fn string_to_bool(answer: &str) -> bool {
    match &answer.to_lowercase()[..] {
        "yes" | "true" | "1" => true,
        _ => false
    }
}

fn version_bump(version: &Version, bump: CommitType) -> Option<Version> {
    let mut version = version.clone();
    match bump {
        CommitType::Unknown => return None,
        CommitType::Patch => version.increment_patch(),
        CommitType::Minor => version.increment_minor(),
        CommitType::Major => version.increment_major(),
    }

    Some(version)
}

fn ci_env_set() -> bool {
    env::var("CI").is_ok()
}

fn current_branch(repo: &git2::Repository) -> Option<String> {
    if let Ok(branch) = env::var("TRAVIS_BRANCH") {
        return Some(branch)
    }

    let head = repo.head().expect("No HEAD found for repository");

    if head.is_branch() {
        let short = head.shorthand().expect("No branch name found");
        return Some(short.into());
    }

    None
}

fn is_release_branch(current: &str, release: &str) -> bool {
    if let Ok(pr) = env::var("TRAVIS_PULL_REQUEST") {
        if pr != "false" {
            return false;
        }
    }

    current == release
}

fn push_to_github(config: &config::Config, tag_name: &str) {
    logger::stdout("Pushing new commit and tag");
    git::push(&config, &tag_name)
        .unwrap_or_else(|err| print_exit!("Failed to push git: {:?}", err));

    logger::stdout("Waiting a tiny bit, so GitHub can store the git tag");
    thread::sleep(Duration::from_secs(1));
}

fn release_on_github(config: &config::Config, tag_message: &str, tag_name: &str) {
    logger::stdout("Creating GitHub release");
    github::release(&config, &tag_name, &tag_message)
        .unwrap_or_else(|err| print_exit!("Failed to create GitHub release: {:?}", err));
}

fn release_on_cratesio(config: &config::Config) {
    logger::stdout("Publishing crate on crates.io");
    if !cargo::publish(&config.repository_path, &config.cargo_token.as_ref().unwrap()) {
        print_exit!("Failed to publish on crates.io");
    }
}

fn main() {
    env_logger::init().expect("Can't instantiate env logger");

    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());

    let mut config_builder = ConfigBuilder::new();

    if args.flag_version {
        println!("semantic.rs 🚀 -- v{}", VERSION);
        process::exit(0);
    }

    // If write mode is requested OR denied,
    // adhere to the user's wish,
    // otherwise we decide based on whether we are running in CI.
    let write_mode = match args.flag_write {
        None => ci_env_set(),
        Some(ref flag) => string_to_bool(flag)
    };

    // We can only release, if we are allowed to write
    let release_mode = write_mode && string_to_bool(&args.flag_release);

    config_builder.write(write_mode);
    config_builder.release(release_mode);
    config_builder.branch(args.flag_branch);

    println!("semantic.rs 🚀");

    logger::stdout("Analyzing your repository");
    let path = Path::new(&args.flag_path);
    let path = fs::canonicalize(path)
        .unwrap_or_else(|_| print_exit!("Path does not exist or a component is not a directory"));
    let repository_path = path.to_str()
        .unwrap_or_else(|| print_exit!("Path is not valid unicode"));

    let repo = match git2::Repository::open(repository_path) {
        Ok(repo) => repo,
        Err(e) => {
            logger::stderr(format!("Could not open the git repository: {:?}", e));
            process::exit(1);
        }
    };

    config_builder.repository_path(repository_path.to_owned());

    // extra scope scope to make sure borrow of `repo` is dropped
    {
        let signature = match git::get_signature(&repo) {
            Ok(sig) => sig,
            Err(e) => {
                logger::stderr(format!("Failed to get the committer's name and email address: {}", e.description()));
                logger::stderr(r"
A release commit needs a committer name and email address.
We tried fetching it from different locations, but couldn't find one.

Committer information is taken from the following environment variables, if set:

GIT_COMMITTER_NAME
GIT_COMMITTER_EMAIL

If none is set the normal git config is tried in the following order:

Local repository config
User config
Global config");
                process::exit(1);
            }
        };

        config_builder.signature(signature.to_owned());
    }

    // In case we are in write-mode AND release mode,
    // we will make sure we got all configuration settings
    if write_mode && release_mode {
        let remote_or_none = repo.find_remote("origin");
        match remote_or_none {
            Ok(remote) => {
                let url = remote.url().expect("Remote URL is not valid UTF-8").to_owned();
                let (user, repo_name) = user_repo_from_url(&url)
                    .unwrap_or_else(|e| print_exit!("Could not extract user and repository name from URL: {:?}", e));
                config_builder.user(user);
                config_builder.repository_name(repo_name);

                let gh_token = env::var("GH_TOKEN")
                    .unwrap_or_else(|err| print_exit!("GH_TOKEN not set: {:?}", err));

                let cargo_token = env::var("CARGO_TOKEN")
                    .unwrap_or_else(|err| print_exit!("CARGO_TOKEN not set: {:?}", err));

                config_builder.gh_token(gh_token);
                config_builder.cargo_token(cargo_token);
            },
            Err(err) => {
                logger::warn(format!("Could not determine the origin remote url: {:?}", err));
                logger::warn("semantic-rs can't push changes or create a release on GitHub");
            }
        }
    }

    config_builder.repository(repo);
    let config = config_builder.build();

    let branch = current_branch(&config.repository)
        .unwrap_or_else(|| print_exit!("Could not determine current branch."));

    if !is_release_branch(&branch, &config.branch) {
        println!("Current branch is '{}', releases are only done from branch '{}'", branch, config.branch);
        println!("No release done from a pull request either.");
        process::exit(0);
    }

    if config.release_mode && ci_env_set() {
        let build_run = Build::from_env()
            .unwrap_or_else(|e| print_exit!("CI mode, but can't check other builds. Error: {:?}", e));

        if !build_run.is_leader() {
            println!("Not the build leader. Nothing to do. Bye.");
            process::exit(0);
        }

        println!("I am the build leader. Waiting for other jobs to finish.");
        match build_run.wait_for_others() {
            Ok(()) => println!("Other jobs finished and succeeded. Doing my work now."),
            Err(travis_after_all::Error::FailedBuilds) => {
                print_exit!("Some builds failed. Stopping here.");
            },
            Err(e) => print_exit!("Waiting for other builds failed Reason: {:?}", e),
        }
    }

    let version = toml_file::read_from_file(&config.repository_path)
        .unwrap_or_else(|err| print_exit!("Reading `Cargo.toml` failed: {:?}", err));

    let version = Version::parse(&version).expect("Not a valid version");
    logger::stdout(format!("Current version: {}", version.to_string()));

    logger::stdout("Analyzing commits");

    let bump = git::version_bump_since_latest(&config.repository);
    if write_mode {
        logger::stdout(format!("Commits analyzed. Bump will be {:?}", bump));
    } else {
        logger::stdout(format!("Commits analyzed. Bump would be {:?}", bump));
    }
    let new_version = match version_bump(&version, bump) {
        Some(new_version) => new_version.to_string(),
        None => {
            logger::stdout("No version bump. Nothing to do.");
            process::exit(0);
        }
    };

    if !config.write_mode {
        logger::stdout(format!("New version would be: {}", new_version));
        logger::stdout("Would write the following Changelog:");
        let changelog = match changelog::generate(repository_path, &version.to_string(), &new_version) {
            Ok(log) => log,
            Err(err) => {
                logger::stderr(format!("Generating Changelog failed: {:?}", err));
                process::exit(1);
            }
        };
        logger::stdout("====================================");
        logger::stdout(changelog);
        logger::stdout("====================================");
        logger::stdout("Would create annotated git tag");
    } else {
        logger::stdout(format!("New version: {}", new_version));

        toml_file::write_new_version(repository_path, &new_version)
            .unwrap_or_else(|err| print_exit!("Writing `Cargo.toml` failed: {:?}", err));

        logger::stdout("Writing Changelog");
        changelog::write(repository_path, &version.to_string(), &new_version)
            .unwrap_or_else(|err| print_exit!("Writing Changelog failed: {:?}", err));

        if config.release_mode {
            logger::stdout("Updating lockfile");
            if !cargo::update_lockfile(repository_path) {
                print_exit!("`cargo fetch` failed. See above for the cargo error message.");
            }
        }

        logger::stdout("Package crate");
        if !cargo::package(repository_path) {
            print_exit!("`cargo package` failed. See above for the cargo error message.");
        }

        git::commit_files(&config, &new_version)
            .unwrap_or_else(|err| print_exit!("Committing files failed: {:?}", err));

        logger::stdout("Creating annotated git tag");
        let tag_message = changelog::generate(repository_path, &version.to_string(), &new_version)
            .unwrap_or_else(|err| print_exit!("Can't generate changelog: {:?}", err));

        let tag_name = format!("v{}", new_version);
        git::tag(&config, &tag_name, &tag_message)
            .unwrap_or_else(|err| print_exit!("Failed to create git tag: {:?}", err));

        if config.release_mode && config.can_push() {
            push_to_github(&config, &tag_name);
            release_on_github(&config, &tag_message, &tag_name);
            release_on_cratesio(&config);
            println!("{} v{} is released. 🚀🚀🚀", config.repository_name.unwrap(), new_version);
        }
    }
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate chrono;
extern crate sxd_document;

use std::env;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use rustc_serialize::json::Json;
use chrono::*;
use sxd_document::Package;
use sxd_document::writer::format_document;

fn help() {
    println!("usage: convert-to-gpx infile.json [outfile.gpx]");
}

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        help();
        return;
    }

    // Process the arguments
    let input = args[1].to_owned();
    let output;
    if args.len() > 2 {
        let path = Path::new(&args[2]);
        output = path.file_stem().unwrap().to_str().unwrap();
    }
    else {
        let path = Path::new(&input);
        output = path.file_stem().unwrap().to_str().unwrap();
    }

    // Read the JSON file
    let mut file = File::open(&input).unwrap();
    let mut contents = String::new();
    file.read_to_string(&mut contents).unwrap();

    let json = Json::from_str(&contents).unwrap();
    let object = json.as_object().unwrap();

    // Try to find the "Runs" array in the JSON
    if let Some(run_array) = object.get("Runs").and_then(|x| x.as_array()) {

        let mut run_number = 1;

        // Loop over each run
        for run in run_array.iter().map(|x| x.as_object().unwrap()) {

            println!("Run #{}", run_number);

            // Collect the distance and time array from the PaceData
            // This array will later help us calculate the time each WayPoint occurs
            let mut distance_and_time_array = Vec::<(f64, i64)>::new();
            if let Some(pace_data_array) = run.get("PaceData").and_then(|x| x.as_array()) {
                for pace_data in pace_data_array.iter().map(|x| x.as_object().unwrap()) {
                    match (pace_data.get("ScaledDistance").and_then(|x| x.as_f64()),
                        pace_data.get("ElapsedSeconds").and_then(|x| x.as_i64())) {

                        (Some(distance), Some(time)) => distance_and_time_array.push((distance, time)),
                        _ => {}
                    }
                }
            }

            if distance_and_time_array.len() == 0 {
                run_number += 1;
                continue;
            }
            let mut last_distance_and_time = distance_and_time_array.remove(0);

            // Process the start date from the MS timestamp
            let start_date_seconds = run.get("StartDate")
                .and_then(|x| x.as_string().unwrap_or("").split(&['(', ')'][..]).nth(1))
                .unwrap()
                .parse::<i64>()
                .ok()
                .unwrap() / 1_000;
            let naive_start_date = NaiveDateTime::from_timestamp(start_date_seconds, 0);
            let start_date = DateTime::<UTC>::from_utc(naive_start_date, UTC);

            // Construct GPX document
            let gpx_package = Package::new();
            let gpx_document = gpx_package.as_document();
            let gpx_element = gpx_document.create_element("gpx");
            gpx_element.set_attribute_value("creator", "convert-to-gpx");
            gpx_element.set_attribute_value("version", "1.1");
            gpx_element.set_attribute_value("xmlns", "http://www.topografix.com/GPX/1/1");
            gpx_element.set_attribute_value("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
            gpx_element.set_attribute_value("xsi:schemaLocation", "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd");
            gpx_element.set_attribute_value("xmlns:gpxtpx", "http://www.garmin.com/xmlschemas/TrackPointExtension/v1");
            gpx_element.set_attribute_value("xmlns:gpxx", "http://www.garmin.com/xmlschemas/GpxExtensions/v3");
            gpx_document.root().append_child(gpx_element);

            let metadata_element = gpx_document.create_element("metadata");
            let time_element = gpx_document.create_element("time");
            time_element.append_child(gpx_document.create_text(&start_date.format("%Y-%m-%dT%H:%M:%SZ").to_string()));
            metadata_element.append_child(time_element);
            gpx_element.append_child(metadata_element);

            let track_element = gpx_document.create_element("trk");
            let track_segment_element = gpx_document.create_element("trkseg");
            track_element.append_child(track_segment_element);
            gpx_element.append_child(track_element);

            if let Some(map_point_array) = run.get("MapPoints").and_then(|x| x.as_array()) {
                for map_point in map_point_array.iter().map(|x| x.as_object().unwrap()) {
                    if let Some(location) = map_point.get("Location").and_then(|x| x.as_object()) {
                        match (location.get("Latitude").and_then(|x| x.as_f64()),
                            location.get("Longitude").and_then(|x| x.as_f64()),
                            map_point.get("TotalDistance").and_then(|x| x.as_f64()),
                            map_point.get("HeartRate").and_then(|x| x.as_i64())) {

                            (Some(latitude), Some(longitude), Some(distance), Some(heart_rate)) => {
                                while distance_and_time_array.len() > 0 && distance > distance_and_time_array[0].0 {
                                    last_distance_and_time = distance_and_time_array.remove(0);
                                }

                                // Try to extrapolate the elapsed seconds from the distance and time from the PaceData
                                let time;
                                if distance_and_time_array.len() > 0 {
                                    let scale = (distance - last_distance_and_time.0) / (distance_and_time_array[0].0 - last_distance_and_time.0);
                                    time = scale * (distance_and_time_array[0].1 - last_distance_and_time.1) as f64 + last_distance_and_time.1 as f64;
                                }
                                else {
                                    time = last_distance_and_time.1 as f64;
                                }

                                // Create the GPX elements for the track point
                                let trackpoint_element = gpx_document.create_element("trkpt");
                                trackpoint_element.set_attribute_value("lat", &format!("{}", latitude / 10_000_000.0));
                                trackpoint_element.set_attribute_value("lon", &format!("{}", longitude / 10_000_000.0));
                                track_segment_element.append_child(trackpoint_element);

                                let waypoint_date = start_date + Duration::seconds(time as i64);
                                let time_element = gpx_document.create_element("time");
                                time_element.append_child(gpx_document.create_text(&waypoint_date.format("%Y-%m-%dT%H:%M:%SZ").to_string()));
                                trackpoint_element.append_child(time_element);

                                let extensions_element = gpx_document.create_element("extensions");
                                let trackpoint_extension_element = gpx_document.create_element("gpxtpx:TrackPointExtension");
                                let heartrate_element = gpx_document.create_element("gpxtpx:hr");
                                heartrate_element.append_child(gpx_document.create_text(&format!("{}", heart_rate)));
                                trackpoint_extension_element.append_child(heartrate_element);
                                extensions_element.append_child(trackpoint_extension_element);
                                trackpoint_element.append_child(extensions_element);
                            },
                            _ => {}
                        }
                    }
                }

                // Output the XML file
                let output_filename = String::from(output) + &format!("-{}.gpx", run_number);
                let mut buffer = File::create(output_filename).ok().expect("There was a problem opening the GPX file.");
                format_document(&gpx_document, &mut buffer).ok().expect("There was a problem outputting the XML.");
            }
            else {
                println!("Could not find any MapPoints! Skipping this run...");
            }

            run_number += 1;
        }
    }
}
<commit_msg>Fix command name to new project name in help<commit_after>extern crate rustc_serialize;
extern crate chrono;
extern crate sxd_document;

use std::env;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use rustc_serialize::json::Json;
use chrono::*;
use sxd_document::Package;
use sxd_document::writer::format_document;

fn help() {
    println!("usage: rust-msband-to-gpx infile.json [outfile.gpx]");
}

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        help();
        return;
    }

    // Process the arguments
    let input = args[1].to_owned();
    let output;
    if args.len() > 2 {
        let path = Path::new(&args[2]);
        output = path.file_stem().unwrap().to_str().unwrap();
    }
    else {
        let path = Path::new(&input);
        output = path.file_stem().unwrap().to_str().unwrap();
    }

    // Read the JSON file
    let mut file = File::open(&input).unwrap();
    let mut contents = String::new();
    file.read_to_string(&mut contents).unwrap();

    let json = Json::from_str(&contents).unwrap();
    let object = json.as_object().unwrap();

    // Try to find the "Runs" array in the JSON
    if let Some(run_array) = object.get("Runs").and_then(|x| x.as_array()) {

        let mut run_number = 1;

        // Loop over each run
        for run in run_array.iter().map(|x| x.as_object().unwrap()) {

            println!("Run #{}", run_number);

            // Collect the distance and time array from the PaceData
            // This array will later help us calculate the time each WayPoint occurs
            let mut distance_and_time_array = Vec::<(f64, i64)>::new();
            if let Some(pace_data_array) = run.get("PaceData").and_then(|x| x.as_array()) {
                for pace_data in pace_data_array.iter().map(|x| x.as_object().unwrap()) {
                    match (pace_data.get("ScaledDistance").and_then(|x| x.as_f64()),
                        pace_data.get("ElapsedSeconds").and_then(|x| x.as_i64())) {

                        (Some(distance), Some(time)) => distance_and_time_array.push((distance, time)),
                        _ => {}
                    }
                }
            }

            if distance_and_time_array.len() == 0 {
                run_number += 1;
                continue;
            }
            let mut last_distance_and_time = distance_and_time_array.remove(0);

            // Process the start date from the MS timestamp
            let start_date_seconds = run.get("StartDate")
                .and_then(|x| x.as_string().unwrap_or("").split(&['(', ')'][..]).nth(1))
                .unwrap()
                .parse::<i64>()
                .ok()
                .unwrap() / 1_000;
            let naive_start_date = NaiveDateTime::from_timestamp(start_date_seconds, 0);
            let start_date = DateTime::<UTC>::from_utc(naive_start_date, UTC);

            // Construct GPX document
            let gpx_package = Package::new();
            let gpx_document = gpx_package.as_document();
            let gpx_element = gpx_document.create_element("gpx");
            gpx_element.set_attribute_value("creator", "convert-to-gpx");
            gpx_element.set_attribute_value("version", "1.1");
            gpx_element.set_attribute_value("xmlns", "http://www.topografix.com/GPX/1/1");
            gpx_element.set_attribute_value("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
            gpx_element.set_attribute_value("xsi:schemaLocation", "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd");
            gpx_element.set_attribute_value("xmlns:gpxtpx", "http://www.garmin.com/xmlschemas/TrackPointExtension/v1");
            gpx_element.set_attribute_value("xmlns:gpxx", "http://www.garmin.com/xmlschemas/GpxExtensions/v3");
            gpx_document.root().append_child(gpx_element);

            let metadata_element = gpx_document.create_element("metadata");
            let time_element = gpx_document.create_element("time");
            time_element.append_child(gpx_document.create_text(&start_date.format("%Y-%m-%dT%H:%M:%SZ").to_string()));
            metadata_element.append_child(time_element);
            gpx_element.append_child(metadata_element);

            let track_element = gpx_document.create_element("trk");
            let track_segment_element = gpx_document.create_element("trkseg");
            track_element.append_child(track_segment_element);
            gpx_element.append_child(track_element);

            if let Some(map_point_array) = run.get("MapPoints").and_then(|x| x.as_array()) {
                for map_point in map_point_array.iter().map(|x| x.as_object().unwrap()) {
                    if let Some(location) = map_point.get("Location").and_then(|x| x.as_object()) {
                        match (location.get("Latitude").and_then(|x| x.as_f64()),
                            location.get("Longitude").and_then(|x| x.as_f64()),
                            map_point.get("TotalDistance").and_then(|x| x.as_f64()),
                            map_point.get("HeartRate").and_then(|x| x.as_i64())) {

                            (Some(latitude), Some(longitude), Some(distance), Some(heart_rate)) => {
                                while distance_and_time_array.len() > 0 && distance > distance_and_time_array[0].0 {
                                    last_distance_and_time = distance_and_time_array.remove(0);
                                }

                                // Try to extrapolate the elapsed seconds from the distance and time from the PaceData
                                let time;
                                if distance_and_time_array.len() > 0 {
                                    let scale = (distance - last_distance_and_time.0) / (distance_and_time_array[0].0 - last_distance_and_time.0);
                                    time = scale * (distance_and_time_array[0].1 - last_distance_and_time.1) as f64 + last_distance_and_time.1 as f64;
                                }
                                else {
                                    time = last_distance_and_time.1 as f64;
                                }

                                // Create the GPX elements for the track point
                                let trackpoint_element = gpx_document.create_element("trkpt");
                                trackpoint_element.set_attribute_value("lat", &format!("{}", latitude / 10_000_000.0));
                                trackpoint_element.set_attribute_value("lon", &format!("{}", longitude / 10_000_000.0));
                                track_segment_element.append_child(trackpoint_element);

                                let waypoint_date = start_date + Duration::seconds(time as i64);
                                let time_element = gpx_document.create_element("time");
                                time_element.append_child(gpx_document.create_text(&waypoint_date.format("%Y-%m-%dT%H:%M:%SZ").to_string()));
                                trackpoint_element.append_child(time_element);

                                let extensions_element = gpx_document.create_element("extensions");
                                let trackpoint_extension_element = gpx_document.create_element("gpxtpx:TrackPointExtension");
                                let heartrate_element = gpx_document.create_element("gpxtpx:hr");
                                heartrate_element.append_child(gpx_document.create_text(&format!("{}", heart_rate)));
                                trackpoint_extension_element.append_child(heartrate_element);
                                extensions_element.append_child(trackpoint_extension_element);
                                trackpoint_element.append_child(extensions_element);
                            },
                            _ => {}
                        }
                    }
                }

                // Output the XML file
                let output_filename = String::from(output) + &format!("-{}.gpx", run_number);
                let mut buffer = File::create(output_filename).ok().expect("There was a problem opening the GPX file.");
                format_document(&gpx_document, &mut buffer).ok().expect("There was a problem outputting the XML.");
            }
            else {
                println!("Could not find any MapPoints! Skipping this run...");
            }

            run_number += 1;
        }
    }
}
<|endoftext|>


<commit_before>#![feature(phase)]

#[phase(plugin, link)] extern crate log;
extern crate tmpdir;

use std::io::fs;
use std::io::process::{Command,ExitSignal,ExitStatus,InheritFd,ProcessOutput};
use std::os;

use tmpdir::TmpDir;

fn is_crate(arg: &str) -> bool {
    Path::new(arg).exists()
}

fn main() {
    let args = os::args();
    let args = args.slice_from(1);

    // If `--run` is not in the arguments: pass all the arguments to `rustc`
    if args.iter().all(|arg| arg.as_slice() != "--run") {
        let mut cmd = Command::new("rustc");
        cmd.args(args);
        cmd.stdout(InheritFd(1));
        cmd.stderr(InheritFd(2));

        info!("cwd: . | cmd: `{}`", cmd);
        match cmd.output() {
            Err(e) => fail!("`{}` failed: {}", cmd, e),
            Ok(ProcessOutput { status: exit, .. }) =>  {
                let exit_code = match exit {
                    ExitSignal(code) => code,
                    ExitStatus(code) => code,
                };

                os::set_exit_status(exit_code);

                return;
            },
        }
    }

    // Before `--run`: arguments for the compiler
    let mut splitted_args = args.split(|arg| arg.as_slice() == "--run");
    let rustc_args = splitted_args.next().unwrap();
    let executable_args = splitted_args.next().unwrap();

    // TODO `--crate-type=lib` should also be forbidden
    // XXX What if the crate has a `crate_type=*lib` attribute?
    if rustc_args.iter().any(|arg| arg.as_slice() == "--out-dir") {
        fail!("Can't use both `--out-dir` and `--run` flags at the same time");
    }

    // Separate the crate file from the other arguments
    let crate_arg = match args.iter().find(|arg| {
        is_crate(arg.as_slice())
    }) {
        Some(arg) => arg,
        None => fail!("Didn't find a crate file in the arguments passed"),
    };

    // Use full path for the crate file
    let current_dir = os::getcwd();
    let crate_path = {
        let path = Path::new(crate_arg.as_slice());

        if path.is_absolute() {
            path
        } else {
            current_dir.join(path)
        }
    };

    // Build the rustc command
    let mut cmd = Command::new("rustc");
    for arg in rustc_args.iter().filter(|&arg| arg != crate_arg) {
        cmd.arg(arg.as_slice());
    }
    cmd.arg(crate_path);
    cmd.stdout(InheritFd(1));
    cmd.stderr(InheritFd(2));

    // Create temporary directory
    let tmpdir = TmpDir::new("rust");
    let tmpdir_path = tmpdir.path();
    let tmpdir_display = tmpdir_path.display();

    // Compile
    info!("cwd: {} | cmd: `{}`", tmpdir_display, cmd);
    match cmd.cwd(tmpdir_path).output() {
        Err(e) => fail!("`{}` failed: {}", cmd, e),
        Ok(ProcessOutput { status: exit, .. }) => if !exit.success() {
            let exit_code = match exit {
                ExitSignal(code) => code,
                ExitStatus(code) => code,
            };

            os::set_exit_status(exit_code);
            return;
        },
    }

    // Look for the produced binary
    let mut cmd = match fs::readdir(tmpdir_path) {
        Err(e) => fail!("`ls {}` failed: {}", tmpdir_display, e),
        Ok(paths) => match paths.as_slice().get(0) {
            Some(path) => Command::new(path),
            None => fail!("no binary found in {}", tmpdir_display),
        }
    };

    // Build the executable command
    for arg in executable_args.iter().filter(|&arg| arg != crate_arg) {
        cmd.arg(arg.as_slice());
    }
    cmd.stdout(InheritFd(1));
    cmd.stderr(InheritFd(2));

    // Execute
    info!("cwd: . | cmd: `{}`", cmd);
    match cmd.output() {
        Err(e) => fail!("`{}` failed: {}", cmd, e),
        Ok(ProcessOutput { status: exit, .. }) => if !exit.success() {
            let exit_code = match exit {
                ExitSignal(code) => code,
                ExitStatus(code) => code,
            };

            os::set_exit_status(exit_code);
            return;
        },
    }
}
<commit_msg>Inherit the stdin of the executable<commit_after>#![feature(phase)]

#[phase(plugin, link)] extern crate log;
extern crate tmpdir;

use std::io::fs;
use std::io::process::{Command,ExitSignal,ExitStatus,InheritFd,ProcessOutput};
use std::os;

use tmpdir::TmpDir;

fn is_crate(arg: &str) -> bool {
    Path::new(arg).exists()
}

fn main() {
    let args = os::args();
    let args = args.slice_from(1);

    // If `--run` is not in the arguments: pass all the arguments to `rustc`
    if args.iter().all(|arg| arg.as_slice() != "--run") {
        let mut cmd = Command::new("rustc");
        cmd.args(args);
        cmd.stdout(InheritFd(1));
        cmd.stderr(InheritFd(2));

        info!("cwd: . | cmd: `{}`", cmd);
        match cmd.output() {
            Err(e) => fail!("`{}` failed: {}", cmd, e),
            Ok(ProcessOutput { status: exit, .. }) =>  {
                let exit_code = match exit {
                    ExitSignal(code) => code,
                    ExitStatus(code) => code,
                };

                os::set_exit_status(exit_code);

                return;
            },
        }
    }

    // Before `--run`: arguments for the compiler
    let mut splitted_args = args.split(|arg| arg.as_slice() == "--run");
    let rustc_args = splitted_args.next().unwrap();
    let executable_args = splitted_args.next().unwrap();

    // TODO `--crate-type=lib` should also be forbidden
    // XXX What if the crate has a `crate_type=*lib` attribute?
    if rustc_args.iter().any(|arg| arg.as_slice() == "--out-dir") {
        fail!("Can't use both `--out-dir` and `--run` flags at the same time");
    }

    // Separate the crate file from the other arguments
    let crate_arg = match args.iter().find(|arg| {
        is_crate(arg.as_slice())
    }) {
        Some(arg) => arg,
        None => fail!("Didn't find a crate file in the arguments passed"),
    };

    // Use full path for the crate file
    let current_dir = os::getcwd();
    let crate_path = {
        let path = Path::new(crate_arg.as_slice());

        if path.is_absolute() {
            path
        } else {
            current_dir.join(path)
        }
    };

    // Build the rustc command
    let mut cmd = Command::new("rustc");
    for arg in rustc_args.iter().filter(|&arg| arg != crate_arg) {
        cmd.arg(arg.as_slice());
    }
    cmd.arg(crate_path);
    cmd.stdout(InheritFd(1));
    cmd.stderr(InheritFd(2));

    // Create temporary directory
    let tmpdir = TmpDir::new("rust");
    let tmpdir_path = tmpdir.path();
    let tmpdir_display = tmpdir_path.display();

    // Compile
    info!("cwd: {} | cmd: `{}`", tmpdir_display, cmd);
    match cmd.cwd(tmpdir_path).output() {
        Err(e) => fail!("`{}` failed: {}", cmd, e),
        Ok(ProcessOutput { status: exit, .. }) => if !exit.success() {
            let exit_code = match exit {
                ExitSignal(code) => code,
                ExitStatus(code) => code,
            };

            os::set_exit_status(exit_code);
            return;
        },
    }

    // Look for the produced binary
    let mut cmd = match fs::readdir(tmpdir_path) {
        Err(e) => fail!("`ls {}` failed: {}", tmpdir_display, e),
        Ok(paths) => match paths.as_slice().get(0) {
            Some(path) => Command::new(path),
            None => fail!("no binary found in {}", tmpdir_display),
        }
    };

    // Build the executable command
    for arg in executable_args.iter().filter(|&arg| arg != crate_arg) {
        cmd.arg(arg.as_slice());
    }
    cmd.stdin(InheritFd(0));
    cmd.stdout(InheritFd(1));
    cmd.stderr(InheritFd(2));

    // Execute
    info!("cwd: . | cmd: `{}`", cmd);
    match cmd.output() {
        Err(e) => fail!("`{}` failed: {}", cmd, e),
        Ok(ProcessOutput { status: exit, .. }) => if !exit.success() {
            let exit_code = match exit {
                ExitSignal(code) => code,
                ExitStatus(code) => code,
            };

            os::set_exit_status(exit_code);
            return;
        },
    }
}
<|endoftext|>


<commit_before>#[derive(Clone, Copy, Debug)]
enum Const {
  Data,
  Codata,
}

impl ToString for Const {
  fn to_string(&self) -> String {
    use Const::*;
    match *self {
      Data => "data".to_string(),
      Codata => "codata".to_string(),
    }
  }
}

#[derive(Clone, Debug)]
struct Var {
  name: String,
  idx: i32,
}

impl Var {
  pub fn new(name: &str, idx: i32) -> Var {
    Var {
      name: name.to_string(),
      idx: idx,
    }
  }
}

impl ToString for Var {
  fn to_string(&self) -> String {
    self.name.clone()
     // + "@" + &self.idx.to_string()
  }
}

#[derive(Clone, Debug)]
enum Expr {
  // Type system constants
  Const(Const),
  // Bound variables
  Var(Var),
  // Lambda
  Lam(Var, Box<Expr>, Box<Expr>),
  // "forall"
  Pi(Var, Box<Expr>, Box<Expr>),
  // Function application
  App(Box<Expr>, Box<Expr>),
}

impl Expr {
  pub fn constant(constant: Const) -> Expr {
    Expr::Const(constant)
  }
  pub fn var(v: &Var) -> Expr {
    Expr::Var(v.clone())
  }
  pub fn lam(var: Var, ty: Expr, body: Expr) -> Expr {
    Expr::Lam(var, Box::new(ty), Box::new(body))
  }
  pub fn pi(var: Var, ty: Expr, body: Expr) -> Expr {
    Expr::Pi(var, Box::new(ty), Box::new(body))
  }
  pub fn app(f: Expr, arg: Expr) -> Expr {
    Expr::App(Box::new(f), Box::new(arg))
  }
}

impl ToString for Expr {
  fn to_string(&self) -> String {
    use Expr::*;
    match self {
      &Const(ref constant) => constant.to_string(),
      &Var(ref var) => var.to_string(),
      &Lam(ref var, ref ty, ref body) => {
        var.to_string() + ":" + &ty.to_string() + " -> " + &body.to_string()
      }
      &Pi(ref var, ref ty, ref body) => {
        "forall (".to_string() + &var.to_string() + ":" + &ty.to_string() +
        ") -> " + &body.to_string()
      }
      &App(ref f, ref arg) => f.to_string() + " " + &arg.to_string(),
    }
  }
}

fn main() {
  println!("{}", Const::Data.to_string());
  println!("{:?}", Expr::constant(Const::Data));
  let a = Var::new("a", 0);
  let x = Var::new("x", 0);
  let expra = Expr::var(&a);
  let exprx = Expr::var(&x);
  // let x = Expr::var("x", 0);
  println!("{}", x.to_string());
  let id = Expr::pi(a.clone(),
                    Expr::constant(Const::Data),
                    Expr::lam(x, expra, exprx));
  println!("{}", id.to_string());
}
<commit_msg>Remove old comments.<commit_after>#[derive(Clone, Copy, Debug)]
enum Const {
  Data,
  Codata,
}

impl ToString for Const {
  fn to_string(&self) -> String {
    use Const::*;
    match *self {
      Data => "data".to_string(),
      Codata => "codata".to_string(),
    }
  }
}

#[derive(Clone, Debug)]
struct Var {
  name: String,
  idx: i32,
}

impl Var {
  pub fn new(name: &str, idx: i32) -> Var {
    Var {
      name: name.to_string(),
      idx: idx,
    }
  }
}

impl ToString for Var {
  fn to_string(&self) -> String {
    self.name.clone()
     // + "@" + &self.idx.to_string()
  }
}

#[derive(Clone, Debug)]
enum Expr {
  // Type system constants
  Const(Const),
  // Bound variables
  Var(Var),
  // Lambda
  Lam(Var, Box<Expr>, Box<Expr>),
  // "forall"
  Pi(Var, Box<Expr>, Box<Expr>),
  // Function application
  App(Box<Expr>, Box<Expr>),
}

impl Expr {
  pub fn constant(constant: Const) -> Expr {
    Expr::Const(constant)
  }
  pub fn var(v: &Var) -> Expr {
    Expr::Var(v.clone())
  }
  pub fn lam(var: Var, ty: Expr, body: Expr) -> Expr {
    Expr::Lam(var, Box::new(ty), Box::new(body))
  }
  pub fn pi(var: Var, ty: Expr, body: Expr) -> Expr {
    Expr::Pi(var, Box::new(ty), Box::new(body))
  }
  pub fn app(f: Expr, arg: Expr) -> Expr {
    Expr::App(Box::new(f), Box::new(arg))
  }
}

impl ToString for Expr {
  fn to_string(&self) -> String {
    use Expr::*;
    match self {
      &Const(ref constant) => constant.to_string(),
      &Var(ref var) => var.to_string(),
      &Lam(ref var, ref ty, ref body) => {
        var.to_string() + ":" + &ty.to_string() + " -> " + &body.to_string()
      }
      &Pi(ref var, ref ty, ref body) => {
        "forall (".to_string() + &var.to_string() + ":" + &ty.to_string() +
        ") -> " + &body.to_string()
      }
      &App(ref f, ref arg) => f.to_string() + " " + &arg.to_string(),
    }
  }
}

fn main() {
  println!("{}", Const::Data.to_string());
  println!("{:?}", Expr::constant(Const::Data));
  let a = Var::new("a", 0);
  let x = Var::new("x", 0);
  let expra = Expr::var(&a);
  let exprx = Expr::var(&x);
  println!("{}", x.to_string());
  let id = Expr::pi(a.clone(),
                    Expr::constant(Const::Data),
                    Expr::lam(x, expra, exprx));
  println!("{}", id.to_string());
}
<|endoftext|>


<commit_before>use std::rand;

enum Suit {
    Clubs,
    Diamonds,
    Spades,
    Hearts
}

impl Suit {
    fn to_string(&self) -> String {
        let x = match *self {
            Clubs => "Clubs",
            Diamonds => "Diamonds",
            Spades => "Spades",
            Hearts => "Hearts"
        };

        x.to_string()
    }
}

enum Rank {
    Ace,
    Two,
    Three,
    Four,
    Five,
    Six,
    Seven,
    Eight,
    Nine,
    Ten,
    Jack,
    Queen,
    King
}

impl Rank {
    fn to_string(&self) -> String {
        let x = match *self {
            Ace => "Ace",
            Two => "2",
            Three => "3",
            Four => "4",
            Five => "5",
            Six => "6",
            Seven => "7",
            Eight => "8",
            Nine => "9",
            Ten => "10",
            Jack => "Jack",
            Queen => "Queen",
            King => "King"
        };

        x.to_string()
    }
}

enum Card {
    Regular(Suit, Rank),
    Joker,
    Blank
}

impl Card {
    fn to_string(&self) -> String {
        match *self {
            Regular(suit, rank) => rank.to_string() + " of " + suit.to_string(),
            Joker => "Joker".to_string(),
            Blank => "Blank Card".to_string()
        }
    }

    fn print(&self) {
        println!("{}", self.to_string());
    }
}

impl Clone for Card {
    fn clone(&self) -> Card {
        match *self {
            Regular(suit, rank) => Regular(suit, rank),
            Joker => Joker,
            Blank => Blank
        }
    }
}

fn main() {
    let mut deck: Vec<Card> = create_deck();
    shuffle_deck(&mut deck);
    for card in deck.iter() {
        card.print();
    }
}

fn shuffle_deck(deck: &mut Vec<Card>) {
    for _x in range(0u, 1000u) {
        //Generate index
        let index = random_in_range(0u, deck.len() - 1);
        //Move to end
        match (*deck).swap_remove(index) {
            Some(card) => deck.push(card),
            None => println!("Something is wrong with our deck!")
        }
    }
}

fn random_in_range(x: uint, y: uint) -> uint{ //Inclusive
    let diff = y - x;
    (rand::random::<uint>() % (diff + 1)) + x
}

fn create_deck() -> Vec<Card> {
    let mut deck: Vec<Card> = Vec::new();

    let suit_array = [
        Clubs,
        Diamonds,
        Spades,
        Hearts
    ];

    let rank_array = [
        Two,
        Three,
        Four,
        Five,
        Six,
        Seven,
        Eight,
        Nine,
        Ten,
        Jack,
        Queen,
        King,
        Ace
    ];

    for suit in suit_array.iter() {
        for rank in rank_array.iter() {
            deck.push(Regular(*suit, *rank));
        }
    }

    deck
}<commit_msg>Implemented fmt::Show for Rank, Suit, and Card.<commit_after>use std::rand;
use std::fmt;

enum Suit {
    Clubs,
    Diamonds,
    Spades,
    Hearts
}

impl fmt::Show for Suit {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Clubs => write!(f, "Clubs"),
            Diamonds => write!(f, "Diamonds"),
            Spades => write!(f, "Spades"),
            Hearts => write!(f, "Hearts")
        }
    }
}

enum Rank {
    Ace,
    Two,
    Three,
    Four,
    Five,
    Six,
    Seven,
    Eight,
    Nine,
    Ten,
    Jack,
    Queen,
    King
}

impl fmt::Show for Rank {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Ace => write!(f, "Ace"),
            Two => write!(f, "2"),
            Three => write!(f, "3"),
            Four => write!(f, "4"),
            Five => write!(f, "5"),
            Six => write!(f, "6"),
            Seven => write!(f, "7"),
            Eight => write!(f, "8"),
            Nine => write!(f, "9"),
            Ten => write!(f, "10"),
            Jack => write!(f, "Jack"),
            Queen => write!(f, "Queen"),
            King => write!(f, "King")
        }
    }
}

enum Card {
    Regular(Suit, Rank),
    Joker,
    Blank
}

impl fmt::Show for Card {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Regular(suit, rank) => write!(f, "{} of {}", rank, suit),
            Joker => write!(f, "Joker"),
            Blank => write!(f, "Blank Card")
        }
    }
}

impl Clone for Card {
    fn clone(&self) -> Card {
        match *self {
            Regular(suit, rank) => Regular(suit, rank),
            Joker => Joker,
            Blank => Blank
        }
    }
}

fn main() {
    let mut deck: Vec<Card> = create_deck();
    shuffle_deck(&mut deck);
    for card in deck.iter() {
        println!("{}", card);
    }
}

fn shuffle_deck(deck: &mut Vec<Card>) {
    for _x in range(0u, 1000u) {
        //Generate index
        let index = random_in_range(0u, deck.len() - 1);
        //Move to end
        match (*deck).swap_remove(index) {
            Some(card) => deck.push(card),
            None => println!("Something is wrong with our deck!")
        }
    }
}

fn random_in_range(x: uint, y: uint) -> uint{ //Inclusive
    let diff = y - x;
    (rand::random::<uint>() % (diff + 1)) + x
}

fn create_deck() -> Vec<Card> {
    let mut deck: Vec<Card> = Vec::new();

    let suit_array = [
        Clubs,
        Diamonds,
        Spades,
        Hearts
    ];

    let rank_array = [
        Two,
        Three,
        Four,
        Five,
        Six,
        Seven,
        Eight,
        Nine,
        Ten,
        Jack,
        Queen,
        King,
        Ace
    ];

    for suit in suit_array.iter() {
        for rank in rank_array.iter() {
            deck.push(Regular(*suit, *rank));
        }
    }

    deck
}<|endoftext|>


<commit_before>extern crate walkdir;
extern crate regex;
extern crate getopts;

use std::env;
use std::path::Path;
use std::io::Write;
use std::process;
use std::error::Error;

use walkdir::{WalkDir, DirEntry, WalkDirIterator};
use regex::{Regex, RegexBuilder};
use getopts::Options;

/// Check if filename of entry starts with a dot.
fn is_hidden(entry: &DirEntry) -> bool {
    entry.file_name()
         .to_str()
         .map(|s| s.starts_with("."))
         .unwrap_or(false)
}

/// Recursively scan the given root path and search for pathnames matching the
/// pattern.
fn scan(root: &Path, pattern: &Regex) {
    let walker = WalkDir::new(root).into_iter();
    for entry in walker.filter_entry(|e| !is_hidden(e))
                       .filter_map(|e| e.ok()) {
        if entry.path() == root {
            continue;
        }

        let path_relative = entry.path().strip_prefix(root).unwrap();
        let path_str = match path_relative.to_str() {
            Some(s) => s,
            None => continue
        };
        match pattern.find(path_str) {
            Some(_) =>
                println!("{}", path_str),
            None =>
                continue
        }
    }
}

/// Print error message to stderr and exit with status `1`.
fn error<T: Error>(err: &T) -> ! {
    writeln!(&mut std::io::stderr(), "{}", err.description())
        .expect("Failed writing to stderr");
    process::exit(1);
}

fn main() {
    let args: Vec<String> = env::args().collect();

    let mut opts = Options::new();
    opts.optflag("h", "help", "print this help message");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { error(&f) }
    };

    if matches.opt_present("h") {
        let brief = "Usage: fd [PATTERN]";
        print!("{}", opts.usage(&brief));
        process::exit(1);
    }

    let empty = String::new();
    let pattern = matches.free.get(0).unwrap_or(&empty);

    let current_dir_buf = env::current_dir()
            .expect("Could not get current directory!");
    let current_dir = current_dir_buf.as_path();

    match
        RegexBuilder::new(pattern)
            .case_insensitive(true)
            .build() {
        Ok(re) =>
            scan(current_dir, &re),
        Err(err) => error(&err)
    }
}
<commit_msg>Add case-sensitive flag, closes #9<commit_after>extern crate walkdir;
extern crate regex;
extern crate getopts;

use std::env;
use std::path::Path;
use std::io::Write;
use std::process;
use std::error::Error;

use walkdir::{WalkDir, DirEntry, WalkDirIterator};
use regex::{Regex, RegexBuilder};
use getopts::Options;

/// Check if filename of entry starts with a dot.
fn is_hidden(entry: &DirEntry) -> bool {
    entry.file_name()
         .to_str()
         .map(|s| s.starts_with("."))
         .unwrap_or(false)
}

/// Recursively scan the given root path and search for pathnames matching the
/// pattern.
fn scan(root: &Path, pattern: &Regex) {
    let walker = WalkDir::new(root).into_iter();
    for entry in walker.filter_entry(|e| !is_hidden(e))
                       .filter_map(|e| e.ok()) {
        if entry.path() == root {
            continue;
        }

        let path_relative = entry.path().strip_prefix(root).unwrap();
        let path_str = match path_relative.to_str() {
            Some(s) => s,
            None => continue
        };
        match pattern.find(path_str) {
            Some(_) =>
                println!("{}", path_str),
            None =>
                continue
        }
    }
}

/// Print error message to stderr and exit with status `1`.
fn error<T: Error>(err: &T) -> ! {
    writeln!(&mut std::io::stderr(), "{}", err.description())
        .expect("Failed writing to stderr");
    process::exit(1);
}

fn main() {
    let args: Vec<String> = env::args().collect();

    let mut opts = Options::new();
    opts.optflag("h", "help", "print this help message");
    opts.optflag("s", "sensitive", "case-sensitive search");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { error(&f) }
    };

    if matches.opt_present("h") {
        let brief = "Usage: fd [PATTERN]";
        print!("{}", opts.usage(&brief));
        process::exit(1);
    }

    let case_insensitive = !matches.opt_present("s");

    let empty = String::new();
    let pattern = matches.free.get(0).unwrap_or(&empty);

    let current_dir_buf = env::current_dir()
            .expect("Could not get current directory!");
    let current_dir = current_dir_buf.as_path();

    match
        RegexBuilder::new(pattern)
            .case_insensitive(case_insensitive)
            .build() {
        Ok(re) =>
            scan(current_dir, &re),
        Err(err) => error(&err)
    }
}
<|endoftext|>


<commit_before>extern crate getopts;

extern crate otp_cop;

use std::{env, thread};
use std::sync::{mpsc, Arc};

use otp_cop::service::{CreateServiceResult, ServiceFactory};

struct ParallelIter<T> {
    count: usize,
    pos: usize,
    rx: mpsc::Receiver<T>
}

impl<T> Iterator for ParallelIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        if self.pos < self.count {
            self.count += 1;
            return self.rx.recv().ok();
        } else {
            return None;
        }
    }
}

fn parallel<T, U, F1>(objs: Vec<T>, f1: F1) -> ParallelIter<U>
        where F1: 'static + Fn(T) -> U + Send + Sync, T: 'static + Send, U: 'static + Send {
    let (tx, rx) = mpsc::channel();
    let count = objs.len();
    let shared_f1 = Arc::new(f1);
    for o in objs {
        let f1 = shared_f1.clone();
        let tx = tx.clone();
        thread::spawn(move || {
            tx.send(f1(o)).unwrap();
        });
    }

    return ParallelIter{count: count, pos: 0, rx: rx};
}

fn main() {
    let service_factories = vec![
        Box::new(otp_cop::SlackServiceFactory) as Box<ServiceFactory>,
        Box::new(otp_cop::GithubServiceFactory) as Box<ServiceFactory>,
    ];

    let mut opts = getopts::Options::new();

    for factory in service_factories.iter() {
        factory.add_options(&mut opts);
    }

    let matches = match opts.parse(env::args().skip(1)) {
        Ok(matches) => matches,
        Err(e) => panic!(e.to_string()),
    };

    let mut services = vec![];

    for factory in service_factories.iter() {
        match factory.create_service(&matches) {
            CreateServiceResult::Service(s) => services.push(s),
            CreateServiceResult::MissingArguments(arg) => panic!(format!("Missing arguments: {:?}", arg)),
            CreateServiceResult::None => continue,
        }
    }

    if services.is_empty() {
        print!("{}", opts.usage("otp-cop: <args>"));
    }

    let count = services.len();
    for (i, result) in parallel(services, |service| service.get_users()).enumerate() {
        println!("{}", result.service_name);
        println!("{}", "=".chars().cycle().take(result.service_name.len()).collect::<String>());
        println!("");
        for user in result.users {
            let email = match user.email {
                Some(email) => format!(" ({})", email),
                None => "".to_string(),
            };
            let details = match user.details {
                Some(details) => format!(" -- {}", details),
                None => "".to_string(),
            };
            println!("@{}{}{}", user.name, email, details);
        }
        if i + 1 != count {
            println!("");
            println!("");
        }
    }
}
<commit_msg>include the number of items in the header<commit_after>extern crate getopts;

extern crate otp_cop;

use std::{env, thread};
use std::sync::{mpsc, Arc};

use otp_cop::service::{CreateServiceResult, ServiceFactory};

struct ParallelIter<T> {
    count: usize,
    pos: usize,
    rx: mpsc::Receiver<T>
}

impl<T> Iterator for ParallelIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        if self.pos < self.count {
            self.count += 1;
            return self.rx.recv().ok();
        } else {
            return None;
        }
    }
}

fn parallel<T, U, F1>(objs: Vec<T>, f1: F1) -> ParallelIter<U>
        where F1: 'static + Fn(T) -> U + Send + Sync, T: 'static + Send, U: 'static + Send {
    let (tx, rx) = mpsc::channel();
    let count = objs.len();
    let shared_f1 = Arc::new(f1);
    for o in objs {
        let f1 = shared_f1.clone();
        let tx = tx.clone();
        thread::spawn(move || {
            tx.send(f1(o)).unwrap();
        });
    }

    return ParallelIter{count: count, pos: 0, rx: rx};
}

fn main() {
    let service_factories = vec![
        Box::new(otp_cop::SlackServiceFactory) as Box<ServiceFactory>,
        Box::new(otp_cop::GithubServiceFactory) as Box<ServiceFactory>,
    ];

    let mut opts = getopts::Options::new();

    for factory in service_factories.iter() {
        factory.add_options(&mut opts);
    }

    let matches = match opts.parse(env::args().skip(1)) {
        Ok(matches) => matches,
        Err(e) => panic!(e.to_string()),
    };

    let mut services = vec![];

    for factory in service_factories.iter() {
        match factory.create_service(&matches) {
            CreateServiceResult::Service(s) => services.push(s),
            CreateServiceResult::MissingArguments(arg) => panic!(format!("Missing arguments: {:?}", arg)),
            CreateServiceResult::None => continue,
        }
    }

    if services.is_empty() {
        print!("{}", opts.usage("otp-cop: <args>"));
    }

    let count = services.len();
    for (i, result) in parallel(services, |service| service.get_users()).enumerate() {
        let header = format!("{} ({})", result.service_name, result.users.len());
        println!("{}", header);
        println!("{}", "=".chars().cycle().take(header.len()).collect::<String>());
        println!("");
        for user in result.users {
            let email = match user.email {
                Some(email) => format!(" ({})", email),
                None => "".to_string(),
            };
            let details = match user.details {
                Some(details) => format!(" -- {}", details),
                None => "".to_string(),
            };
            println!("@{}{}{}", user.name, email, details);
        }
        if i + 1 != count {
            println!("");
            println!("");
        }
    }
}
<|endoftext|>


<commit_before>#![feature(advanced_slice_patterns, slice_patterns, convert)]

extern crate argparse;
extern crate yaml;
extern crate term;
extern crate chrono;

use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;
use std::fmt;

use yaml::constructor::*;
use yaml::constructor::YamlStandardData::{YamlMapping, YamlString, YamlInteger};

use std::collections::{HashMap, HashSet};
use argparse::{ArgumentParser, List};
use chrono::*;

struct Season {
    num: isize,
    matches: Vec<Match>,
}

impl Season {
    fn new(num: isize, matches: Vec<Match>) -> Season {
        Season { num: num, matches: matches }
    }

    fn winrate(&self) -> f32 {
        let wins: Vec<&Match> = self.matches.iter()
            .filter(|m| m.result == MatchResult::Win).collect();

        let total   = self.matches.len() as f32;
        let winrate = (wins.len() as f32) / total * 100.0;

        winrate
    }

    fn deck(&self, name: &String, class: &String) -> Season  {
        let deck = lowercase(&format!("{} {}", name, class));

        let dms: Vec<Match> = self.matches.clone().into_iter()
            .filter(|m| lowercase(&m.deck) == deck).collect();

        Season::new(self.num, dms)
    }

    fn vs(&self) -> HashMap<String, (usize, f32)> {
        let mut wrates = HashMap::new();
        let mut opps = HashSet::new();

        let mut ms = self.matches.to_vec();
        ms.sort_by(|a, b| a.opponent.cmp(&b.opponent));

        for m in &ms {
            opps.insert(m.opponent.clone());
        }

        for o in opps {
            let dms: Vec<&Match> = self.matches.iter()
                .filter(|m| lowercase(&m.opponent) == lowercase(&o)).collect();

            let wins: Vec<&&Match> = dms.iter()
                .filter(|m| m.result == MatchResult::Win).collect();

            let total   = dms.len() as f32;
            let winrate = (wins.len() as f32) / total * 100.0;

            wrates.insert(o, (dms.len(), winrate,));
        }

        wrates
    }

    fn time(&self, ts: DateTime<Local>) -> Season {
        let dms: Vec<Match> = self.matches.clone().into_iter()
            .filter(|m| (m.datetime.day(), m.datetime.month()) == (ts.day(), ts.month())).collect();

        Season::new(self.num, dms)
    }
}

impl fmt::Display for Season {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "{}", format!("Season {}", self.num));

        for m in &self.matches {
            writeln!(f, "{}", m);
        }

        writeln!(f, "{}", "")
    }
}

#[derive(Debug, Clone)]
struct Match {
    id: isize,
    deck: String,
    opponent: String,
    result: MatchResult,
    kind: MatchType,
    datetime: DateTime<Local>,
}

impl Match {
    fn new(id: isize) -> Match {
        Match { id:        id,
                deck:      String::new(),
                opponent:  String::new(),
                result:    MatchResult::Win,
                kind:      MatchType::Casual,
                datetime:  Local::now() }
    }
}

impl fmt::Display for Match {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut t = term::stdout().unwrap();

        if self.result == MatchResult:: Win {
            t.fg(term::color::GREEN).unwrap();
        } else {
            t.fg(term::color::RED).unwrap();
        }

        write!(f, "{}",
            format!(" {}) {} vs {} \t\t{}",
                self.id, self.deck, self.opponent, self.kind));

        t.reset().unwrap();

        write!(f, "{}", "")
    }
}

#[derive(PartialEq, Eq, Debug, Clone)]
enum MatchResult {
    Win,
    Loss,
}

impl fmt::Display for MatchResult {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s = match self {
            &MatchResult::Win  => "Win",
            &MatchResult::Loss => "Loss",
        };

        write!(f, "{}", s)
    }
}

#[derive(Debug, Clone)]
enum MatchType {
    Ranked,
    Casual,
    Friendly,
}

impl fmt::Display for MatchType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s = match self {
            &MatchType::Ranked   => "Ranked",
            &MatchType::Casual   => "Casual",
            &MatchType::Friendly => "Friendly",
        };

        write!(f, "{}", s)
    }
}

fn parse_season(map: &Vec<(YamlStandardData, YamlStandardData)>) -> Result<Season, &'static str> {
    match map.as_slice() {
        [(YamlString(ref name), YamlMapping(ref map))] => {
            let mut matches: Vec<Match>  = Vec::new();

            for m in map.as_slice() {
                match m {
                    &(YamlInteger(ref id), YamlMapping(ref content)) =>
                        matches.push(parse_match(*id, content)),

                    _ => continue,
                }
            }

            let s_name = name.to_string();
            let temp: Vec<&str> = s_name.split(' ').collect();
            let season_num = temp[1].to_string().parse::<isize>().unwrap();

            Ok(Season::new(season_num, matches))
        },

        _ => Err("Error"),
    }
}

fn lowercase(s: &String) -> String {
    s.chars().map(|c| c.to_lowercase().next().unwrap()).collect::<String>()
}

fn capitalize(s: &String) -> String {
    s.chars().enumerate()
        .map(|(i, c)| if i == 0 {
                c.to_uppercase().next().unwrap()
            } else {
                c.to_lowercase().next().unwrap()
            }).collect::<String>()
}

fn parse_match(id: isize, map: &Vec<(YamlStandardData, YamlStandardData)>) -> Match {
    let mut m = Match::new(id);

    for e in map.as_slice() {
        match e {
            &(YamlString(ref key), YamlString(ref value)) =>
                match key.as_str() {
                    "deck"     => m.deck     = value.trim().to_string(),
                    "opponent" => m.opponent = value.trim().to_string(),
                    "result"   =>
                        match value.as_str() {
                            "Win"  => m.result = MatchResult::Win,
                            "Loss" => m.result = MatchResult::Loss,
                            _      => continue,
                        },
                    "type"     =>
                        match value.as_str() {
                            "Ranked"   => m.kind = MatchType::Ranked,
                            "Casual"   => m.kind = MatchType::Casual,
                            "Friendly" => m.kind = MatchType::Friendly,
                            _          => continue,
                        },
                    "datetime" =>
                        m.datetime = Local.datetime_from_str(value, "%Y-%m-%d %H:%M:%S").unwrap(),

                    _ => continue,
                },

            _ => continue
        }
    }

    m
}

fn parse(data: Vec<YamlStandardData>) -> Result<Vec<Season>, &'static str> {
    let mut seasons: Vec<Season> = Vec::new();

    for doc in data.iter() {
        match doc {
            &YamlMapping(ref map) =>
                seasons.push(parse_season(map).unwrap()),

            _ => return Err("No docs"),
        }
    }

    Ok(seasons)
}

fn main() {
    let path = "hearthstone.yaml";

    let mut args: Vec<String> = Vec::new();

    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Calc HS stats");
        ap.refer(&mut args)
            .add_argument("args", List,
                          "Deck to calc winrate for");
        ap.parse_args_or_exit();
    }

    let mut reader = BufReader::new(File::open(path).unwrap());
    let data = yaml::parse_io_utf8(&mut reader).unwrap();

    let seasons = parse(data).unwrap();

    if args.len() >= 1 {
        let season = seasons.last().unwrap();

        match args[0].as_str() {
            "deck" => {
                let deck   = &args[1..3];
                let name   = deck[0].to_string();
                let class  = deck[1].to_string();

                let data = season.deck(&name, &class);

                println!("Matches: ");

                for m in &data.matches {
                    println!("{}", m);
                }

                println!("\nMatches: {}", data.matches.len());
                println!("Winrate: {}%\n", data.winrate());

                let wrates = season.vs();

                for (k, v) in wrates {
                    println!("{}\t\t {}% {}", k, v.1, v.0);
                }
            },

            "show" => {
                print!("{}", season);
                println!("Total Winrate: {}%", season.winrate());
            },

            "today" => {
                let data = season.time(Local::now());

                println!("Matches: ");

                for m in &data.matches {

                    println!("{}", m);
                }

                println!("\nMatches: {}", data.matches.len());
                println!("Winrate: {}%\n", data.winrate());
            }

            "yesterday" => {
                let date = Local::now().checked_sub(Duration::days(1)).unwrap();
                let data = season.time(date);

                println!("Matches: ");

                for m in &data.matches {
                    println!("{}", m);
                }

                println!("\nMatches: {}", data.matches.len());
                println!("Winrate: {}%\n", data.winrate());
            }

            _ => println!("Command unknown"),
        }
    }
}
<commit_msg>moved show suff into display impl for season<commit_after>#![feature(advanced_slice_patterns, slice_patterns, convert)]

extern crate argparse;
extern crate yaml;
extern crate term;
extern crate chrono;

use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;
use std::fmt;

use yaml::constructor::*;
use yaml::constructor::YamlStandardData::{YamlMapping, YamlString, YamlInteger};

use std::collections::{HashMap, HashSet};
use argparse::{ArgumentParser, List};
use chrono::*;

struct Season {
    num: isize,
    matches: Vec<Match>,
}

impl Season {
    fn new(num: isize, matches: Vec<Match>) -> Season {
        Season { num: num, matches: matches }
    }

    fn winrate(&self) -> f32 {
        let wins: Vec<&Match> = self.matches.iter()
            .filter(|m| m.result == MatchResult::Win).collect();

        let total   = self.matches.len() as f32;
        let winrate = (wins.len() as f32) / total * 100.0;

        winrate
    }

    fn deck(&self, name: &String, class: &String) -> Season  {
        let deck = lowercase(&format!("{} {}", name, class));

        let dms: Vec<Match> = self.matches.clone().into_iter()
            .filter(|m| lowercase(&m.deck) == deck).collect();

        Season::new(self.num, dms)
    }

    fn vs(&self) -> HashMap<String, (usize, f32)> {
        let mut wrates = HashMap::new();
        let mut opps = HashSet::new();

        let mut ms = self.matches.to_vec();
        ms.sort_by(|a, b| a.opponent.cmp(&b.opponent));

        for m in &ms {
            opps.insert(m.opponent.clone());
        }

        for o in opps {
            let dms: Vec<&Match> = self.matches.iter()
                .filter(|m| lowercase(&m.opponent) == lowercase(&o)).collect();

            let wins: Vec<&&Match> = dms.iter()
                .filter(|m| m.result == MatchResult::Win).collect();

            let total   = dms.len() as f32;
            let winrate = (wins.len() as f32) / total * 100.0;

            wrates.insert(o, (dms.len(), winrate,));
        }

        wrates
    }

    fn time(&self, ts: DateTime<Local>) -> Season {
        let dms: Vec<Match> = self.matches.clone().into_iter()
            .filter(|m| (m.datetime.day(), m.datetime.month()) == (ts.day(), ts.month())).collect();

        Season::new(self.num, dms)
    }
}

impl fmt::Display for Season {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "{}", format!("Season {}", self.num));

        for m in &self.matches {
            writeln!(f, "{}", m);
        }

        writeln!(f, "\nMatches: {}", self.matches.len());
        writeln!(f, "Winrate: {}%", self.winrate())
    }
}

#[derive(Debug, Clone)]
struct Match {
    id: isize,
    deck: String,
    opponent: String,
    result: MatchResult,
    kind: MatchType,
    datetime: DateTime<Local>,
}

impl Match {
    fn new(id: isize) -> Match {
        Match { id:        id,
                deck:      String::new(),
                opponent:  String::new(),
                result:    MatchResult::Win,
                kind:      MatchType::Casual,
                datetime:  Local::now() }
    }
}

impl fmt::Display for Match {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut t = term::stdout().unwrap();

        if self.result == MatchResult:: Win {
            t.fg(term::color::GREEN).unwrap();
        } else {
            t.fg(term::color::RED).unwrap();
        }

        write!(f, "{}",
            format!(" {}) {} vs {} \t\t{}",
                self.id, self.deck, self.opponent, self.kind));

        t.reset().unwrap();

        write!(f, "{}", "")
    }
}

#[derive(PartialEq, Eq, Debug, Clone)]
enum MatchResult {
    Win,
    Loss,
}

impl fmt::Display for MatchResult {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s = match self {
            &MatchResult::Win  => "Win",
            &MatchResult::Loss => "Loss",
        };

        write!(f, "{}", s)
    }
}

#[derive(Debug, Clone)]
enum MatchType {
    Ranked,
    Casual,
    Friendly,
}

impl fmt::Display for MatchType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s = match self {
            &MatchType::Ranked   => "Ranked",
            &MatchType::Casual   => "Casual",
            &MatchType::Friendly => "Friendly",
        };

        write!(f, "{}", s)
    }
}

fn parse_season(map: &Vec<(YamlStandardData, YamlStandardData)>) -> Result<Season, &'static str> {
    match map.as_slice() {
        [(YamlString(ref name), YamlMapping(ref map))] => {
            let mut matches: Vec<Match>  = Vec::new();

            for m in map.as_slice() {
                match m {
                    &(YamlInteger(ref id), YamlMapping(ref content)) =>
                        matches.push(parse_match(*id, content)),

                    _ => continue,
                }
            }

            let s_name = name.to_string();
            let temp: Vec<&str> = s_name.split(' ').collect();
            let season_num = temp[1].to_string().parse::<isize>().unwrap();

            Ok(Season::new(season_num, matches))
        },

        _ => Err("Error"),
    }
}

fn lowercase(s: &String) -> String {
    s.chars().map(|c| c.to_lowercase().next().unwrap()).collect::<String>()
}

fn capitalize(s: &String) -> String {
    s.chars().enumerate()
        .map(|(i, c)| if i == 0 {
                c.to_uppercase().next().unwrap()
            } else {
                c.to_lowercase().next().unwrap()
            }).collect::<String>()
}

fn parse_match(id: isize, map: &Vec<(YamlStandardData, YamlStandardData)>) -> Match {
    let mut m = Match::new(id);

    for e in map.as_slice() {
        match e {
            &(YamlString(ref key), YamlString(ref value)) =>
                match key.as_str() {
                    "deck"     => m.deck     = value.trim().to_string(),
                    "opponent" => m.opponent = value.trim().to_string(),
                    "result"   =>
                        match value.as_str() {
                            "Win"  => m.result = MatchResult::Win,
                            "Loss" => m.result = MatchResult::Loss,
                            _      => continue,
                        },
                    "type"     =>
                        match value.as_str() {
                            "Ranked"   => m.kind = MatchType::Ranked,
                            "Casual"   => m.kind = MatchType::Casual,
                            "Friendly" => m.kind = MatchType::Friendly,
                            _          => continue,
                        },
                    "datetime" =>
                        m.datetime = Local.datetime_from_str(value, "%Y-%m-%d %H:%M:%S").unwrap(),

                    _ => continue,
                },

            _ => continue
        }
    }

    m
}

fn parse(data: Vec<YamlStandardData>) -> Result<Vec<Season>, &'static str> {
    let mut seasons: Vec<Season> = Vec::new();

    for doc in data.iter() {
        match doc {
            &YamlMapping(ref map) =>
                seasons.push(parse_season(map).unwrap()),

            _ => return Err("No docs"),
        }
    }

    Ok(seasons)
}

fn main() {
    let path = "hearthstone.yaml";

    let mut args: Vec<String> = Vec::new();

    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Calc HS stats");
        ap.refer(&mut args)
            .add_argument("args", List,
                          "Deck to calc winrate for");
        ap.parse_args_or_exit();
    }

    let mut reader = BufReader::new(File::open(path).unwrap());
    let data = yaml::parse_io_utf8(&mut reader).unwrap();

    let seasons = parse(data).unwrap();

    if args.len() >= 1 {
        let season = seasons.last().unwrap();

        match args[0].as_str() {
            "deck" => {
                let deck   = &args[1..3];
                let name   = deck[0].to_string();
                let class  = deck[1].to_string();

                let data = season.deck(&name, &class);

                println!("{}", data);

                let wrates = season.vs();

                for (k, v) in wrates {
                    println!("{}\t\t {}% {}", k, v.1, v.0);
                }
            },

            "show" => {
                print!("{}", season);
                println!("Total Winrate: {}%", season.winrate());
            },

            "today" => {
                let data = season.time(Local::now());

                println!("{}", data);
            }

            "yesterday" => {
                let date = Local::now().checked_sub(Duration::days(1)).unwrap();
                let data = season.time(date);

                println!("{}", data);
            }

            _ => println!("Command unknown"),
        }
    }
}
<|endoftext|>


<commit_before>#![feature(slicing_syntax, macro_rules)]
#![feature(overloaded_calls)]

extern crate http;
extern crate url;
extern crate serialize;

use std::os;
use std::str;
use std::sync::{Arc, Mutex};
use std::io::net::ip::{SocketAddr, Ipv4Addr};
use std::collections::HashMap;

use http::method::{Get, Post};
use http::server::{Config, Server, Request, ResponseWriter};
use http::server::request::{AbsolutePath};

use serialize::json;

use incoming::{SlackPayload};
use outgoing::{SlackEndpoint, OutgoingWebhook};

mod incoming;
mod outgoing;

type Scores = HashMap<String, i32>;

#[deriving(Send,Clone)]
struct KarmaServer {
    scores: Arc<Mutex<Scores>>,
    endpoint: String,
}

impl KarmaServer {
    fn new(scores: Scores, endpoint: String) -> KarmaServer {
        KarmaServer {
            scores: Arc::new(Mutex::new(scores)),
            endpoint: endpoint
        }
    }
}

fn handle_karma(req: Vec<u8>, points: &mut Scores, cb: |&&str, &i32, &&str|) {
    let payload = match SlackPayload::from_body(req.as_slice()) {
        Ok(payload) => payload,
        Err(err) => {
            println!("Error! {}", err); return
        }
    };

    let op = match payload.command {
        "%2F%2B%2B" => |c: i32| c + 1,
        "%2F++" => |c: i32| c + 1,
        "%2F%2D%2D" => |c: i32| c - 1,
        "%2F--" => |c: i32| c - 1,
        _ => return,
    };

    let mut matches = payload.text.splitn(1, ' ');
    let target = match (matches.next(), matches.next()) {
        (None, None) => return, // No message or user
        (Some(user), None) => user, // user, no message
        (Some(user), Some(_)) => user, // TODO deal with the message
        (None, Some(_)) => unreachable!(),
    };

    let current = points.insert(target.to_string(), 0).unwrap_or(0);
    points.insert(target.to_string(), op(current));

    cb(&target, &op(current), &payload.channel_name);
}

impl Server for KarmaServer {
    fn get_config(&self) -> Config {
        match os::getenv("PORT") {
            None => panic!("Must specify PORT"),
            Some(port) => {
                let port = from_str::<u16>(port.as_slice()).expect("PORT must be an int");
                Config { bind_address: SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: port } }
            }
        }
    }

    #[allow(unused_must_use)]
    fn handle_request(&self, r: Request, w: &mut ResponseWriter) {
        let path = match r.request_uri { AbsolutePath(ref path) => path[], _ => return };

        println!("{}: {}", r.method, path);

        match (&r.method, path) {
            (&Get, "/") => {
                w.write(b"Hello world!");
            },
            (&Get, "/karma") => {
                let scores = (*self.scores).lock();
                let json = json::encode(&*scores);
                w.write(json.as_bytes());
            }
            (&Post, "/normalise") => {
                let mut scores = (*self.scores).lock();
                for (_, v) in scores.iter_mut() {
                    let new = *v as f64;
                    *v = new.sqrt() as i32;
                }
            }
            (&Post, "/slack") => {
                let mut scores = (*self.scores).lock();
                let slack = self.get_slack_endpoint();
                handle_karma(r.body, &mut *scores, |u, s, c| {
                    let msg = format!("{} now at {}", u, s);
                    let channel = format!("#{}", c);
                    let payload = OutgoingWebhook {
                        text: msg.as_slice(),
                        channel: channel.as_slice(),
                        username: "karmabot",
                        icon_emoji: Some(":ghost:"),
                    };

                    slack.send(&payload);
                });
            },
            (_, _) => {
                w.write(b"Not found :(");
            }
        }
    }
}

impl KarmaServer {
    fn get_slack_endpoint(&self) -> SlackEndpoint {
        return SlackEndpoint {
            url: self.endpoint.clone()
        }
    }
}

fn main() {
    let endpoint = match os::getenv("WEBHOOK_ENDPOINT") {
        Some(e) => e,
        None => panic!("Must set WEBHOOK_ENDPOINT"),
    };
    let server = KarmaServer::new(HashMap::new(), endpoint);
    server.serve_forever();
}
<commit_msg>Remove superfluous import<commit_after>#![feature(slicing_syntax, macro_rules)]
#![feature(overloaded_calls)]

extern crate http;
extern crate url;
extern crate serialize;

use std::os;
use std::sync::{Arc, Mutex};
use std::io::net::ip::{SocketAddr, Ipv4Addr};
use std::collections::HashMap;

use http::method::{Get, Post};
use http::server::{Config, Server, Request, ResponseWriter};
use http::server::request::{AbsolutePath};

use serialize::json;

use incoming::{SlackPayload};
use outgoing::{SlackEndpoint, OutgoingWebhook};

mod incoming;
mod outgoing;

type Scores = HashMap<String, i32>;

#[deriving(Send,Clone)]
struct KarmaServer {
    scores: Arc<Mutex<Scores>>,
    endpoint: String,
}

impl KarmaServer {
    fn new(scores: Scores, endpoint: String) -> KarmaServer {
        KarmaServer {
            scores: Arc::new(Mutex::new(scores)),
            endpoint: endpoint
        }
    }
}

fn handle_karma(req: Vec<u8>, points: &mut Scores, cb: |&&str, &i32, &&str|) {
    let payload = match SlackPayload::from_body(req.as_slice()) {
        Ok(payload) => payload,
        Err(err) => {
            println!("Error! {}", err); return
        }
    };

    let op = match payload.command {
        "%2F%2B%2B" => |c: i32| c + 1,
        "%2F++" => |c: i32| c + 1,
        "%2F%2D%2D" => |c: i32| c - 1,
        "%2F--" => |c: i32| c - 1,
        _ => return,
    };

    let mut matches = payload.text.splitn(1, ' ');
    let target = match (matches.next(), matches.next()) {
        (None, None) => return, // No message or user
        (Some(user), None) => user, // user, no message
        (Some(user), Some(_)) => user, // TODO deal with the message
        (None, Some(_)) => unreachable!(),
    };

    let current = points.insert(target.to_string(), 0).unwrap_or(0);
    points.insert(target.to_string(), op(current));

    cb(&target, &op(current), &payload.channel_name);
}

impl Server for KarmaServer {
    fn get_config(&self) -> Config {
        match os::getenv("PORT") {
            None => panic!("Must specify PORT"),
            Some(port) => {
                let port = from_str::<u16>(port.as_slice()).expect("PORT must be an int");
                Config { bind_address: SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: port } }
            }
        }
    }

    #[allow(unused_must_use)]
    fn handle_request(&self, r: Request, w: &mut ResponseWriter) {
        let path = match r.request_uri { AbsolutePath(ref path) => path[], _ => return };

        println!("{}: {}", r.method, path);

        match (&r.method, path) {
            (&Get, "/") => {
                w.write(b"Hello world!");
            },
            (&Get, "/karma") => {
                let scores = (*self.scores).lock();
                let json = json::encode(&*scores);
                w.write(json.as_bytes());
            }
            (&Post, "/normalise") => {
                let mut scores = (*self.scores).lock();
                for (_, v) in scores.iter_mut() {
                    let new = *v as f64;
                    *v = new.sqrt() as i32;
                }
            }
            (&Post, "/slack") => {
                let mut scores = (*self.scores).lock();
                let slack = self.get_slack_endpoint();
                handle_karma(r.body, &mut *scores, |u, s, c| {
                    let msg = format!("{} now at {}", u, s);
                    let channel = format!("#{}", c);
                    let payload = OutgoingWebhook {
                        text: msg.as_slice(),
                        channel: channel.as_slice(),
                        username: "karmabot",
                        icon_emoji: Some(":ghost:"),
                    };

                    slack.send(&payload);
                });
            },
            (_, _) => {
                w.write(b"Not found :(");
            }
        }
    }
}

impl KarmaServer {
    fn get_slack_endpoint(&self) -> SlackEndpoint {
        return SlackEndpoint {
            url: self.endpoint.clone()
        }
    }
}

fn main() {
    let endpoint = match os::getenv("WEBHOOK_ENDPOINT") {
        Some(e) => e,
        None => panic!("Must set WEBHOOK_ENDPOINT"),
    };
    let server = KarmaServer::new(HashMap::new(), endpoint);
    server.serve_forever();
}
<|endoftext|>


<commit_before>use std::io;
use std::io::prelude::*;
use std::iter::repeat;
use std::str::FromStr;

fn main() {
    let title = "RUSTYHAM: A HAMMING CODE GENERATOR IN RUST";
    let border: String = repeat('=').take(title.len()).collect::<>();
    println!("{}", border);
    println!("{}", title);
    println!("{}", border);

    loop {
        let mut linebuf: String = String::new();
        println!("(1) Encode ASCII");
        println!("(2) Encode binary");
        println!("(3) Decode to ASCII");
        println!("(4) Decode to binary");
        print!("Enter your choice: ");
        io::stdout().flush();
        io::stdin().read_line(&mut linebuf);

        let num = i32::from_str(linebuf.trim());
        match num.ok() {
            Some(n) => {
                let mut good = true;
                println!("{}", match n {
                    1 => hamming(),
                    2...4 => "Sorry, not implemented yet.",
                    _ => { good = false; "Invalid input." }
                });
                if good { break; }
            }
            None => {
                println!("Invalid input.");
            }
        };
    }
}

fn hamming() -> &'static str {
    "STOP - HAMMINGTIME!"
}
<commit_msg>block length computation<commit_after>use std::io;
use std::io::prelude::*;
use std::iter::repeat;
use std::str::FromStr;
use std::num::Int;
use std::num::ToPrimitive;

fn main() {
    let title = "RUSTYHAM: A HAMMING CODE GENERATOR IN RUST";
    let border: String = repeat('=').take(title.len()).collect::<>();
    println!("{}", border);
    println!("{}", title);
    println!("{}", border);

    loop {
        let mut linebuf = String::new();
        println!("(1) Encode ASCII");
        println!("(2) Encode binary");
        println!("(3) Decode to ASCII");
        println!("(4) Decode to binary");
        print!("Enter your choice: ");
        io::stdout().flush();
        io::stdin().read_line(&mut linebuf);

        let num = i32::from_str(linebuf.trim());
        match num.ok() {
            Some(n) => {
                let mut good = true;
                println!("{}", match n {
                    1 => hamming(),
                    2...4 => "Sorry, not implemented yet.".to_string(),
                    _ => { good = false; "Invalid input.".to_string() }
                });
                if good { break; }
            }
            None => {
                println!("Invalid input.");
            }
        };
    }
}

fn hamming() -> String {
    let mut message = String::new();
    print!("Enter string to encode: ");
    io::stdout().flush();
    io::stdin().read_line(&mut message);

    message = message.trim().to_string();
    let mlen = message.len().to_u32().unwrap();
    let len = 2.pow((2..).find(|&r| 2.pow(r) - r - 1 >= mlen).unwrap()) - 1;

    message
}
<|endoftext|>