<commit_before>
use clap::{SubCommand, App, Arg, ArgMatches};

use std::path::Path;
use std::fs;
use std::marker::PhantomData;
use std::collections::BTreeMap;
use std::net::SocketAddr;
use std::error::Error;

use config::ConfigFile;
use blockchain::{ConsensusConfig, GenesisConfig};
use node::NodeConfig;
use storage::Storage;
use crypto::{self, PublicKey, SecretKey};
use super::generate_testnet_config;

const DEFAULT_EXONUM_LISTEN_PORT: u16 = 6333;

#[derive(Debug)]
pub struct RunCommand<'a, 'b>
    where 'a: 'b
{
    _p: PhantomData<App<'a, 'b>>,
}

impl<'a, 'b> RunCommand<'a, 'b>
    where 'a: 'b
{
    pub fn new() -> App<'a, 'b> {
        SubCommand::with_name("run")
            .about("Run node with given configuration")
            .arg(Arg::with_name("NODE_CONFIG_PATH")
                     .short("c")
                     .long("node-config")
                     .value_name("NODE_CONFIG_PATH")
                     .help("Path to node configuration file")
                     .required(true)
                     .takes_value(true))
            .arg(Arg::with_name("LEVELDB_PATH")
                     .short("d")
                     .long("leveldb-path")
                     .value_name("LEVELDB_PATH")
                     .help("Use leveldb database with the given path")
                     .required(false)
                     .takes_value(true))
            .arg(Arg::with_name("PUBLIC_API_ADDRESS")
                     .long("public-api-address")
                     .help("Listen address for public api")
                     .required(false)
                     .takes_value(true))
            .arg(Arg::with_name("PRIVATE_API_ADDRESS")
                     .long("private-api-address")
                     .help("Listen address for private api")
                     .required(false)
                     .takes_value(true))
    }

    pub fn node_config_path(matches: &'a ArgMatches<'a>) -> &'a Path {
        matches
            .value_of("NODE_CONFIG_PATH")
            .map(Path::new)
            .expect("Path to node configuration is no setted")
    }

    pub fn node_config(matches: &'a ArgMatches<'a>) -> NodeConfig {
        let path = Self::node_config_path(matches);
        let mut cfg: NodeConfig = ConfigFile::load(path).unwrap();
        // Override api options
        if let Some(addr) = Self::public_api_address(matches) {
            cfg.api.public_api_address = Some(addr);
        }
        if let Some(addr) = Self::private_api_address(matches) {
            cfg.api.private_api_address = Some(addr);
        }
        cfg
    }

    pub fn public_api_address(matches: &'a ArgMatches<'a>) -> Option<SocketAddr> {
        matches
            .value_of("PUBLIC_API_ADDRESS")
            .map(|s| {
                     s.parse()
                         .expect("Public api address has incorrect format")
                 })
    }

    pub fn private_api_address(matches: &'a ArgMatches<'a>) -> Option<SocketAddr> {
        matches
            .value_of("PRIVATE_API_ADDRESS")
            .map(|s| {
                     s.parse()
                         .expect("Private api address has incorrect format")
                 })
    }

    pub fn leveldb_path(matches: &'a ArgMatches<'a>) -> Option<&'a Path> {
        matches.value_of("LEVELDB_PATH").map(Path::new)
    }

    #[cfg(not(feature="memorydb"))]
    pub fn db(matches: &'a ArgMatches<'a>) -> Box<Database> {
        use storage::{LevelDB, LevelDBOptions};

        let path = Self::leveldb_path(matches).unwrap();
        let mut options = LevelDBOptions::new();
        options.create_if_missing = true;
        Box::new(LevelDB::open(path, options).unwrap())
    }

    #[cfg(feature="memorydb")]
    pub fn db(_: &'a ArgMatches<'a>) -> Box<Database> {
        use storage::MemoryDB;
        Box::new(MemoryDB::new())
    }
}

#[derive(Serialize, Deserialize)]
pub struct ValidatorIdent {
    pub values: BTreeMap<String, String>,
    addr: SocketAddr,
}

#[derive(Serialize, Deserialize, Default)]
pub struct ConfigTemplate {
    validators: BTreeMap<PublicKey, ValidatorIdent>,
    consensus_cfg: ConsensusConfig,
    count: usize,
    services: BTreeMap<String, String>,
}

// toml file could not save array without "field name"
#[derive(Serialize, Deserialize)]
struct PubKeyConfig {
    public_key: PublicKey,
}

impl ::std::convert::From<PublicKey> for PubKeyConfig {
    fn from(pk: PublicKey) -> Self {
        PubKeyConfig {
            public_key: pk
        }
    }
}

impl ::std::convert::Into<PublicKey> for PubKeyConfig {
    fn into(self) -> PublicKey {
        self.public_key
    }
}

#[derive(Serialize, Deserialize)]
pub struct KeyConfig {
    public_key: PublicKey,
    secret_key: SecretKey,
}

pub struct KeyGeneratorCommand;

impl KeyGeneratorCommand {
    /// Creates basic keygen subcommand.
    pub fn new<'a>() -> App<'a, 'a> {
        SubCommand::with_name("keygen")
            .about("Generate basic node secret key.")
            .arg(Arg::with_name("KEYCHAIN")
                     .help("Path to key config.")
                     .required(true)
                     .index(1))
    }

    /// Path where keychain config should be saved
    pub fn keychain<'a>(matches: &'a ArgMatches<'a>) -> &'a Path {
        Path::new(matches.value_of("KEYCHAIN").unwrap())
    }

    /// Generates and writes key config to `keychain()` path.
    pub fn execute(matches: &ArgMatches) {
        let (pub_key, sec_key) = crypto::gen_keypair();
        let keyconfig = Self::keychain(matches);
        let pub_key_path = keyconfig.with_extension("pub");
        let pub_key_config: PubKeyConfig = pub_key.into();
        // save pub_key seperately
        ConfigFile::save(&pub_key_config, &pub_key_path)
                    .expect("Could not write public key file.");

        let config = KeyConfig {
            public_key: pub_key,
            secret_key: sec_key,
        };

        ConfigFile::save(&config, Self::keychain(matches))
                    .expect("Could not write keychain file.");
    }
}

/// implements command for template generating
pub struct GenerateTemplateCommand;
impl GenerateTemplateCommand {
    pub fn new<'a>() -> App<'a, 'a> {
        SubCommand::with_name("generate-template")
            .about("Generate basic template.")
            .arg(Arg::with_name("COUNT")
                     .help("Validator total count.")
                     .required(true)
                     .index(1))
            .arg(Arg::with_name("TEMPLATE")
                     .help("Path to template config.")
                     .required(true)
                     .index(2))
    }

    /// Path where template config should be saved
    pub fn template<'a>(matches: &'a ArgMatches<'a>) -> &'a Path {
        Path::new(matches.value_of("TEMPLATE").unwrap())
    }
    /// Validator total count
    pub fn count(matches: &ArgMatches) -> usize {
        matches.value_of("COUNT").unwrap().parse().unwrap()
    }

    /// Write default template config into `template()` path.
    pub fn execute<T>(matches: &ArgMatches, values: T)
        where T: Into<Option<BTreeMap<String, String>>>
    {
        let values = values.into().unwrap_or_default();
        let template = ConfigTemplate {
            count: Self::count(matches),
            services: values,
            ..ConfigTemplate::default()
        };

        ConfigFile::save(&template, Self::template(matches))
                        .expect("Could not write template file.");
    }
}

pub struct AddValidatorCommand;
impl AddValidatorCommand {
    pub fn new<'a>() -> App<'a, 'a> {
        SubCommand::with_name("add-validator")
            .about("Preinit configuration, add validator to config template.")
            .arg(Arg::with_name("TEMPLATE")
                     .help("Path to template")
                     .required(true)
                     .index(1))
            .arg(Arg::with_name("PUBLIC_KEY")
                     .help("Path to public key file.")
                     .required(true)
                     .index(2))
            .arg(Arg::with_name("LISTEN_ADDR")
                     .short("a")
                     .long("listen-addr")
                     .value_name("LISTEN_ADDR")
                     .required(true)
                     .takes_value(true))
            .arg(Arg::with_name("PORT")
                     .short("p")
                     .long("port")
                     .value_name("PORT")
                     .required(false)
                     .takes_value(true))

    }

    /// path to public_key file
    pub fn public_key<'a>(matches: &'a ArgMatches<'a>) -> &'a Path {
        Path::new(matches.value_of("PUBLIC_KEY").unwrap())
    }

    /// path to template config
    pub fn template<'a>(matches: &'a ArgMatches<'a>) -> &'a Path {
        Path::new(matches.value_of("TEMPLATE").unwrap())
    }

    // exonum listen port
    pub fn port(matches: &ArgMatches) -> Option<u16> {
        matches
            .value_of("PORT")
            .and_then(|port| port.parse().ok())
    }

    // exonum listen addr
    pub fn addr(matches: &ArgMatches) -> String {
        matches.value_of("LISTEN_ADDR").unwrap().to_string()
    }

    #[cfg_attr(feature="cargo-clippy", allow(map_entry))]
    pub fn execute<'a, F>(matches: &ArgMatches, on_add: F)
        where F: Into<Option<&'a Fn(usize, &mut BTreeMap<String, String>)
                        -> Result<BTreeMap<String, String>, Box<Error>>>>,
    {
        let template_path = Self::template(matches);
        let public_key_path = Self::public_key(matches);

        let mut template: ConfigTemplate = ConfigFile::load(template_path).unwrap();
        let public_key: PubKeyConfig = ConfigFile::load(public_key_path).unwrap();
        let public_key = public_key.into();
        let addr = format!("{}:{}",
                           Self::addr(matches),
                           Self::port(matches).unwrap_or(DEFAULT_EXONUM_LISTEN_PORT))
                .parse()
                .unwrap();
        if !template.validators.contains_key(&public_key) {
            if template.validators.len() >= template.count {
                panic!("This template alredy full.");
            }
            let func = on_add
                .into()
                .map(|f| f(template.count, &mut template.services));
            let map = func.unwrap_or_else(|| Ok(BTreeMap::new()));

            let ident = ValidatorIdent {
                addr: addr,
                values: map.unwrap(),
            };
            template.validators.insert(public_key, ident);
        } else {
            panic!("This node alredy in template");
        }

        ConfigFile::save(&template, template_path).unwrap();
    }
}

pub struct InitCommand;

impl InitCommand {
    pub fn new<'a>() -> App<'a, 'a> {
        SubCommand::with_name("init")
            .about("Toolchain to generate configuration")
            .arg(Arg::with_name("FULL_TEMPLATE")
                     .help("Path to full template")
                     .required(true)
                     .index(1))
            .arg(Arg::with_name("KEYCHAIN")
                     .help("Path to keychain config.")
                     .required(true)
                     .index(2))
            .arg(Arg::with_name("CONFIG_PATH")
                     .help("Path to node config.")
                     .required(true)
                     .index(3))

    }

    /// path to full template config
    pub fn template<'a>(matches: &'a ArgMatches<'a>) -> &'a Path {
        Path::new(matches.value_of("FULL_TEMPLATE").unwrap())
    }

    /// path to output config
    pub fn config<'a>(matches: &'a ArgMatches<'a>) -> &'a Path {
        Path::new(matches.value_of("CONFIG_PATH").unwrap())
    }

    /// path to keychain (public and secret keys)
    pub fn keychain<'a>(matches: &'a ArgMatches<'a>) -> &'a Path {
        Path::new(matches.value_of("KEYCHAIN").unwrap())
    }

    pub fn execute<'a, F>(matches: &ArgMatches, on_init: F)
        where F: Into<Option<&'a Fn(&BTreeMap<String, String>,
                        &BTreeMap<PublicKey, ValidatorIdent>)
                        -> Result<(), Box<Error>>>>
    {
        let config_path = Self::config(matches);
        let template_path = Self::template(matches);
        let keychain_path = Self::keychain(matches);

        let template: ConfigTemplate = ConfigFile::load(template_path)
                                                .expect("Failed to load config template.");
        let keychain: KeyConfig = ConfigFile::load(keychain_path)
                                                .expect("Failed to load key config.");

        if template.validators.len() != template.count {
            panic!("Template should be full.");
        }

        let func = on_init
            .into()
            .map(|f| f(&template.services, &template.validators));
        let func = func.unwrap_or(Ok(()));
        // propogate error
        func.unwrap();

        let genesis = GenesisConfig::new(template.validators.iter().map(|(k, _)| *k));
        let peers = template
            .validators
            .iter()
            .map(|(_, ident)| ident.addr)
            .collect();
        let validator_ident = &template.validators[&keychain.public_key];

        let config = NodeConfig {
            listen_address: validator_ident.addr,
            network: Default::default(),
            peers: peers,
            public_key: keychain.public_key,
            secret_key: keychain.secret_key,
            genesis: genesis,
            api: Default::default(),
        };

        ConfigFile::save(&config, config_path)
                    .expect("Could not write config file.");
    }
}

pub struct GenerateTestnetCommand;

impl GenerateTestnetCommand {
    pub fn new<'a>() -> App<'a, 'a> {
        SubCommand::with_name("generate")
            .about("Generates genesis configuration")
            .arg(Arg::with_name("OUTPUT_DIR")
                     .short("o")
                     .long("output-dir")
                     .value_name("OUTPUT_DIR")
                     .required(true)
                     .takes_value(true))
            .arg(Arg::with_name("START_PORT")
                     .short("p")
                     .long("start-port")
                     .value_name("START_PORT")
                     .required(false)
                     .takes_value(true))
            .arg(Arg::with_name("COUNT")
                     .help("Validators count")
                     .required(true)
                     .index(1))
    }

    pub fn output_dir<'a>(matches: &'a ArgMatches<'a>) -> &'a Path {
        Path::new(matches.value_of("OUTPUT_DIR").unwrap())
    }

    pub fn validators_count(matches: &ArgMatches) -> u8 {
        matches.value_of("COUNT").unwrap().parse().unwrap()
    }

    pub fn start_port(matches: &ArgMatches) -> Option<u16> {
        matches
            .value_of("START_PORT")
            .map(|p| p.parse().unwrap())
    }

    pub fn execute<'a>(matches: &'a ArgMatches<'a>) {
        let dir = Self::output_dir(matches);
        let count = Self::validators_count(matches);
        let start_port = Self::start_port(matches).unwrap_or_else(|| 2000);

        let dir = dir.join("validators");
        if !dir.exists() {
            fs::create_dir_all(&dir).unwrap();
        }

        let configs = generate_testnet_config(count, start_port);
        for (idx, cfg) in configs.into_iter().enumerate() {
            let file_name = format!("{}.toml", idx);
            ConfigFile::save(&cfg, &dir.join(file_name)).unwrap();
        }
    }
}
<commit_msg>rewrite address option<commit_after>
use clap::{SubCommand, App, Arg, ArgMatches};

use std::path::Path;
use std::fs;
use std::marker::PhantomData;
use std::collections::BTreeMap;
use std::net::SocketAddr;
use std::error::Error;

use config::ConfigFile;
use blockchain::{ConsensusConfig, GenesisConfig};
use node::NodeConfig;
use storage::Storage;
use crypto::{self, PublicKey, SecretKey};
use super::generate_testnet_config;

const DEFAULT_EXONUM_LISTEN_PORT: u16 = 6333;

#[derive(Debug)]
pub struct RunCommand<'a, 'b>
    where 'a: 'b
{
    _p: PhantomData<App<'a, 'b>>,
}

impl<'a, 'b> RunCommand<'a, 'b>
    where 'a: 'b
{
    pub fn new() -> App<'a, 'b> {
        SubCommand::with_name("run")
            .about("Run node with given configuration")
            .arg(Arg::with_name("NODE_CONFIG_PATH")
                     .short("c")
                     .long("node-config")
                     .value_name("NODE_CONFIG_PATH")
                     .help("Path to node configuration file")
                     .required(true)
                     .takes_value(true))
            .arg(Arg::with_name("LEVELDB_PATH")
                     .short("d")
                     .long("leveldb-path")
                     .value_name("LEVELDB_PATH")
                     .help("Use leveldb database with the given path")
                     .required(false)
                     .takes_value(true))
            .arg(Arg::with_name("PUBLIC_API_ADDRESS")
                     .long("public-api-address")
                     .help("Listen address for public api")
                     .required(false)
                     .takes_value(true))
            .arg(Arg::with_name("PRIVATE_API_ADDRESS")
                     .long("private-api-address")
                     .help("Listen address for private api")
                     .required(false)
                     .takes_value(true))
    }

    pub fn node_config_path(matches: &'a ArgMatches<'a>) -> &'a Path {
        matches
            .value_of("NODE_CONFIG_PATH")
            .map(Path::new)
            .expect("Path to node configuration is no setted")
    }

    pub fn node_config(matches: &'a ArgMatches<'a>) -> NodeConfig {
        let path = Self::node_config_path(matches);
        let mut cfg: NodeConfig = ConfigFile::load(path).unwrap();
        // Override api options
        if let Some(addr) = Self::public_api_address(matches) {
            cfg.api.public_api_address = Some(addr);
        }
        if let Some(addr) = Self::private_api_address(matches) {
            cfg.api.private_api_address = Some(addr);
        }
        cfg
    }

    pub fn public_api_address(matches: &'a ArgMatches<'a>) -> Option<SocketAddr> {
        matches
            .value_of("PUBLIC_API_ADDRESS")
            .map(|s| {
                     s.parse()
                         .expect("Public api address has incorrect format")
                 })
    }

    pub fn private_api_address(matches: &'a ArgMatches<'a>) -> Option<SocketAddr> {
        matches
            .value_of("PRIVATE_API_ADDRESS")
            .map(|s| {
                     s.parse()
                         .expect("Private api address has incorrect format")
                 })
    }

    pub fn leveldb_path(matches: &'a ArgMatches<'a>) -> Option<&'a Path> {
        matches.value_of("LEVELDB_PATH").map(Path::new)
    }

    #[cfg(not(feature="memorydb"))]
    pub fn db(matches: &'a ArgMatches<'a>) -> Box<Database> {
        use storage::{LevelDB, LevelDBOptions};

        let path = Self::leveldb_path(matches).unwrap();
        let mut options = LevelDBOptions::new();
        options.create_if_missing = true;
        Box::new(LevelDB::open(path, options).unwrap())
    }

    #[cfg(feature="memorydb")]
    pub fn db(_: &'a ArgMatches<'a>) -> Box<Database> {
        use storage::MemoryDB;
        Box::new(MemoryDB::new())
    }
}

#[derive(Serialize, Deserialize)]
pub struct ValidatorIdent {
    pub values: BTreeMap<String, String>,
    addr: SocketAddr,
}

#[derive(Serialize, Deserialize, Default)]
pub struct ConfigTemplate {
    validators: BTreeMap<PublicKey, ValidatorIdent>,
    consensus_cfg: ConsensusConfig,
    count: usize,
    services: BTreeMap<String, String>,
}

// toml file could not save array without "field name"
#[derive(Serialize, Deserialize)]
struct PubKeyConfig {
    public_key: PublicKey,
}

impl ::std::convert::From<PublicKey> for PubKeyConfig {
    fn from(pk: PublicKey) -> Self {
        PubKeyConfig {
            public_key: pk
        }
    }
}

impl ::std::convert::Into<PublicKey> for PubKeyConfig {
    fn into(self) -> PublicKey {
        self.public_key
    }
}

#[derive(Serialize, Deserialize)]
pub struct KeyConfig {
    public_key: PublicKey,
    secret_key: SecretKey,
}

pub struct KeyGeneratorCommand;

impl KeyGeneratorCommand {
    /// Creates basic keygen subcommand.
    pub fn new<'a>() -> App<'a, 'a> {
        SubCommand::with_name("keygen")
            .about("Generate basic node secret key.")
            .arg(Arg::with_name("KEYCHAIN")
                     .help("Path to key config.")
                     .required(true)
                     .index(1))
    }

    /// Path where keychain config should be saved
    pub fn keychain<'a>(matches: &'a ArgMatches<'a>) -> &'a Path {
        Path::new(matches.value_of("KEYCHAIN").unwrap())
    }

    /// Generates and writes key config to `keychain()` path.
    pub fn execute(matches: &ArgMatches) {
        let (pub_key, sec_key) = crypto::gen_keypair();
        let keyconfig = Self::keychain(matches);
        let pub_key_path = keyconfig.with_extension("pub");
        let pub_key_config: PubKeyConfig = pub_key.into();
        // save pub_key seperately
        ConfigFile::save(&pub_key_config, &pub_key_path)
                    .expect("Could not write public key file.");

        let config = KeyConfig {
            public_key: pub_key,
            secret_key: sec_key,
        };

        ConfigFile::save(&config, Self::keychain(matches))
                    .expect("Could not write keychain file.");
    }
}

/// implements command for template generating
pub struct GenerateTemplateCommand;
impl GenerateTemplateCommand {
    pub fn new<'a>() -> App<'a, 'a> {
        SubCommand::with_name("generate-template")
            .about("Generate basic template.")
            .arg(Arg::with_name("COUNT")
                     .help("Validator total count.")
                     .required(true)
                     .index(1))
            .arg(Arg::with_name("TEMPLATE")
                     .help("Path to template config.")
                     .required(true)
                     .index(2))
    }

    /// Path where template config should be saved
    pub fn template<'a>(matches: &'a ArgMatches<'a>) -> &'a Path {
        Path::new(matches.value_of("TEMPLATE").unwrap())
    }
    /// Validator total count
    pub fn count(matches: &ArgMatches) -> usize {
        matches.value_of("COUNT").unwrap().parse().unwrap()
    }

    /// Write default template config into `template()` path.
    pub fn execute<T>(matches: &ArgMatches, values: T)
        where T: Into<Option<BTreeMap<String, String>>>
    {
        let values = values.into().unwrap_or_default();
        let template = ConfigTemplate {
            count: Self::count(matches),
            services: values,
            ..ConfigTemplate::default()
        };

        ConfigFile::save(&template, Self::template(matches))
                        .expect("Could not write template file.");
    }
}

pub struct AddValidatorCommand;
impl AddValidatorCommand {
    pub fn new<'a>() -> App<'a, 'a> {
        SubCommand::with_name("add-validator")
            .about("Preinit configuration, add validator to config template.")
            .arg(Arg::with_name("TEMPLATE")
                     .help("Path to template")
                     .required(true)
                     .index(1))
            .arg(Arg::with_name("PUBLIC_KEY")
                     .help("Path to public key file.")
                     .required(true)
                     .index(2))
            .arg(Arg::with_name("LISTEN_ADDR")
                     .short("a")
                     .long("listen-addr")
                     .value_name("LISTEN_ADDR")
                     .required(true)
                     .takes_value(true))

    }

    /// path to public_key file
    pub fn public_key<'a>(matches: &'a ArgMatches<'a>) -> &'a Path {
        Path::new(matches.value_of("PUBLIC_KEY").unwrap())
    }

    /// path to template config
    pub fn template<'a>(matches: &'a ArgMatches<'a>) -> &'a Path {
        Path::new(matches.value_of("TEMPLATE").unwrap())
    }

    // exonum listen addr
    pub fn addr(matches: &ArgMatches) -> String {
        matches.value_of("LISTEN_ADDR").unwrap().to_string()
    }

    #[cfg_attr(feature="cargo-clippy", allow(map_entry))]
    pub fn execute<'a, F>(matches: &ArgMatches, on_add: F)
        where F: Into<Option<&'a Fn(usize, &mut BTreeMap<String, String>)
                        -> Result<BTreeMap<String, String>, Box<Error>>>>,
    {
        let template_path = Self::template(matches);
        let public_key_path = Self::public_key(matches);
        let addr = Self::addr(matches);
        let mut addr_parts = addr.split(':');

        let mut template: ConfigTemplate = ConfigFile::load(template_path).unwrap();
        let public_key: PubKeyConfig = ConfigFile::load(public_key_path).unwrap();
        let public_key = public_key.into();
        let addr = format!("{}:{}",
                           addr_parts.next().expect("expected ip addr"),
                           addr_parts.next().map_or(DEFAULT_EXONUM_LISTEN_PORT,
                                                    |s| s.parse().expect("could not parse port")))
                .parse()
                .unwrap();
        if !template.validators.contains_key(&public_key) {
            if template.validators.len() >= template.count {
                panic!("This template already full.");
            }
            let func = on_add
                .into()
                .map(|f| f(template.count, &mut template.services));
            let map = func.unwrap_or_else(|| Ok(BTreeMap::new()));

            let ident = ValidatorIdent {
                addr: addr,
                values: map.unwrap(),
            };
            template.validators.insert(public_key, ident);
        } else {
            panic!("This node already in template");
        }

        ConfigFile::save(&template, template_path).unwrap();
    }
}

pub struct InitCommand;

impl InitCommand {
    pub fn new<'a>() -> App<'a, 'a> {
        SubCommand::with_name("init")
            .about("Toolchain to generate configuration")
            .arg(Arg::with_name("FULL_TEMPLATE")
                     .help("Path to full template")
                     .required(true)
                     .index(1))
            .arg(Arg::with_name("KEYCHAIN")
                     .help("Path to keychain config.")
                     .required(true)
                     .index(2))
            .arg(Arg::with_name("CONFIG_PATH")
                     .help("Path to node config.")
                     .required(true)
                     .index(3))

    }

    /// path to full template config
    pub fn template<'a>(matches: &'a ArgMatches<'a>) -> &'a Path {
        Path::new(matches.value_of("FULL_TEMPLATE").unwrap())
    }

    /// path to output config
    pub fn config<'a>(matches: &'a ArgMatches<'a>) -> &'a Path {
        Path::new(matches.value_of("CONFIG_PATH").unwrap())
    }

    /// path to keychain (public and secret keys)
    pub fn keychain<'a>(matches: &'a ArgMatches<'a>) -> &'a Path {
        Path::new(matches.value_of("KEYCHAIN").unwrap())
    }

    pub fn execute<'a, F>(matches: &ArgMatches, on_init: F)
        where F: Into<Option<&'a Fn(&BTreeMap<String, String>,
                        &BTreeMap<PublicKey, ValidatorIdent>)
                        -> Result<(), Box<Error>>>>
    {
        let config_path = Self::config(matches);
        let template_path = Self::template(matches);
        let keychain_path = Self::keychain(matches);

        let template: ConfigTemplate = ConfigFile::load(template_path)
                                                .expect("Failed to load config template.");
        let keychain: KeyConfig = ConfigFile::load(keychain_path)
                                                .expect("Failed to load key config.");

        if template.validators.len() != template.count {
            panic!("Template should be full.");
        }

        let func = on_init
            .into()
            .map(|f| f(&template.services, &template.validators));
        let func = func.unwrap_or(Ok(()));
        // propogate error
        func.unwrap();

        let genesis = GenesisConfig::new(template.validators.iter().map(|(k, _)| *k));
        let peers = template
            .validators
            .iter()
            .map(|(_, ident)| ident.addr)
            .collect();
        let validator_ident = &template.validators[&keychain.public_key];

        let config = NodeConfig {
            listen_address: validator_ident.addr,
            network: Default::default(),
            peers: peers,
            public_key: keychain.public_key,
            secret_key: keychain.secret_key,
            genesis: genesis,
            api: Default::default(),
        };

        ConfigFile::save(&config, config_path)
                    .expect("Could not write config file.");
    }
}

pub struct GenerateTestnetCommand;

impl GenerateTestnetCommand {
    pub fn new<'a>() -> App<'a, 'a> {
        SubCommand::with_name("generate")
            .about("Generates genesis configuration")
            .arg(Arg::with_name("OUTPUT_DIR")
                     .short("o")
                     .long("output-dir")
                     .value_name("OUTPUT_DIR")
                     .required(true)
                     .takes_value(true))
            .arg(Arg::with_name("START_PORT")
                     .short("p")
                     .long("start-port")
                     .value_name("START_PORT")
                     .required(false)
                     .takes_value(true))
            .arg(Arg::with_name("COUNT")
                     .help("Validators count")
                     .required(true)
                     .index(1))
    }

    pub fn output_dir<'a>(matches: &'a ArgMatches<'a>) -> &'a Path {
        Path::new(matches.value_of("OUTPUT_DIR").unwrap())
    }

    pub fn validators_count(matches: &ArgMatches) -> u8 {
        matches.value_of("COUNT").unwrap().parse().unwrap()
    }

    pub fn start_port(matches: &ArgMatches) -> Option<u16> {
        matches
            .value_of("START_PORT")
            .map(|p| p.parse().unwrap())
    }

    pub fn execute<'a>(matches: &'a ArgMatches<'a>) {
        let dir = Self::output_dir(matches);
        let count = Self::validators_count(matches);
        let start_port = Self::start_port(matches).unwrap_or_else(|| 2000);

        let dir = dir.join("validators");
        if !dir.exists() {
            fs::create_dir_all(&dir).unwrap();
        }

        let configs = generate_testnet_config(count, start_port);
        for (idx, cfg) in configs.into_iter().enumerate() {
            let file_name = format!("{}.toml", idx);
            ConfigFile::save(&cfg, &dir.join(file_name)).unwrap();
        }
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("Pointing", inherited=True, gecko_name="UserInterface") %>

<%helpers:longhand name="cursor" boxed="${product == 'gecko'}" animation_value_type="none"
  spec="https://drafts.csswg.org/css-ui/#cursor">
    pub use self::computed_value::T as SpecifiedValue;
    use values::HasViewportPercentage;
    use values::computed::ComputedValueAsSpecified;
    use values::specified::url::SpecifiedUrl;

    impl ComputedValueAsSpecified for SpecifiedValue {}
    no_viewport_percentage!(SpecifiedValue);

    pub mod computed_value {
        use std::fmt;
        use style_traits::cursor::Cursor;
        use style_traits::ToCss;
        use values::specified::url::SpecifiedUrl;

        #[derive(Clone, PartialEq, Copy, Debug)]
        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
        pub enum Keyword {
            AutoCursor,
            SpecifiedCursor(Cursor),
        }

        #[cfg(not(feature = "gecko"))]
        pub type T = Keyword;

        #[cfg(feature = "gecko")]
        #[derive(Clone, PartialEq, Debug)]
        pub struct Image {
            pub url: SpecifiedUrl,
            pub hotspot: Option<(f32, f32)>,
        }

        #[cfg(feature = "gecko")]
        #[derive(Clone, PartialEq, Debug)]
        pub struct T {
            pub images: Vec<Image>,
            pub keyword: Keyword,
        }

        impl ToCss for Keyword {
            fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
                match *self {
                    Keyword::AutoCursor => dest.write_str("auto"),
                    Keyword::SpecifiedCursor(c) => c.to_css(dest),
                }
            }
        }

        #[cfg(feature = "gecko")]
        impl ToCss for Image {
            fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
                try!(self.url.to_css(dest));
                if let Some((x, y)) = self.hotspot {
                    try!(dest.write_str(" "));
                    try!(x.to_css(dest));
                    try!(dest.write_str(" "));
                    try!(y.to_css(dest));
                }
                Ok(())
            }
        }

        #[cfg(feature = "gecko")]
        impl ToCss for T {
            fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
                for url in &self.images {
                    try!(url.to_css(dest));
                    try!(dest.write_str(", "));
                }
                self.keyword.to_css(dest)
            }
        }
    }

    #[cfg(not(feature = "gecko"))]
    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        computed_value::Keyword::AutoCursor
    }

    #[cfg(feature = "gecko")]
    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        computed_value::T {
            images: vec![],
            keyword: computed_value::Keyword::AutoCursor
        }
    }

    impl Parse for computed_value::Keyword {
        fn parse(_context: &ParserContext, input: &mut Parser) -> Result<computed_value::Keyword, ()> {
            use std::ascii::AsciiExt;
            use style_traits::cursor::Cursor;
            let ident = try!(input.expect_ident());
            if ident.eq_ignore_ascii_case("auto") {
                Ok(computed_value::Keyword::AutoCursor)
            } else {
                Cursor::from_css_keyword(&ident).map(computed_value::Keyword::SpecifiedCursor)
            }
        }
    }

    #[cfg(feature = "gecko")]
    fn parse_image(context: &ParserContext, input: &mut Parser) -> Result<computed_value::Image, ()> {
        Ok(computed_value::Image {
            url: try!(SpecifiedUrl::parse(context, input)),
            hotspot: match input.try(|input| input.expect_number()) {
                Ok(number) => Some((number, try!(input.expect_number()))),
                Err(()) => None,
            },
        })
    }

    #[cfg(not(feature = "gecko"))]
    pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
        computed_value::Keyword::parse(context, input)
    }

    /// cursor: [<url> [<number> <number>]?]# [auto | default | ...]
    #[cfg(feature = "gecko")]
    pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
        let mut images = vec![];
        loop {
            match input.try(|input| parse_image(context, input)) {
                Ok(image) => images.push(image),
                Err(()) => break,
            }
            try!(input.expect_comma());
        }

        Ok(computed_value::T {
            images: images,
            keyword: try!(computed_value::Keyword::parse(context, input)),
        })
    }
</%helpers:longhand>

// NB: `pointer-events: auto` (and use of `pointer-events` in anything that isn't SVG, in fact)
// is nonstandard, slated for CSS4-UI.
// TODO(pcwalton): SVG-only values.
${helpers.single_keyword("pointer-events", "auto none", animation_value_type="none",
                         extra_gecko_values="visiblepainted visiblefill visiblestroke visible painted fill stroke",
                         spec="https://www.w3.org/TR/SVG11/interact.html#PointerEventsProperty")}

${helpers.single_keyword("-moz-user-input", "auto none enabled disabled",
                         products="gecko", gecko_ffi_name="mUserInput",
                         gecko_enum_prefix="StyleUserInput",
                         gecko_inexhaustive=True,
                         animation_value_type="none",
                         spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-input)")}

${helpers.single_keyword("-moz-user-modify", "read-only read-write write-only",
                         products="gecko", gecko_ffi_name="mUserModify",
                         gecko_enum_prefix="StyleUserModify",
                         needs_conversion=True,
                         animation_value_type="none",
                         spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-modify)")}

${helpers.single_keyword("-moz-user-focus",
                         "none ignore normal select-after select-before select-menu select-same select-all",
                         products="gecko", gecko_ffi_name="mUserFocus",
                         gecko_enum_prefix="StyleUserFocus",
                         gecko_inexhaustive=True,
                         animation_value_type="none",
                         spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-focus)")}

${helpers.predefined_type("caret-color",
                          "ColorOrAuto",
                          "Either::Second(Auto)",
                          spec="https://drafts.csswg.org/css-ui/#caret-color",
                          animation_value_type="Either<IntermediateColor, Auto>",
                          boxed=True,
                          products="gecko")}
<commit_msg>Properly parse 'pointer-events: all'<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("Pointing", inherited=True, gecko_name="UserInterface") %>

<%helpers:longhand name="cursor" boxed="${product == 'gecko'}" animation_value_type="none"
  spec="https://drafts.csswg.org/css-ui/#cursor">
    pub use self::computed_value::T as SpecifiedValue;
    use values::HasViewportPercentage;
    use values::computed::ComputedValueAsSpecified;
    use values::specified::url::SpecifiedUrl;

    impl ComputedValueAsSpecified for SpecifiedValue {}
    no_viewport_percentage!(SpecifiedValue);

    pub mod computed_value {
        use std::fmt;
        use style_traits::cursor::Cursor;
        use style_traits::ToCss;
        use values::specified::url::SpecifiedUrl;

        #[derive(Clone, PartialEq, Copy, Debug)]
        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
        pub enum Keyword {
            AutoCursor,
            SpecifiedCursor(Cursor),
        }

        #[cfg(not(feature = "gecko"))]
        pub type T = Keyword;

        #[cfg(feature = "gecko")]
        #[derive(Clone, PartialEq, Debug)]
        pub struct Image {
            pub url: SpecifiedUrl,
            pub hotspot: Option<(f32, f32)>,
        }

        #[cfg(feature = "gecko")]
        #[derive(Clone, PartialEq, Debug)]
        pub struct T {
            pub images: Vec<Image>,
            pub keyword: Keyword,
        }

        impl ToCss for Keyword {
            fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
                match *self {
                    Keyword::AutoCursor => dest.write_str("auto"),
                    Keyword::SpecifiedCursor(c) => c.to_css(dest),
                }
            }
        }

        #[cfg(feature = "gecko")]
        impl ToCss for Image {
            fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
                try!(self.url.to_css(dest));
                if let Some((x, y)) = self.hotspot {
                    try!(dest.write_str(" "));
                    try!(x.to_css(dest));
                    try!(dest.write_str(" "));
                    try!(y.to_css(dest));
                }
                Ok(())
            }
        }

        #[cfg(feature = "gecko")]
        impl ToCss for T {
            fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
                for url in &self.images {
                    try!(url.to_css(dest));
                    try!(dest.write_str(", "));
                }
                self.keyword.to_css(dest)
            }
        }
    }

    #[cfg(not(feature = "gecko"))]
    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        computed_value::Keyword::AutoCursor
    }

    #[cfg(feature = "gecko")]
    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        computed_value::T {
            images: vec![],
            keyword: computed_value::Keyword::AutoCursor
        }
    }

    impl Parse for computed_value::Keyword {
        fn parse(_context: &ParserContext, input: &mut Parser) -> Result<computed_value::Keyword, ()> {
            use std::ascii::AsciiExt;
            use style_traits::cursor::Cursor;
            let ident = try!(input.expect_ident());
            if ident.eq_ignore_ascii_case("auto") {
                Ok(computed_value::Keyword::AutoCursor)
            } else {
                Cursor::from_css_keyword(&ident).map(computed_value::Keyword::SpecifiedCursor)
            }
        }
    }

    #[cfg(feature = "gecko")]
    fn parse_image(context: &ParserContext, input: &mut Parser) -> Result<computed_value::Image, ()> {
        Ok(computed_value::Image {
            url: try!(SpecifiedUrl::parse(context, input)),
            hotspot: match input.try(|input| input.expect_number()) {
                Ok(number) => Some((number, try!(input.expect_number()))),
                Err(()) => None,
            },
        })
    }

    #[cfg(not(feature = "gecko"))]
    pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
        computed_value::Keyword::parse(context, input)
    }

    /// cursor: [<url> [<number> <number>]?]# [auto | default | ...]
    #[cfg(feature = "gecko")]
    pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
        let mut images = vec![];
        loop {
            match input.try(|input| parse_image(context, input)) {
                Ok(image) => images.push(image),
                Err(()) => break,
            }
            try!(input.expect_comma());
        }

        Ok(computed_value::T {
            images: images,
            keyword: try!(computed_value::Keyword::parse(context, input)),
        })
    }
</%helpers:longhand>

// NB: `pointer-events: auto` (and use of `pointer-events` in anything that isn't SVG, in fact)
// is nonstandard, slated for CSS4-UI.
// TODO(pcwalton): SVG-only values.
${helpers.single_keyword("pointer-events", "auto none", animation_value_type="none",
                         extra_gecko_values="visiblepainted visiblefill visiblestroke visible painted fill stroke all",
                         spec="https://www.w3.org/TR/SVG11/interact.html#PointerEventsProperty")}

${helpers.single_keyword("-moz-user-input", "auto none enabled disabled",
                         products="gecko", gecko_ffi_name="mUserInput",
                         gecko_enum_prefix="StyleUserInput",
                         gecko_inexhaustive=True,
                         animation_value_type="none",
                         spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-input)")}

${helpers.single_keyword("-moz-user-modify", "read-only read-write write-only",
                         products="gecko", gecko_ffi_name="mUserModify",
                         gecko_enum_prefix="StyleUserModify",
                         needs_conversion=True,
                         animation_value_type="none",
                         spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-modify)")}

${helpers.single_keyword("-moz-user-focus",
                         "none ignore normal select-after select-before select-menu select-same select-all",
                         products="gecko", gecko_ffi_name="mUserFocus",
                         gecko_enum_prefix="StyleUserFocus",
                         gecko_inexhaustive=True,
                         animation_value_type="none",
                         spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-focus)")}

${helpers.predefined_type("caret-color",
                          "ColorOrAuto",
                          "Either::Second(Auto)",
                          spec="https://drafts.csswg.org/css-ui/#caret-color",
                          animation_value_type="Either<IntermediateColor, Auto>",
                          boxed=True,
                          products="gecko")}
<|endoftext|>


<commit_before>use std::collections::{VecDeque};
use std::cmp::Ordering;
use std::num::Wrapping;

use base::types::monster::StatType;
use base::monster::Monster;

use calculate::damage::calculate_damage;

use rand::{Rng, StdRng};

#[derive(Debug)]
pub struct Party<'a>
{
	pub members: &'a mut [Monster],
	side: u8,
	active: Vec<usize>,
}

impl<'a> Party<'a>
{
	pub fn new(members: &'a mut [Monster], out: usize) -> Self
	{
		let mut party = Party
		{
			members: members,
			side: 1,
			active: Vec::with_capacity(out),
		};

		let mut current = Wrapping(usize::max_value());
		for _ in 0..party.active.capacity()
		{
			current = Wrapping(party.next_alive((current + Wrapping(1usize)).0));
			println!("Yolo swag {}", current);
			if current.0 == party.members.len()
			{
				break;
			}
			party.active.push(current.0);
			if party.active.len() == party.active.capacity()
			{
				break;
			}
		}
		party
	}
	fn next_alive(&self, party: usize) -> usize
	{
		for member_index in party..self.members.len()
		{
			if self.members[member_index].get_health() != 0
			{
				return member_index;
			}
		}
		println!("Yolo swag");
		self.members.len()
	}
	pub fn active_member(&self, index: usize) -> &Monster
	{
		&self.members[index]
	}
	pub fn active_count(&self) -> usize
	{
		self.active.len()
	}
}

#[derive(Debug)]
pub struct CommandAttack
{
	pub attack_index: usize,
	pub party: usize,
	pub monster: usize,
}

#[derive(Debug)]
pub enum CommandType
{
	Attack(CommandAttack),
	//Item(ItemId),
	//Switch(ToId),
	Escape,
}

#[derive(Debug)]
pub struct Command
{
	pub command_type: CommandType,
	pub party: usize,
	pub monster: usize,
}

impl Command
{
	fn new(command_type: CommandType, party: usize, monster: usize,) -> Self
	{
		Command
		{
			command_type: command_type,
			party: party,
			monster: monster,
		}
	}
}

impl Command
{
	fn cmp(command_self: &Command, monster_self: &Monster, command_other: &Command,
		monster_other: &Monster) -> Ordering
	{
		match command_self.command_type
		{
			CommandType::Attack(_) =>
			{
				if let CommandType::Attack(_) = command_other.command_type
				{
					monster_other.get_stat_speed().cmp(&monster_self.get_stat_speed())
				}
				else
				{
					Ordering::Greater
				}
			}
			CommandType::Escape =>
			{
				if let CommandType::Escape = command_other.command_type
				{
					let group = command_self.party.cmp(&command_other.party);
					if group == Ordering::Equal
					{
						command_self.monster.cmp(&command_other.monster)
					}
					else
					{
						group
					}
				}
				else
				{
					Ordering::Less
				}
			}
		}
	}
}

impl CommandType
{
	fn effects<'a, R: Rng>(&self, parties: &Vec<Party<'a>>, command: &Command, rng: &mut R) -> VecDeque<Effect>
	{
		let mut v = VecDeque::new();
		match *self
		{
			CommandType::Attack(ref target) =>
			{
				let offense = &parties[command.party].members[command.monster];
				let defense = &parties[target.party].members[target.monster];
				let damage = Damage
				{
					amount: calculate_damage(offense, 0, defense, false, 1f32, rng),
					party: target.party,
					monster: target.monster
				};
				v.push_back(Effect::Damage(damage));
			}
			CommandType::Escape =>
			{
				v.push_back(Effect::None(Reason::Escape));
			},
		}
		v
	}
}

#[derive(Debug)]
pub struct Damage
{
	amount: StatType,
	party: usize,
	monster: usize,
}

impl Damage
{
	pub fn amount(&self) -> StatType
	{
		self.amount
	}
	pub fn party(&self) -> usize
	{
		self.party
	}
	pub fn member(&self) -> usize
	{
		self.monster
	}
}

#[derive(Debug)]
pub enum Reason
{
	Critical,
	Escape,
}

#[derive(Debug)]
pub enum Effect
{
	Damage(Damage),
	// Status(StatusId),
	// Bonus(BonusType),
	// Ability(AbilityId),
	// Miss,
	// ,
	// Uneffective,
	// LessEffective,
	// SuperEffecitve,
	None(Reason),
}

#[derive(Debug)]
struct BattleCommand
{
	command: Command,
	effects: VecDeque<Effect>,
}

impl BattleCommand
{
	fn new<'a, R: Rng>(command: Command, parties: &Vec<Party<'a>>, rng: &mut R) -> Self
	{
		let effects = command.command_type.effects(parties, &command, rng);
		BattleCommand
		{
			effects: effects,
			command: command,
		}
	}
}

pub struct Battle<'a>
{
	/// Maps to the groups that have already added a command.
	ready: Vec<Vec<bool>>,

	/// True if the turn has started, false otherwise.
	started: bool,

	/// The total number of available participants.
	total: usize,

	/// The number of groups still waiting for a command.
	waiting: usize,

	/// The parties in this battle.
	parties: Vec<Party<'a>>,

	/// The list of executed commands, for playback.
	commands: Vec<BattleCommand>,

	/// The queue of upcoming commands in the next turn.
	queue: Vec<Command>,

	/// The current effect being executed.
	current: usize,

	rng: StdRng,

	// TODO: lingering effects.
}

pub enum BattleExecution
{
	Command,
	Queue,
	Waiting,
}

impl<'a> Battle<'a>
{
	pub fn new(parties: Vec<Party<'a>>) -> Self
	{
		let mut total = 0;
		let mut ready = Vec::with_capacity(parties.len());
		for group in parties.iter()
		{
			total += group.active_count();
			ready.push(vec![false; group.active_count()]);
		}
		Battle
		{
			ready: ready,
			started: false,
			total: total,
			waiting: total,
			parties: parties,
			commands: Vec::new(),
			queue: Vec::new(),
			current: 0,
			rng: StdRng::new().unwrap(),
		}
	}
	pub fn party(&self, index: usize) -> &Party<'a>
	{
		&self.parties[index]
	}
	pub fn monster(&self, party: usize, monster: usize) -> &Monster
	{
		&self.parties[party].members[monster]
	}
	pub fn monster_active(&self, party: usize, monster: usize) -> &Monster
	{
		self.parties[party].active_member(monster)
	}
	pub fn monster_active_count(&self, party: usize) -> usize
	{
		self.parties[party].active_count()
	}
	fn monster_command(&self, command: &Command) -> &Monster
	{
		self.monster(command.party, command.monster)
	}
	/// Adds a command to the turn queue. Returns true if the command is a valid command.
	pub fn add_command(&mut self, command: CommandType, party: usize, monster: usize) -> bool
	{
		if self.started
		{
			println!("Already starte1.");
			return false;
		}
		if party >= self.parties.len()
		{
			println!("Already len 1.");
			return false;
		}
		if self.ready[party][monster] == true
		{
			println!("Already ready {}.", monster);
			return false;
		}
		if monster >= self.parties[party].members.len()
		{
			println!("Already len.");
			return false
		}

		// TODO: Check if attack is valid against target.

		self.ready[party][monster] = true;
		self.waiting -= 1;
		println!("{} {:?}", self.waiting, self.ready);

		self.queue.push(Command::new(command, party, monster));
		true
	}

	fn execute_command(&mut self) -> BattleExecution
	{
		let mut min_index = 0;
		for index in 1..self.queue.len()
		{
			if Command::cmp(&self.queue[index], self.monster_command(&self.queue[index]),
				&self.queue[min_index], self.monster_command(&self.queue[min_index])) == Ordering::Less
			{
				min_index = index;
			}
		}
		let command = self.queue.swap_remove(min_index);
		if let CommandType::Attack(ref attack) = command.command_type
		{
			let target = self.parties[command.party].members.get_mut(command.monster).unwrap();
			target.get_attacks_mut()[attack.attack_index].limit_left_take(1);
		}

		let battle_command = BattleCommand::new(command, &self.parties, &mut self.rng);
		self.commands.push(battle_command);
		self.current = 0;
		BattleExecution::Command
	}

	/// Executes the next battle action.
	pub fn execute(&mut self) -> BattleExecution
	{
		if self.started
		{
			if self.current != self.commands.last().unwrap().effects.len()
			{
				self.apply_effect();

				self.current += 1;
				BattleExecution::Queue
			}
			else if !self.queue.is_empty()
			{
				self.execute_command()
			}
			else
			{
				// Reset the waiting for new commands.
				self.waiting = self.total;
				self.started = false;
				for ready_party in self.ready.iter_mut()
				{
					for ready in ready_party.iter_mut()
					{
						*ready = false;
					}
				}
				BattleExecution::Waiting
			}
		}
		else
		{
			if self.waiting != 0
			{
				BattleExecution::Waiting
			}
			else
			{
				// TODO: Insert lingering effects into priority queue.

				self.started = true;
				self.execute_command()
			}
		}
	}

	/// The current executing command.
	pub fn get_current_command(&self) -> Option<&Command>
	{
		self.commands.last().map(|battle_command| &battle_command.command)
	}

	/// The current executing result of the current executing command.
	pub fn get_current_effect(&self) -> Option<&Effect>
	{
		self.commands.last().map(|battle_command| &battle_command.effects[self.current - 1])
	}

	fn apply_effect(&mut self)
	{
		let battle_command = self.commands.last().unwrap();
		match battle_command.effects[self.current]
		{
			Effect::Damage(ref effect) =>
			{
				let target = self.parties[effect.party].members.get_mut(effect.monster).unwrap();
				target.lose_health(effect.amount);
			}
			_ => ()
		}
	}
}
<commit_msg>Remove dead monsters from active party member list<commit_after>use std::collections::{VecDeque};
use std::cmp::Ordering;
use std::num::Wrapping;

use base::types::monster::StatType;
use base::monster::Monster;

use calculate::damage::calculate_damage;

use rand::{Rng, StdRng};

#[derive(Debug)]
pub struct Party<'a>
{
	pub members: &'a mut [Monster],
	side: u8,
	active: Vec<usize>,
}

impl<'a> Party<'a>
{
	pub fn new(members: &'a mut [Monster], out: usize) -> Self
	{
		let mut party = Party
		{
			members: members,
			side: 1,
			active: Vec::with_capacity(out),
		};

		let mut current = Wrapping(usize::max_value());
		for _ in 0..party.active.capacity()
		{
			current = Wrapping(party.next_alive((current + Wrapping(1usize)).0));
			println!("Yolo swag {}", current);
			if current.0 == party.members.len()
			{
				break;
			}
			party.active.push(current.0);
			if party.active.len() == party.active.capacity()
			{
				break;
			}
		}
		party
	}
	fn next_alive(&self, party: usize) -> usize
	{
		for member_index in party..self.members.len()
		{
			if self.members[member_index].get_health() != 0 &&
				!self.active.contains(&member_index)
			{
				return member_index;
			}
		}
		self.members.len()
	}
	pub fn active_member(&self, index: usize) -> &Monster
	{
		&self.members[index]
	}
	pub fn active_count(&self) -> usize
	{
		self.active.len()
	}
	fn active_update(&mut self, member: usize)
	{
		let next = self.next_alive(0);
		if next == self.members.len()
		{
			self.active.remove(member);
		}
		else
		{
			self.active[member] = next;
		}
	}
}

#[derive(Debug)]
pub struct CommandAttack
{
	pub attack_index: usize,
	pub party: usize,
	pub monster: usize,
}

#[derive(Debug)]
pub enum CommandType
{
	Attack(CommandAttack),
	//Item(ItemId),
	//Switch(ToId),
	Escape,
}

#[derive(Debug)]
pub struct Command
{
	pub command_type: CommandType,
	pub party: usize,
	pub monster: usize,
}

impl Command
{
	fn new(command_type: CommandType, party: usize, monster: usize,) -> Self
	{
		Command
		{
			command_type: command_type,
			party: party,
			monster: monster,
		}
	}
}

impl Command
{
	fn cmp(command_self: &Command, monster_self: &Monster, command_other: &Command,
		monster_other: &Monster) -> Ordering
	{
		match command_self.command_type
		{
			CommandType::Attack(_) =>
			{
				if let CommandType::Attack(_) = command_other.command_type
				{
					monster_other.get_stat_speed().cmp(&monster_self.get_stat_speed())
				}
				else
				{
					Ordering::Greater
				}
			}
			CommandType::Escape =>
			{
				if let CommandType::Escape = command_other.command_type
				{
					let group = command_self.party.cmp(&command_other.party);
					if group == Ordering::Equal
					{
						command_self.monster.cmp(&command_other.monster)
					}
					else
					{
						group
					}
				}
				else
				{
					Ordering::Less
				}
			}
		}
	}
}

impl CommandType
{
	fn effects<'a, R: Rng>(&self, parties: &Vec<Party<'a>>, command: &Command, rng: &mut R) -> VecDeque<Effect>
	{
		let mut v = VecDeque::new();
		match *self
		{
			CommandType::Attack(ref target) =>
			{
				let offense = &parties[command.party].members[command.monster];
				let defense = &parties[target.party].members[target.monster];
				let damage = Damage
				{
					amount: calculate_damage(offense, 0, defense, false, 1f32, rng),
					party: target.party,
					monster: target.monster
				};
				v.push_back(Effect::Damage(damage));
			}
			CommandType::Escape =>
			{
				v.push_back(Effect::None(Reason::Escape));
			},
		}
		v
	}
}

#[derive(Debug)]
pub struct Damage
{
	amount: StatType,
	party: usize,
	monster: usize,
}

impl Damage
{
	pub fn amount(&self) -> StatType
	{
		self.amount
	}
	pub fn party(&self) -> usize
	{
		self.party
	}
	pub fn member(&self) -> usize
	{
		self.monster
	}
}

#[derive(Debug)]
pub enum Reason
{
	Critical,
	Escape,
}

#[derive(Debug)]
pub enum Effect
{
	Damage(Damage),
	// Status(StatusId),
	// Bonus(BonusType),
	// Ability(AbilityId),
	// Miss,
	// ,
	// Uneffective,
	// LessEffective,
	// SuperEffecitve,
	None(Reason),
}

#[derive(Debug)]
struct BattleCommand
{
	command: Command,
	effects: VecDeque<Effect>,
}

impl BattleCommand
{
	fn new<'a, R: Rng>(command: Command, parties: &Vec<Party<'a>>, rng: &mut R) -> Self
	{
		let effects = command.command_type.effects(parties, &command, rng);
		BattleCommand
		{
			effects: effects,
			command: command,
		}
	}
}

pub struct Battle<'a>
{
	/// Maps to the groups that have already added a command.
	ready: Vec<Vec<bool>>,

	/// True if the turn has started, false otherwise.
	started: bool,

	/// The total number of available participants.
	total: usize,

	/// The number of groups still waiting for a command.
	waiting: usize,

	/// The parties in this battle.
	parties: Vec<Party<'a>>,

	/// The list of executed commands, for playback.
	commands: Vec<BattleCommand>,

	/// The queue of upcoming commands in the next turn.
	queue: Vec<Command>,

	/// The current effect being executed.
	current: usize,

	rng: StdRng,

	// TODO: lingering effects.
}

pub enum BattleExecution
{
	Command,
	Queue,
	Waiting,
}

impl<'a> Battle<'a>
{
	pub fn new(parties: Vec<Party<'a>>) -> Self
	{
		let mut total = 0;
		let mut ready = Vec::with_capacity(parties.len());
		for group in parties.iter()
		{
			total += group.active_count();
			ready.push(vec![false; group.active_count()]);
		}
		Battle
		{
			ready: ready,
			started: false,
			total: total,
			waiting: total,
			parties: parties,
			commands: Vec::new(),
			queue: Vec::new(),
			current: 0,
			rng: StdRng::new().unwrap(),
		}
	}
	pub fn party(&self, index: usize) -> &Party<'a>
	{
		&self.parties[index]
	}
	pub fn monster(&self, party: usize, monster: usize) -> &Monster
	{
		&self.parties[party].members[monster]
	}
	pub fn monster_active(&self, party: usize, monster: usize) -> &Monster
	{
		self.parties[party].active_member(monster)
	}
	pub fn monster_active_count(&self, party: usize) -> usize
	{
		self.parties[party].active_count()
	}
	fn monster_command(&self, command: &Command) -> &Monster
	{
		self.monster(command.party, command.monster)
	}
	/// Adds a command to the turn queue. Returns true if the command is a valid command.
	pub fn add_command(&mut self, command: CommandType, party: usize, monster: usize) -> bool
	{
		if self.started
		{
			println!("Already starte1.");
			return false;
		}
		if party >= self.parties.len()
		{
			println!("Already len 1.");
			return false;
		}
		if self.ready[party][monster] == true
		{
			println!("Already ready {}.", monster);
			return false;
		}
		if monster >= self.parties[party].members.len()
		{
			println!("Already len.");
			return false
		}

		// TODO: Check if attack is valid against target.

		self.ready[party][monster] = true;
		self.waiting -= 1;
		println!("{} {:?}", self.waiting, self.ready);

		self.queue.push(Command::new(command, party, monster));
		true
	}

	fn execute_command(&mut self) -> BattleExecution
	{
		let mut min_index = 0;
		for index in 1..self.queue.len()
		{
			if Command::cmp(&self.queue[index], self.monster_command(&self.queue[index]),
				&self.queue[min_index], self.monster_command(&self.queue[min_index])) == Ordering::Less
			{
				min_index = index;
			}
		}
		let command = self.queue.swap_remove(min_index);
		if let CommandType::Attack(ref attack) = command.command_type
		{
			let target = self.parties[command.party].members.get_mut(command.monster).unwrap();
			target.get_attacks_mut()[attack.attack_index].limit_left_take(1);
		}

		let battle_command = BattleCommand::new(command, &self.parties, &mut self.rng);
		self.commands.push(battle_command);
		self.current = 0;
		BattleExecution::Command
	}

	/// Executes the next battle action.
	pub fn execute(&mut self) -> BattleExecution
	{
		if self.started
		{
			if self.current != self.commands.last().unwrap().effects.len()
			{
				self.apply_effect();

				self.current += 1;
				BattleExecution::Queue
			}
			else if !self.queue.is_empty()
			{
				self.execute_command()
			}
			else
			{
				// Reset the waiting for new commands.
				self.waiting = self.total;
				self.started = false;
				for ready_party in self.ready.iter_mut()
				{
					for ready in ready_party.iter_mut()
					{
						*ready = false;
					}
				}
				BattleExecution::Waiting
			}
		}
		else
		{
			if self.waiting != 0
			{
				BattleExecution::Waiting
			}
			else
			{
				// TODO: Insert lingering effects into priority queue.

				self.started = true;
				self.execute_command()
			}
		}
	}

	/// The current executing command.
	pub fn get_current_command(&self) -> Option<&Command>
	{
		self.commands.last().map(|battle_command| &battle_command.command)
	}

	/// The current executing result of the current executing command.
	pub fn get_current_effect(&self) -> Option<&Effect>
	{
		self.commands.last().map(|battle_command| &battle_command.effects[self.current - 1])
	}

	fn apply_effect(&mut self)
	{
		let battle_command = self.commands.last().unwrap();
		match battle_command.effects[self.current]
		{
			Effect::Damage(ref effect) =>
			{
				let dead =
				{
					let target = self.parties[effect.party].members.get_mut(effect.monster).unwrap();
					target.lose_health(effect.amount);
					target.get_health() == 0
				};

				if dead
				{
					self.parties.get_mut(effect.party).unwrap().active_update(effect.monster);

					// In case the dead monster's command exists in queue, remove it.
					for i in 0..self.queue.len()
					{
						if self.queue[i].party == effect.party &&
							self.queue[i].monster == effect.monster
						{
							self.queue.remove(i);
							break;
						}
					}

					// At this point, it doesn't matter which we remove because they're all false.
					self.ready[effect.party].pop();
					self.total -= 1;
				}
			}
			_ => ()
		}
	}
}
<|endoftext|>


<commit_before>extern crate rustful;
use rustful::{Server, Router, Request};

fn say_hello(request: &Request) -> ~str {
	let person = match request.variables.find(&~"person") {
		Some(name) => name.to_str(),
		None => ~"stranger"
	};
	format!("Hello, {}!", person.to_str())
}

fn main() {
	let routes = ~[
		("/", say_hello),
		("/:person", say_hello)
	];

	let server = Server {
		router: ~Router::from_vec(routes),
		port: 8080
	};

	server.run();
}<commit_msg>Removed unnecessary to_str<commit_after>extern crate rustful;
use rustful::{Server, Router, Request};

fn say_hello(request: &Request) -> ~str {
	let person = match request.variables.find(&~"person") {
		Some(name) => name.to_str(),
		None => ~"stranger"
	};
	format!("Hello, {}!", person)
}

fn main() {
	let routes = ~[
		("/", say_hello),
		("/:person", say_hello)
	];

	let server = Server {
		router: ~Router::from_vec(routes),
		port: 8080
	};

	server.run();
}<|endoftext|>


<commit_before><commit_msg>Add content of merge request module<commit_after>//! List merge requests
//!
//! https://docs.gitlab.com/ce/api/merge_requests.html#list-merge-requests
//!
//! # List merge requests
//!
//! Get all merge requests for this project.
//! The `state` parameter can be used to get only merge requests with a given state (`opened`, `closed`, or `merged`) or all of them (`all`).
//! The pagination parameters `page` and `per_page` can be used to restrict the list of merge requests.
//!
//! ```text
//! GET /projects/ID/merge_requests
//! GET /projects/ID/merge_requests?state=opened
//! GET /projects/ID/merge_requests?state=all
//! GET /projects/ID/merge_requests?iid=42
//! GET /projects/ID/merge_requests?iid[]=42&iid[]=43
//! ```
//!
//! Parameters:
//!
//! - `id` (required) - The ID of a project
//! - `iid` (optional) - Return the request having the given `iid`
//! - `state` (optional) - Return `all` requests or just those that are `merged`, `opened` or `closed`
//! - `order_by` (optional) - Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`
//! - `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
//!
//!

use BuildQuery;

use serde_json;

use gitlab::GitLab;
use MergeRequests;

// Types from serde_types.in.rs
use MergeRequestState;

// pub mod group;

impl GitLab {
    pub fn merge_requests(&self, listing: Listing) -> Result<MergeRequests, serde_json::Error> {
        let query = listing.build_query();
        self.get(&query)
    }
}

#[derive(Debug, Copy, Clone)]
pub enum ListingOrderBy {
    CreatedAt,
    UpdatedAt,
}

#[derive(Debug, Copy, Clone)]
pub enum ListingSort {
    Asc,
    Desc,
}

#[derive(Default, Debug, Clone)]
pub struct Listing {
    /// Project id
    id: i64,
    /// Merge request's IID
    iid: Vec<i64>,
    /// State of the requests
    state: Option<MergeRequestState>,
    /// Return requests ordered by. Default is `ListingOrderBy::CreatedAt`.
    order_by: Option<ListingOrderBy>,
    /// Return requests sorted. Default is `ListingSort::Desc`.
    sort: Option<ListingSort>,
}

#[allow(dead_code)]
impl Listing {
    pub fn new(id: i64) -> Listing {
        Listing {id: id, ..Default::default()}
    }
    pub fn iid(&mut self, iid: Vec<i64>) -> &mut Listing {
        self.iid = iid;
        self
    }
    pub fn state(&mut self, state: MergeRequestState) -> &mut Listing {
        self.state = Some(state);
        self
    }
    pub fn order_by(&mut self, order_by: ListingOrderBy) -> &mut Listing {
        self.order_by = Some(order_by);
        self
    }
    fn sort(&mut self, sort: ListingSort) -> &mut Listing {
        self.sort = Some(sort);
        self
    }
}

impl BuildQuery for Listing {
    fn build_query(&self) -> String {

        let mut query = format!("projects/{}/merge_requests", self.id);

        let amp_char = "&";
        let none_char = "";
        let mut split_char = &none_char;

        // Append a "?" only if at least one of the `Option` is `Some(_)` or if
        // strings contain something.
        query.push_str(match (self.iid.is_empty(),
                              &self.state,
                              &self.order_by,
                              &self.sort) {
            (true, &None, &None, &None) => "",
            _ => "?",
        });

        if !self.iid.is_empty() {
            query.push_str(split_char);
            split_char = &amp_char;

            if self.iid.len() == 1 {
                query.push_str("iid=");
                query.push_str(&self.iid[0].to_string());
            } else {
                let mut array_split_char = &none_char;
                for iid in &self.iid {
                    query.push_str(array_split_char);
                    query.push_str("iid[]=");
                    query.push_str(&iid.to_string());
                    array_split_char = &amp_char;
                }
            }
        }

        self.state.map(|state| {
            query.push_str(split_char);
            split_char = &amp_char;

            query.push_str("state=");
            query.push_str(match state {
                MergeRequestState::Merged => "merged",
                MergeRequestState::Opened => "opened",
                MergeRequestState::Closed => "closed",
                MergeRequestState::All => "all",
            });
        });

        self.order_by.map(|order_by| {
            query.push_str(split_char);
            split_char = &amp_char;

            query.push_str("order_by=");
            query.push_str(match order_by {
                ListingOrderBy::CreatedAt => "created_at",
                ListingOrderBy::UpdatedAt => "updated_at",
            });
        });

        self.sort.map(|sort| {
            query.push_str(split_char);
            split_char = &amp_char;

            query.push_str("sort=");
            query.push_str(match sort {
                ListingSort::Asc => "asc",
                ListingSort::Desc => "desc",
            });
        });

        query
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use BuildQuery;
    use MergeRequestState;

    #[test]
    fn build_query_default() {
        let expected_string = "projects/123/merge_requests";
        let listing = Listing {id: 123, ..Default::default()};
        let query = listing.build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects/123/merge_requests";
        let listing = Listing::new(123);
        let query = listing.build_query();
        assert_eq!(query, expected_string);
    }

    // /// Return requests ordered by. Default is `ListingOrderBy::CreatedAt`.
    // order_by: Option<ListingOrderBy>,
    // /// Return requests sorted. Default is `ListingSort::Desc`.
    // sort: Option<ListingSort>,

    #[test]
    fn build_query_iid() {
        let expected_string = format!("projects/123/merge_requests?iid=456");
        let query = Listing::new(123).iid(vec![456]).build_query();
        assert_eq!(query, expected_string);

        let expected_string = format!("projects/123/merge_requests?iid[]=456&iid[]=789");
        let query = Listing::new(123).iid(vec![456,789]).build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn build_query_state() {
        let expected_string = "projects/123/merge_requests?state=opened";
        let query = Listing::new(123).state(MergeRequestState::Opened).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects/123/merge_requests?state=closed";
        let query = Listing::new(123).state(MergeRequestState::Closed).build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn build_query_order_by() {
        let expected_string = "projects/123/merge_requests?order_by=created_at";
        let query = Listing::new(123).order_by(ListingOrderBy::CreatedAt).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects/123/merge_requests?order_by=updated_at";
        let query = Listing::new(123).order_by(ListingOrderBy::UpdatedAt).build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn build_query_sort() {
        let expected_string = "projects/123/merge_requests?sort=asc";
        let query = Listing::new(123).sort(ListingSort::Asc).build_query();
        assert_eq!(query, expected_string);

        let expected_string = "projects/123/merge_requests?sort=desc";
        let query = Listing::new(123).sort(ListingSort::Desc).build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn build_query_multiple() {
        let expected_string = "projects/123/merge_requests?iid[]=456&iid[]=789&order_by=created_at&sort=asc";
        let query = Listing::new(123).iid(vec![456,789]).sort(ListingSort::Asc).order_by(ListingOrderBy::CreatedAt).build_query();
        assert_eq!(query, expected_string);
    }
}
<|endoftext|>