<commit_before>use std::cmp;
use std::fmt::{Show,Formatter};
use std::fmt;
use std::slice;
use semver::Version;

use core::{
    Dependency,
    Manifest,
    PackageId,
    Registry,
    Target,
    Summary
};
use core::dependency::SerializedDependency;
use util::{CargoResult, graph, Config};
use serialize::{Encoder,Encodable};
use core::source::{SourceId, SourceSet, Source};

// TODO: Is manifest_path a relic?
#[deriving(Clone)]
pub struct Package {
    // The package's manifest
    manifest: Manifest,
    // The root of the package
    manifest_path: Path,
    // Where this package came from
    source_id: SourceId,
}

#[deriving(Encodable)]
struct SerializedPackage {
    name: String,
    version: String,
    dependencies: Vec<SerializedDependency>,
    authors: Vec<String>,
    targets: Vec<Target>,
    manifest_path: String,
}

impl<E, S: Encoder<E>> Encodable<S, E> for Package {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        let manifest = self.get_manifest();
        let summary = manifest.get_summary();
        let package_id = summary.get_package_id();

        SerializedPackage {
            name: package_id.get_name().to_string(),
            version: package_id.get_version().to_string(),
            dependencies: summary.get_dependencies().iter().map(|d| {
                SerializedDependency::from_dependency(d)
            }).collect(),
            authors: Vec::from_slice(manifest.get_authors()),
            targets: Vec::from_slice(manifest.get_targets()),
            manifest_path: self.manifest_path.display().to_string()
        }.encode(s)
    }
}

impl Package {
    pub fn new(manifest: Manifest,
               manifest_path: &Path,
               source_id: &SourceId) -> Package {
        Package {
            manifest: manifest,
            manifest_path: manifest_path.clone(),
            source_id: source_id.clone(),
        }
    }

    pub fn get_manifest(&self) -> &Manifest {
        &self.manifest
    }

    pub fn get_summary(&self) -> &Summary {
        self.manifest.get_summary()
    }

    pub fn get_package_id(&self) -> &PackageId {
        self.manifest.get_package_id()
    }

    pub fn get_name(&self) -> &str {
        self.get_package_id().get_name()
    }

    pub fn get_version(&self) -> &Version {
        self.get_package_id().get_version()
    }

    pub fn get_dependencies(&self) -> &[Dependency] {
        self.get_manifest().get_dependencies()
    }

    pub fn get_targets(&self) -> &[Target] {
        self.get_manifest().get_targets()
    }

    pub fn get_manifest_path(&self) -> &Path {
        &self.manifest_path
    }

    pub fn get_root(&self) -> Path {
        self.manifest_path.dir_path()
    }

    pub fn get_target_dir(&self) -> &Path {
        self.manifest.get_target_dir()
    }

    pub fn get_absolute_target_dir(&self) -> Path {
        self.get_root().join(self.get_target_dir())
    }

    pub fn get_source_ids(&self) -> Vec<SourceId> {
        let mut ret = vec!(self.source_id.clone());
        ret.push_all(self.manifest.get_source_ids());
        ret
    }

    pub fn get_fingerprint(&self, config: &mut Config) -> CargoResult<String> {
        let mut sources = self.get_source_ids();
        // Sort the sources just to make sure we have a consistent fingerprint.
        sources.sort_by(|a, b| {
            cmp::lexical_ordering(a.kind.cmp(&b.kind),
                                  a.location.to_string().cmp(&b.location.to_string()))
        });
        let sources = sources.iter().map(|source_id| {
            source_id.load(config)
        }).collect::<Vec<_>>();
        SourceSet::new(sources).fingerprint(self)
    }
}

impl Show for Package {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", self.get_summary().get_package_id())
    }
}

impl PartialEq for Package {
    fn eq(&self, other: &Package) -> bool {
        self.get_package_id() == other.get_package_id()
    }
}

#[deriving(PartialEq,Clone,Show)]
pub struct PackageSet {
    packages: Vec<Package>,
}

impl PackageSet {
    pub fn new(packages: &[Package]) -> PackageSet {
        //assert!(packages.len() > 0,
        //        "PackageSet must be created with at least one package")
        PackageSet { packages: Vec::from_slice(packages) }
    }

    pub fn len(&self) -> uint {
        self.packages.len()
    }

    pub fn pop(&mut self) -> Package {
        self.packages.pop().expect("PackageSet.pop: empty set")
    }

    /// Get a package by name out of the set
    pub fn get(&self, name: &str) -> &Package {
        self.packages.iter().find(|pkg| name == pkg.get_name())
            .expect("PackageSet.get: empty set")
    }

    pub fn get_all(&self, names: &[&str]) -> Vec<&Package> {
        names.iter().map(|name| self.get(*name) ).collect()
    }

    pub fn get_packages(&self) -> &[Package] {
        self.packages.as_slice()
    }

    // For now, assume that the package set contains only one package with a
    // given name
    pub fn sort(&self) -> Option<PackageSet> {
        let mut graph = graph::Graph::new();

        for pkg in self.packages.iter() {
            let deps: Vec<&str> = pkg.get_dependencies().iter()
                .map(|dep| dep.get_name())
                .collect();

            graph.add(pkg.get_name(), deps.as_slice());
        }

        let pkgs = some!(graph.sort()).iter().map(|name| {
            self.get(*name).clone()
        }).collect();

        Some(PackageSet {
            packages: pkgs
        })
    }

    pub fn iter(&self) -> slice::Items<Package> {
        self.packages.iter()
    }
}

impl Registry for PackageSet {
    fn query(&mut self, name: &Dependency) -> CargoResult<Vec<Summary>> {
        Ok(self.packages.iter()
            .filter(|pkg| name.get_name() == pkg.get_name())
            .map(|pkg| pkg.get_summary().clone())
            .collect())
    }
}
<commit_msg>auto merge of #237 : cburgdorf/cargo/fix_deprecation_warning, r=alexcrichton<commit_after>use std::fmt::{Show,Formatter};
use std::fmt;
use std::slice;
use semver::Version;

use core::{
    Dependency,
    Manifest,
    PackageId,
    Registry,
    Target,
    Summary
};
use core::dependency::SerializedDependency;
use util::{CargoResult, graph, Config};
use serialize::{Encoder,Encodable};
use core::source::{SourceId, SourceSet, Source};

// TODO: Is manifest_path a relic?
#[deriving(Clone)]
pub struct Package {
    // The package's manifest
    manifest: Manifest,
    // The root of the package
    manifest_path: Path,
    // Where this package came from
    source_id: SourceId,
}

#[deriving(Encodable)]
struct SerializedPackage {
    name: String,
    version: String,
    dependencies: Vec<SerializedDependency>,
    authors: Vec<String>,
    targets: Vec<Target>,
    manifest_path: String,
}

impl<E, S: Encoder<E>> Encodable<S, E> for Package {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        let manifest = self.get_manifest();
        let summary = manifest.get_summary();
        let package_id = summary.get_package_id();

        SerializedPackage {
            name: package_id.get_name().to_string(),
            version: package_id.get_version().to_string(),
            dependencies: summary.get_dependencies().iter().map(|d| {
                SerializedDependency::from_dependency(d)
            }).collect(),
            authors: Vec::from_slice(manifest.get_authors()),
            targets: Vec::from_slice(manifest.get_targets()),
            manifest_path: self.manifest_path.display().to_string()
        }.encode(s)
    }
}

impl Package {
    pub fn new(manifest: Manifest,
               manifest_path: &Path,
               source_id: &SourceId) -> Package {
        Package {
            manifest: manifest,
            manifest_path: manifest_path.clone(),
            source_id: source_id.clone(),
        }
    }

    pub fn get_manifest(&self) -> &Manifest {
        &self.manifest
    }

    pub fn get_summary(&self) -> &Summary {
        self.manifest.get_summary()
    }

    pub fn get_package_id(&self) -> &PackageId {
        self.manifest.get_package_id()
    }

    pub fn get_name(&self) -> &str {
        self.get_package_id().get_name()
    }

    pub fn get_version(&self) -> &Version {
        self.get_package_id().get_version()
    }

    pub fn get_dependencies(&self) -> &[Dependency] {
        self.get_manifest().get_dependencies()
    }

    pub fn get_targets(&self) -> &[Target] {
        self.get_manifest().get_targets()
    }

    pub fn get_manifest_path(&self) -> &Path {
        &self.manifest_path
    }

    pub fn get_root(&self) -> Path {
        self.manifest_path.dir_path()
    }

    pub fn get_target_dir(&self) -> &Path {
        self.manifest.get_target_dir()
    }

    pub fn get_absolute_target_dir(&self) -> Path {
        self.get_root().join(self.get_target_dir())
    }

    pub fn get_source_ids(&self) -> Vec<SourceId> {
        let mut ret = vec!(self.source_id.clone());
        ret.push_all(self.manifest.get_source_ids());
        ret
    }

    pub fn get_fingerprint(&self, config: &mut Config) -> CargoResult<String> {
        let mut sources = self.get_source_ids();
        // Sort the sources just to make sure we have a consistent fingerprint.
        sources.sort_by(|a, b| {
            let a = (&a.kind, a.location.to_string());
            let b = (&b.kind, b.location.to_string());
            a.cmp(&b)
        });
        let sources = sources.iter().map(|source_id| {
            source_id.load(config)
        }).collect::<Vec<_>>();
        SourceSet::new(sources).fingerprint(self)
    }
}

impl Show for Package {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", self.get_summary().get_package_id())
    }
}

impl PartialEq for Package {
    fn eq(&self, other: &Package) -> bool {
        self.get_package_id() == other.get_package_id()
    }
}

#[deriving(PartialEq,Clone,Show)]
pub struct PackageSet {
    packages: Vec<Package>,
}

impl PackageSet {
    pub fn new(packages: &[Package]) -> PackageSet {
        //assert!(packages.len() > 0,
        //        "PackageSet must be created with at least one package")
        PackageSet { packages: Vec::from_slice(packages) }
    }

    pub fn len(&self) -> uint {
        self.packages.len()
    }

    pub fn pop(&mut self) -> Package {
        self.packages.pop().expect("PackageSet.pop: empty set")
    }

    /// Get a package by name out of the set
    pub fn get(&self, name: &str) -> &Package {
        self.packages.iter().find(|pkg| name == pkg.get_name())
            .expect("PackageSet.get: empty set")
    }

    pub fn get_all(&self, names: &[&str]) -> Vec<&Package> {
        names.iter().map(|name| self.get(*name) ).collect()
    }

    pub fn get_packages(&self) -> &[Package] {
        self.packages.as_slice()
    }

    // For now, assume that the package set contains only one package with a
    // given name
    pub fn sort(&self) -> Option<PackageSet> {
        let mut graph = graph::Graph::new();

        for pkg in self.packages.iter() {
            let deps: Vec<&str> = pkg.get_dependencies().iter()
                .map(|dep| dep.get_name())
                .collect();

            graph.add(pkg.get_name(), deps.as_slice());
        }

        let pkgs = some!(graph.sort()).iter().map(|name| {
            self.get(*name).clone()
        }).collect();

        Some(PackageSet {
            packages: pkgs
        })
    }

    pub fn iter(&self) -> slice::Items<Package> {
        self.packages.iter()
    }
}

impl Registry for PackageSet {
    fn query(&mut self, name: &Dependency) -> CargoResult<Vec<Summary>> {
        Ok(self.packages.iter()
            .filter(|pkg| name.get_name() == pkg.get_name())
            .map(|pkg| pkg.get_summary().clone())
            .collect())
    }
}
<|endoftext|>


<commit_before>extern crate serde_json;
extern crate tempdir;

use std::path::PathBuf;
use std::sync::{
    mpsc::{channel, Receiver, Sender},
    Arc,
};
use std::thread;

use task_maker_cache::Cache;
use task_maker_dag::CacheMode;
use task_maker_exec::{executors::LocalExecutor, ExecutorClient};
use task_maker_format::ui::UIMessage;
use task_maker_format::{ioi, EvaluationConfig, EvaluationData, TaskFormat, UISender};
use task_maker_store::*;

use turingarena::evaluation::{mem::*, record};
use turingarena::score::Score;
use turingarena::submission::mem::Submission;

use turingarena::evaluation::Event;

pub fn run_evaluation(task_path: PathBuf, submission: Submission) -> Receiver<Event> {
    let (event_tx, event_rx) = channel();

    let store_path = tempdir::TempDir::new("task-maker").unwrap().into_path();
    let file_store =
        Arc::new(FileStore::new(store_path.join("store")).expect("Cannot create the file store"));

    let (tx, rx_remote) = channel();
    let (tx_remote, rx) = channel();

    let server_file_store = file_store.clone();
    thread::Builder::new()
        .name("Executor thread".into())
        .spawn(move || {
            let num_cores = num_cpus::get();
            let sandbox_path = store_path.join("sandboxes");
            let cache = Cache::new(store_path.join("cache")).expect("Cannot create the cache");
            let executor = LocalExecutor::new(server_file_store, num_cores, sandbox_path);

            executor.evaluate(tx_remote, rx_remote, cache).unwrap();
        })
        .expect("Failed to spawn the executor thread");

    thread::Builder::new()
        .name("Client thread".into())
        .spawn(move || {
            let dir = tempdir::TempDir::new("evaluation").unwrap();
            let solution_file = &submission.field_values[0].file;
            let solution_path = dir.path().join(&solution_file.name.0);
            std::fs::write(&solution_path, &solution_file.content)
                .expect("Unable to write solution file");
            println!("=={:?} start", solution_path);

            let (mut eval, receiver) = EvaluationData::new();

            let config = eval.dag.config_mut();

            thread::Builder::new()
                .name("Forwarder thread".into())
                .spawn(move || {
                    for m in receiver.iter() {
                        ui_message_to_events(m, &event_tx).expect("Failed to send event");
                    }
                })
                .expect("Failed to spawn the forwarder thread");

            config
                .keep_sandboxes(false)
                .dry_run(true)
                .cache_mode(CacheMode::Everything)
                .copy_exe(false)
                .extra_time(0.0);

            let eval_config = EvaluationConfig {
                solution_filter: vec![],
                booklet_solutions: false,
                solution_paths: vec![solution_path.to_owned()],
            };
            let task = ioi::Task::new(task_path, &eval_config).expect("Invalid task");
            task.execute(&mut eval, &eval_config)
                .expect("Failed to build the DAG");

            trace!("The DAG is: {:#?}", eval.dag);

            let ui_sender = eval.sender.clone();
            ExecutorClient::evaluate(eval.dag, tx, &rx, file_store, move |status| {
                ui_sender.send(UIMessage::ServerStatus { status })
            })
            .expect("Client failed");
        })
        .expect("Failed to spawn the executor thread");
    event_rx
}

fn ui_message_to_events(ui_message: UIMessage, tx: &Sender<Event>) -> Result<(), failure::Error> {
    match ui_message {
        UIMessage::IOITestcaseScore {
            subtask,
            testcase,
            solution,
            score,
            message,
        } => tx.send(Event::Value(ValueEvent {
            key: record::Key(format!("subtask.{}.testcase.{}.score", subtask, testcase)),
            value: record::Value::Score(record::ScoreValue {
                score: Score(score as f64),
            }),
        }))?,
        UIMessage::IOISubtaskScore {
            subtask,
            solution,
            score,
        } => {
            tx.send(Event::Value(ValueEvent {
                key: record::Key(format!("subtask.{}.score", subtask)),
                value: record::Value::Score(record::ScoreValue {
                    score: Score(score as f64),
                }),
            }))?;
            tx.send(Event::Score(ScoreEvent {
                scorable_id: format!("subtask.{}", subtask),
                score: Score(score as f64),
            }))?;
        },
        _ => (),
    };
    Ok(())
}
<commit_msg>task-maker: use simply `testcase.<id>` as case ID<commit_after>extern crate serde_json;
extern crate tempdir;

use std::path::PathBuf;
use std::sync::{
    mpsc::{channel, Receiver, Sender},
    Arc,
};
use std::thread;

use task_maker_cache::Cache;
use task_maker_dag::CacheMode;
use task_maker_exec::{executors::LocalExecutor, ExecutorClient};
use task_maker_format::ui::UIMessage;
use task_maker_format::{ioi, EvaluationConfig, EvaluationData, TaskFormat, UISender};
use task_maker_store::*;

use turingarena::evaluation::{mem::*, record};
use turingarena::score::Score;
use turingarena::submission::mem::Submission;

use turingarena::evaluation::Event;

pub fn run_evaluation(task_path: PathBuf, submission: Submission) -> Receiver<Event> {
    let (event_tx, event_rx) = channel();

    let store_path = tempdir::TempDir::new("task-maker").unwrap().into_path();
    let file_store =
        Arc::new(FileStore::new(store_path.join("store")).expect("Cannot create the file store"));

    let (tx, rx_remote) = channel();
    let (tx_remote, rx) = channel();

    let server_file_store = file_store.clone();
    thread::Builder::new()
        .name("Executor thread".into())
        .spawn(move || {
            let num_cores = num_cpus::get();
            let sandbox_path = store_path.join("sandboxes");
            let cache = Cache::new(store_path.join("cache")).expect("Cannot create the cache");
            let executor = LocalExecutor::new(server_file_store, num_cores, sandbox_path);

            executor.evaluate(tx_remote, rx_remote, cache).unwrap();
        })
        .expect("Failed to spawn the executor thread");

    thread::Builder::new()
        .name("Client thread".into())
        .spawn(move || {
            let dir = tempdir::TempDir::new("evaluation").unwrap();
            let solution_file = &submission.field_values[0].file;
            let solution_path = dir.path().join(&solution_file.name.0);
            std::fs::write(&solution_path, &solution_file.content)
                .expect("Unable to write solution file");
            println!("=={:?} start", solution_path);

            let (mut eval, receiver) = EvaluationData::new();

            let config = eval.dag.config_mut();

            thread::Builder::new()
                .name("Forwarder thread".into())
                .spawn(move || {
                    for m in receiver.iter() {
                        ui_message_to_events(m, &event_tx).expect("Failed to send event");
                    }
                })
                .expect("Failed to spawn the forwarder thread");

            config
                .keep_sandboxes(false)
                .dry_run(true)
                .cache_mode(CacheMode::Everything)
                .copy_exe(false)
                .extra_time(0.0);

            let eval_config = EvaluationConfig {
                solution_filter: vec![],
                booklet_solutions: false,
                solution_paths: vec![solution_path.to_owned()],
            };
            let task = ioi::Task::new(task_path, &eval_config).expect("Invalid task");
            task.execute(&mut eval, &eval_config)
                .expect("Failed to build the DAG");

            trace!("The DAG is: {:#?}", eval.dag);

            let ui_sender = eval.sender.clone();
            ExecutorClient::evaluate(eval.dag, tx, &rx, file_store, move |status| {
                ui_sender.send(UIMessage::ServerStatus { status })
            })
            .expect("Client failed");
        })
        .expect("Failed to spawn the executor thread");
    event_rx
}

fn ui_message_to_events(ui_message: UIMessage, tx: &Sender<Event>) -> Result<(), failure::Error> {
    match ui_message {
        UIMessage::IOITestcaseScore {
            subtask,
            testcase,
            solution,
            score,
            message,
        } => tx.send(Event::Value(ValueEvent {
            key: record::Key(format!("testcase.{}.score", testcase)),
            value: record::Value::Score(record::ScoreValue {
                score: Score(score as f64),
            }),
        }))?,
        UIMessage::IOISubtaskScore {
            subtask,
            solution,
            score,
        } => {
            tx.send(Event::Value(ValueEvent {
                key: record::Key(format!("subtask.{}.score", subtask)),
                value: record::Value::Score(record::ScoreValue {
                    score: Score(score as f64),
                }),
            }))?;
            tx.send(Event::Score(ScoreEvent {
                scorable_id: format!("subtask.{}", subtask),
                score: Score(score as f64),
            }))?;
        },
        _ => (),
    };
    Ok(())
}
<|endoftext|>


<commit_before>use config::gobjects::GObject;
use config::identables::Identables;
use env::Env;
use library;
use nameutil;
use super::trampolines;
use super::imports::Imports;
use version::Version;

#[derive(Debug)]
pub struct Info {
    pub connect_name: String,
    pub signal_name: String,
    pub trampoline_name: Option<String>, //TODO: remove Option
    pub version: Option<Version>,
    pub deprecated_version: Option<Version>,
}

pub fn analyze(env: &Env, signals: &[library::Signal], type_tid: library::TypeId,
               in_trait: bool, trampolines: &mut trampolines::Trampolines,
               obj: &GObject, imports: &mut Imports) -> Vec<Info> {
    let mut sns = Vec::new();

    for signal in signals {
        let configured_signals = obj.signals.matched(&signal.name);
        if configured_signals.iter().any(|f| f.ignore) {
            continue;
        }

        let info = analyze_signal(env, signal, type_tid, in_trait, trampolines, imports);
        if let Some(info) = info {
            sns.push(info);
        }
    }

    sns
}

fn analyze_signal(env: &Env, signal: &library::Signal, type_tid: library::TypeId,
                  in_trait: bool, trampolines: &mut trampolines::Trampolines,
                  imports: &mut Imports) -> Option<Info> {
    let mut used_types: Vec<String> = Vec::with_capacity(4);
    let version = signal.version;
    let deprecated_version = signal.deprecated_version;

    let connect_name = format!("connect_{}", nameutil::signal_to_snake(&signal.name));
    let trampoline_name = trampolines::analyze(env, signal, type_tid, in_trait, trampolines,
                                               &mut used_types, version);

    if trampoline_name.is_some() {
        imports.add_used_types(&used_types, version);
        if in_trait {
            imports.add("Object", version);
        }
        imports.add("glib::signal::connect", version);
        imports.add("std::mem::transmute", version);
        imports.add("std::boxed::Box as Box_", version);
        imports.add("glib_ffi::gpointer", version);
    }

    let info = Info {
        connect_name: connect_name,
        signal_name: signal.name.clone(),
        trampoline_name: trampoline_name,
        version: version,
        deprecated_version: deprecated_version,
    };
    Some(info)
}
<commit_msg>Add use Downcast<commit_after>use config::gobjects::GObject;
use config::identables::Identables;
use env::Env;
use library;
use nameutil;
use super::trampolines;
use super::imports::Imports;
use version::Version;

#[derive(Debug)]
pub struct Info {
    pub connect_name: String,
    pub signal_name: String,
    pub trampoline_name: Option<String>, //TODO: remove Option
    pub version: Option<Version>,
    pub deprecated_version: Option<Version>,
}

pub fn analyze(env: &Env, signals: &[library::Signal], type_tid: library::TypeId,
               in_trait: bool, trampolines: &mut trampolines::Trampolines,
               obj: &GObject, imports: &mut Imports) -> Vec<Info> {
    let mut sns = Vec::new();

    for signal in signals {
        let configured_signals = obj.signals.matched(&signal.name);
        if configured_signals.iter().any(|f| f.ignore) {
            continue;
        }

        let info = analyze_signal(env, signal, type_tid, in_trait, trampolines, imports);
        if let Some(info) = info {
            sns.push(info);
        }
    }

    sns
}

fn analyze_signal(env: &Env, signal: &library::Signal, type_tid: library::TypeId,
                  in_trait: bool, trampolines: &mut trampolines::Trampolines,
                  imports: &mut Imports) -> Option<Info> {
    let mut used_types: Vec<String> = Vec::with_capacity(4);
    let version = signal.version;
    let deprecated_version = signal.deprecated_version;

    let connect_name = format!("connect_{}", nameutil::signal_to_snake(&signal.name));
    let trampoline_name = trampolines::analyze(env, signal, type_tid, in_trait, trampolines,
                                               &mut used_types, version);

    if trampoline_name.is_some() {
        imports.add_used_types(&used_types, version);
        if in_trait {
            imports.add("Object", version);
            imports.add("glib::object::Downcast", version);
        }
        imports.add("glib::signal::connect", version);
        imports.add("std::mem::transmute", version);
        imports.add("std::boxed::Box as Box_", version);
        imports.add("glib_ffi::gpointer", version);
    }

    let info = Info {
        connect_name: connect_name,
        signal_name: signal.name.clone(),
        trampoline_name: trampoline_name,
        version: version,
        deprecated_version: deprecated_version,
    };
    Some(info)
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;

use crate::types::*;
use crate::data_types::*;
use crate::web::config::*;
use crate::web::cmp_utils::cmp_residues;
use crate::web::util::*;

use pombase_rc_string::RcString;

fn gene_display_name(gene: &GeneDetails) -> RcString {
    if let Some(ref name) = gene.name {
        name.clone()
    } else {
        gene.uniquename.clone()
    }
}

fn string_from_ext_range(ext_range: &ExtRange,
                          genes: &UniquenameGeneMap, terms: &TermIdDetailsMap) -> RcString {
    match *ext_range {
        ExtRange::Gene(ref gene_uniquename) | ExtRange::Promoter(ref gene_uniquename) => {
            let gene = genes.get(gene_uniquename)
                .unwrap_or_else(|| panic!("can't find gene: {}", gene_uniquename));
            gene_display_name(gene)
        },
        ExtRange::Transcript(ref transcript_uniquename) => transcript_uniquename.clone(),
        ExtRange::SummaryGenes(_) => panic!("can't handle SummaryGenes\n"),
        ExtRange::SummaryTranscripts(_) => panic!("can't handle SummaryTranscripts\n"),
        ExtRange::Term(ref termid) => RcString::from(&terms.get(termid).unwrap().name),
        ExtRange::SummaryModifiedResidues(ref residue) => RcString::from(&residue.join(",")),
        ExtRange::SummaryTerms(_) => panic!("can't handle SummaryGenes\n"),
        ExtRange::Misc(ref misc) => misc.clone(),
        ExtRange::Domain(ref domain) => domain.clone(),
        ExtRange::GeneProduct(ref gene_product) => gene_product.clone(),
        ExtRange::GeneAndGeneProduct(ref gene_and_gene_product) =>
            RcString::from(&format!("{} ({})", gene_and_gene_product.gene_uniquename,
                                    gene_and_gene_product.product)),
    }
}

fn cmp_ext_part(ext_part1: &ExtPart, ext_part2: &ExtPart,
                genes: &UniquenameGeneMap,
                terms: &TermIdDetailsMap) -> Ordering {
    let ord = ext_part1.rel_type_display_name.cmp(&ext_part2.rel_type_display_name);

    if ord == Ordering::Equal {
        let ext_part1_str = string_from_ext_range(&ext_part1.ext_range, genes, terms);
        let ext_part2_str = string_from_ext_range(&ext_part2.ext_range, genes, terms);

        ext_part1_str.to_lowercase().cmp(&ext_part2_str.to_lowercase())
    } else {
        ord
    }
}

// compare the extension up to the last common index
fn cmp_extension_prefix(cv_config: &CvConfig, ext1: &[ExtPart], ext2: &[ExtPart],
                        genes: &UniquenameGeneMap,
                        terms: &TermIdDetailsMap) -> Ordering {
    let conf_rel_ranges = &cv_config.summary_relation_ranges_to_collect;

    let is_grouping_rel_name =
        |ext: &ExtPart| !conf_rel_ranges.contains(&ext.rel_type_name);

    // put the extension that will be grouped in the summary at the end
    // See: https://github.com/pombase/pombase-chado/issues/636
    let (mut ext1_for_cmp, ext1_rest): (Vec<ExtPart>, Vec<ExtPart>) =
        ext1.to_vec().into_iter().partition(&is_grouping_rel_name);
    ext1_for_cmp.extend(ext1_rest);

    let (mut ext2_for_cmp, ext2_rest): (Vec<ExtPart>, Vec<ExtPart>) =
        ext2.to_vec().into_iter().partition(&is_grouping_rel_name);
    ext2_for_cmp.extend(ext2_rest);

    let iter = ext1_for_cmp.iter().zip(&ext2_for_cmp).enumerate();
    for (_, (ext1_part, ext2_part)) in iter {
        let ord = cmp_ext_part(ext1_part, ext2_part, genes, terms);

        if ord != Ordering::Equal {
            return ord
        }
    }

    Ordering::Equal
}

fn cmp_extension(cv_config: &CvConfig, ext1: &[ExtPart], ext2: &[ExtPart],
                 genes: &UniquenameGeneMap,
                 terms: &TermIdDetailsMap) -> Ordering {
    let cmp = cmp_extension_prefix(cv_config, ext1, ext2, genes, terms);
    if cmp == Ordering::Equal {
        ext1.len().cmp(&ext2.len())
    } else {
        cmp
    }
}

fn cmp_genotypes(genotype1: &GenotypeDetails, genotype2: &GenotypeDetails) -> Ordering {
    genotype1.display_uniquename.to_lowercase().cmp(&genotype2.display_uniquename.to_lowercase())
}

// compare two gene vectors which must be ordered vecs
fn cmp_gene_vec(genes: &UniquenameGeneMap,
                gene_vec1: &[GeneUniquename],
                gene_vec2: &[GeneUniquename]) -> Ordering {

    let gene_short_vec1: Vec<GeneShort> =
        gene_vec1.iter().map(|gene_uniquename: &RcString| {
            make_gene_short(genes, gene_uniquename)
        }).collect();
    let gene_short_vec2: Vec<GeneShort> =
        gene_vec2.iter().map(|gene_uniquename: &RcString| {
            make_gene_short(genes, gene_uniquename)
        }).collect();

    gene_short_vec1.cmp(&gene_short_vec2)
}

pub fn cmp_ont_annotation_detail(cv_config: &CvConfig,
                                 detail1: &OntAnnotationDetail,
                                 detail2: &OntAnnotationDetail,
                                 genes: &UniquenameGeneMap,
                                 genotypes: &UniquenameGenotypeMap,
                                 terms: &TermIdDetailsMap) -> Result<Ordering, String> {
    if let Some(ref detail1_genotype_uniquename) = detail1.genotype {
        if let Some(ref detail2_genotype_uniquename) = detail2.genotype {
            let genotype1 = genotypes.get(detail1_genotype_uniquename).unwrap();
            let genotype2 = genotypes.get(detail2_genotype_uniquename).unwrap();

            let ord = cmp_genotypes(genotype1, genotype2);

            if ord == Ordering::Equal {
                Ok(cmp_extension(cv_config, &detail1.extension, &detail2.extension,
                                 genes, terms))
            } else {
                Ok(ord)
            }
        } else {
            Err(format!("comparing two OntAnnotationDetail but one has a genotype and
one a gene:\n{:?}\n{:?}\n", detail1, detail2))
        }
    } else {
        if detail2.genotype.is_some() {
            Err(format!("comparing two OntAnnotationDetail but one has a genotype and
one a gene:\n{:?}\n{:?}\n", detail1, detail2))
        } else {
            let ord = cmp_gene_vec(genes, &detail1.genes, &detail2.genes);

            if ord == Ordering::Equal {
                if let Some(ref sort_details_by) = cv_config.sort_details_by {
                    for sort_type in sort_details_by {
                        if sort_type == "modification" {
                            let res = cmp_residues(&detail1.residue, &detail2.residue);
                            if res != Ordering::Equal {
                                return Ok(res);
                            }
                        } else {
                            let res = cmp_extension(cv_config, &detail1.extension,
                                                    &detail2.extension, genes, terms);
                            if res != Ordering::Equal {
                                return Ok(res);
                            }
                        }
                    }
                    Ok(Ordering::Equal)
                } else {
                    Ok(cmp_extension(cv_config, &detail1.extension, &detail2.extension,
                                     genes, terms))
                }
            } else {
                Ok(ord)
            }
        }
    }
}

pub fn sort_cv_annotation_details<T: AnnotationContainer>
    (container: &mut T,
     config: &Config,
     gene_map: &UniquenameGeneMap,
     genotype_map: &UniquenameGenotypeMap,
     term_map: &TermIdDetailsMap,
     annotation_details_map: &IdOntAnnotationDetailMap)
{

    let detail_cmp_using_cv_name = |cv_name: &str| {
        let cv_config = config.cv_config.get(cv_name);

        move |id1: &i32, id2: &i32| {
            let annotation1: &OntAnnotationDetail =
                annotation_details_map.get(id1).expect("can't find OntAnnotationDetail");
            let annotation2: &OntAnnotationDetail =
                annotation_details_map.get(id2).expect("can't find OntAnnotationDetail");

            if let Some(cv_config) = cv_config {
                let result =
                    cmp_ont_annotation_detail(cv_config,
                                              annotation1, annotation2,
                                              gene_map,
                                              genotype_map,
                                              term_map);
                result.unwrap_or_else(|err| panic!("error from cmp_ont_annotation_detail: {}", err))
            } else {
                Ordering::Equal
            }
        }
    };

    for (_, term_annotations) in container.cv_annotations_mut() {
        for term_annotation in term_annotations {
            let termid = &term_annotation.term;
            if let Some(term_details) = term_map.get(termid) {
                let cmp = detail_cmp_using_cv_name(&term_details.cv_name);
                term_annotation.annotations.sort_by(cmp);
            } else {
                panic!("failed to find TermDetails for {}", termid);
            }
        }
    }
}
<commit_msg>Cope with displaying condition term pages<commit_after>use std::cmp::Ordering;

use crate::types::*;
use crate::data_types::*;
use crate::web::config::*;
use crate::web::cmp_utils::cmp_residues;
use crate::web::util::*;

use pombase_rc_string::RcString;

fn gene_display_name(gene: &GeneDetails) -> RcString {
    if let Some(ref name) = gene.name {
        name.clone()
    } else {
        gene.uniquename.clone()
    }
}

fn string_from_ext_range(ext_range: &ExtRange,
                          genes: &UniquenameGeneMap, terms: &TermIdDetailsMap) -> RcString {
    match *ext_range {
        ExtRange::Gene(ref gene_uniquename) | ExtRange::Promoter(ref gene_uniquename) => {
            let gene = genes.get(gene_uniquename)
                .unwrap_or_else(|| panic!("can't find gene: {}", gene_uniquename));
            gene_display_name(gene)
        },
        ExtRange::Transcript(ref transcript_uniquename) => transcript_uniquename.clone(),
        ExtRange::SummaryGenes(_) => panic!("can't handle SummaryGenes\n"),
        ExtRange::SummaryTranscripts(_) => panic!("can't handle SummaryTranscripts\n"),
        ExtRange::Term(ref termid) => RcString::from(&terms.get(termid).unwrap().name),
        ExtRange::SummaryModifiedResidues(ref residue) => RcString::from(&residue.join(",")),
        ExtRange::SummaryTerms(_) => panic!("can't handle SummaryGenes\n"),
        ExtRange::Misc(ref misc) => misc.clone(),
        ExtRange::Domain(ref domain) => domain.clone(),
        ExtRange::GeneProduct(ref gene_product) => gene_product.clone(),
        ExtRange::GeneAndGeneProduct(ref gene_and_gene_product) =>
            RcString::from(&format!("{} ({})", gene_and_gene_product.gene_uniquename,
                                    gene_and_gene_product.product)),
    }
}

fn cmp_ext_part(ext_part1: &ExtPart, ext_part2: &ExtPart,
                genes: &UniquenameGeneMap,
                terms: &TermIdDetailsMap) -> Ordering {
    let ord = ext_part1.rel_type_display_name.cmp(&ext_part2.rel_type_display_name);

    if ord == Ordering::Equal {
        let ext_part1_str = string_from_ext_range(&ext_part1.ext_range, genes, terms);
        let ext_part2_str = string_from_ext_range(&ext_part2.ext_range, genes, terms);

        ext_part1_str.to_lowercase().cmp(&ext_part2_str.to_lowercase())
    } else {
        ord
    }
}

// compare the extension up to the last common index
fn cmp_extension_prefix(cv_config: &CvConfig, ext1: &[ExtPart], ext2: &[ExtPart],
                        genes: &UniquenameGeneMap,
                        terms: &TermIdDetailsMap) -> Ordering {
    let conf_rel_ranges = &cv_config.summary_relation_ranges_to_collect;

    let is_grouping_rel_name =
        |ext: &ExtPart| !conf_rel_ranges.contains(&ext.rel_type_name);

    // put the extension that will be grouped in the summary at the end
    // See: https://github.com/pombase/pombase-chado/issues/636
    let (mut ext1_for_cmp, ext1_rest): (Vec<ExtPart>, Vec<ExtPart>) =
        ext1.to_vec().into_iter().partition(&is_grouping_rel_name);
    ext1_for_cmp.extend(ext1_rest);

    let (mut ext2_for_cmp, ext2_rest): (Vec<ExtPart>, Vec<ExtPart>) =
        ext2.to_vec().into_iter().partition(&is_grouping_rel_name);
    ext2_for_cmp.extend(ext2_rest);

    let iter = ext1_for_cmp.iter().zip(&ext2_for_cmp).enumerate();
    for (_, (ext1_part, ext2_part)) in iter {
        let ord = cmp_ext_part(ext1_part, ext2_part, genes, terms);

        if ord != Ordering::Equal {
            return ord
        }
    }

    Ordering::Equal
}

fn cmp_extension(cv_config: &CvConfig, ext1: &[ExtPart], ext2: &[ExtPart],
                 genes: &UniquenameGeneMap,
                 terms: &TermIdDetailsMap) -> Ordering {
    let cmp = cmp_extension_prefix(cv_config, ext1, ext2, genes, terms);
    if cmp == Ordering::Equal {
        ext1.len().cmp(&ext2.len())
    } else {
        cmp
    }
}

fn cmp_genotypes(genotype1: &GenotypeDetails, genotype2: &GenotypeDetails) -> Ordering {
    genotype1.display_uniquename.to_lowercase().cmp(&genotype2.display_uniquename.to_lowercase())
}

// compare two gene vectors which must be ordered vecs
fn cmp_gene_vec(genes: &UniquenameGeneMap,
                gene_vec1: &[GeneUniquename],
                gene_vec2: &[GeneUniquename]) -> Ordering {

    let gene_short_vec1: Vec<GeneShort> =
        gene_vec1.iter().map(|gene_uniquename: &RcString| {
            make_gene_short(genes, gene_uniquename)
        }).collect();
    let gene_short_vec2: Vec<GeneShort> =
        gene_vec2.iter().map(|gene_uniquename: &RcString| {
            make_gene_short(genes, gene_uniquename)
        }).collect();

    gene_short_vec1.cmp(&gene_short_vec2)
}

pub fn cmp_ont_annotation_detail(cv_config: &CvConfig,
                                 detail1: &OntAnnotationDetail,
                                 detail2: &OntAnnotationDetail,
                                 genes: &UniquenameGeneMap,
                                 genotypes: &UniquenameGenotypeMap,
                                 terms: &TermIdDetailsMap) -> Result<Ordering, String> {
    if let Some(ref detail1_genotype_uniquename) = detail1.genotype {
        if let Some(ref detail2_genotype_uniquename) = detail2.genotype {
            let genotype1 = genotypes.get(detail1_genotype_uniquename).unwrap();
            let genotype2 = genotypes.get(detail2_genotype_uniquename).unwrap();

            let ord = cmp_genotypes(genotype1, genotype2);

            if ord == Ordering::Equal {
                Ok(cmp_extension(cv_config, &detail1.extension, &detail2.extension,
                                 genes, terms))
            } else {
                Ok(ord)
            }
        } else {
            // needed to display the FYECO term pages
            Ok(Ordering::Less)
        }
    } else {
        if detail2.genotype.is_some() {
            // needed to display the FYECO term pages
            Ok(Ordering::Greater)
        } else {
            let ord = cmp_gene_vec(genes, &detail1.genes, &detail2.genes);

            if ord == Ordering::Equal {
                if let Some(ref sort_details_by) = cv_config.sort_details_by {
                    for sort_type in sort_details_by {
                        if sort_type == "modification" {
                            let res = cmp_residues(&detail1.residue, &detail2.residue);
                            if res != Ordering::Equal {
                                return Ok(res);
                            }
                        } else {
                            let res = cmp_extension(cv_config, &detail1.extension,
                                                    &detail2.extension, genes, terms);
                            if res != Ordering::Equal {
                                return Ok(res);
                            }
                        }
                    }
                    Ok(Ordering::Equal)
                } else {
                    Ok(cmp_extension(cv_config, &detail1.extension, &detail2.extension,
                                     genes, terms))
                }
            } else {
                Ok(ord)
            }
        }
    }
}

pub fn sort_cv_annotation_details<T: AnnotationContainer>
    (container: &mut T,
     config: &Config,
     gene_map: &UniquenameGeneMap,
     genotype_map: &UniquenameGenotypeMap,
     term_map: &TermIdDetailsMap,
     annotation_details_map: &IdOntAnnotationDetailMap)
{

    let detail_cmp_using_cv_name = |cv_name: &str| {
        let cv_config = config.cv_config.get(cv_name);

        move |id1: &i32, id2: &i32| {
            let annotation1: &OntAnnotationDetail =
                annotation_details_map.get(id1).expect("can't find OntAnnotationDetail");
            let annotation2: &OntAnnotationDetail =
                annotation_details_map.get(id2).expect("can't find OntAnnotationDetail");

            if let Some(cv_config) = cv_config {
                let result =
                    cmp_ont_annotation_detail(cv_config,
                                              annotation1, annotation2,
                                              gene_map,
                                              genotype_map,
                                              term_map);
                result.unwrap_or_else(|err| panic!("error from cmp_ont_annotation_detail: {}", err))
            } else {
                Ordering::Equal
            }
        }
    };

    for (_, term_annotations) in container.cv_annotations_mut() {
        for term_annotation in term_annotations {
            let termid = &term_annotation.term;
            if let Some(term_details) = term_map.get(termid) {
                let cmp = detail_cmp_using_cv_name(&term_details.cv_name);
                term_annotation.annotations.sort_by(cmp);
            } else {
                panic!("failed to find TermDetails for {}", termid);
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::result;

use analysis::ref_mode::RefMode;
use env::Env;
use library::{self, Nullable};
use super::conversion_type::ConversionType;
use traits::*;

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TypeError {
    Ignored(String),
    Mismatch(String),
    Unimplemented(String),
}

pub type Result = result::Result<String, TypeError>;

fn into_inner(res: Result) -> String {
    use self::TypeError::*;
    match res {
        Ok(s) |
            Err(Ignored(s)) |
            Err(Mismatch(s)) |
            Err(Unimplemented(s)) => s,
    }
}

impl IntoString for Result {
    fn into_string(self) -> String {
        use self::TypeError::*;
        match self {
            Ok(s) => s,
            Err(Ignored(s)) => format!("/*Ignored*/{}", s),
            Err(Mismatch(s)) => format!("/*Metadata mismatch*/{}", s),
            Err(Unimplemented(s)) => format!("/*Unimplemented*/{}", s),
        }
    }
}

impl MapAny<String> for Result {
    fn map_any<F: FnOnce(String) -> String>(self, op: F) -> Result {
        use self::TypeError::*;
        match self {
            Ok(s) => Ok(op(s)),
            Err(Ignored(s)) => Err(Ignored(op(s))),
            Err(Mismatch(s)) => Err(Mismatch(op(s))),
            Err(Unimplemented(s)) => Err(Unimplemented(op(s))),
        }
    }
}

pub fn rust_type(env: &Env, type_id: library::TypeId) -> Result {
    rust_type_full(env, type_id, Nullable(false), RefMode::None)
}

pub fn bounds_rust_type(env: &Env, type_id: library::TypeId) -> Result {
    rust_type_full(env, type_id, Nullable(false), RefMode::ByRefFake)
}

fn rust_type_full(env: &Env, type_id: library::TypeId, nullable: Nullable, ref_mode: RefMode) -> Result {
    use library::Type::*;
    use library::Fundamental::*;
    let ok = |s: &str| Ok(s.into());
    let err = |s: &str| Err(TypeError::Unimplemented(s.into()));
    let mut skip_option = false;
    let type_ = env.library.type_(type_id);
    let mut rust_type = match *type_ {
        Fundamental(fund) => {
            match fund {
                None => err("()"),
                Boolean => ok("bool"),
                Int8 => ok("i8"),
                UInt8 => ok("u8"),
                Int16 => ok("i16"),
                UInt16 => ok("u16"),
                Int32 => ok("i32"),
                UInt32 => ok("u32"),
                Int64 => ok("i64"),
                UInt64 => ok("u64"),

                Int => ok("i32"),      //maybe dependent on target system
                UInt => ok("u32"),     //maybe dependent on target system

                Short => ok("libc::c_short"),   //depends of target system
                UShort => ok("libc::c_ushort"), //depends of target system
                Long => ok("libc::c_long"),     //depends of target system
                ULong => ok("libc::c_ulong"),   //depends of target system

                Float => ok("f32"),
                Double => ok("f64"),

                UniChar => ok("char"),
                Utf8 => if ref_mode.is_ref() { ok("str") } else { ok("String") },
                Filename => {
                    if ref_mode.is_ref() {
                        ok("std::path::Path")
                    } else {
                        ok("std::path::PathBuf")
                    }
                }
                Type => ok("glib::types::Type"),
                Unsupported => err("Unsupported"),
                _ => err(&format!("Fundamental: {:?}", fund)),
            }
        }
        Alias(ref alias) => {
            rust_type_full(env, alias.typ, nullable, ref_mode)
                .map_any(|_| alias.name.clone())
        }
        Record(library::Record { ref c_type, .. }) if c_type == "GVariantType" => {
            if ref_mode.is_ref() { ok("VariantTy") } else { ok("VariantType") }
        }
        Enumeration(..) |
            Bitfield(..) |
            Record(..) |
            Union(..) |
            Class(..) |
            Interface(..) => {
            let name = type_.get_name().to_owned();
            if env.type_status(&type_id.full_name(&env.library)).ignored() {
                Err(TypeError::Ignored(name))
            }
            else {
                Ok(name)
            }
        }
        List(inner_tid) |
            SList(inner_tid) |
            CArray(inner_tid)
            if ConversionType::of(&env.library, inner_tid) == ConversionType::Pointer => {
            skip_option = true;
            let inner_ref_mode = match *env.library.type_(inner_tid) {
                Class(..) |
                    Interface(..) => RefMode::None,
                _ => ref_mode,
            };
            rust_type_full(env, inner_tid, Nullable(false), inner_ref_mode)
                .map_any(|s| if ref_mode.is_ref() {
                    format!("[{}]", s)
                } else {
                    format!("Vec<{}>", s)
                })
        }
        _ => Err(TypeError::Unimplemented(type_.get_name().to_owned())),
    };

    if type_id.ns_id != library::MAIN_NAMESPACE && type_id.ns_id != library::INTERNAL_NAMESPACE
        && !implemented_in_main_namespace(&env.library, type_id) {
        if env.type_status(&type_id.full_name(&env.library)).ignored() {
            rust_type = Err(TypeError::Ignored(into_inner(rust_type)));
        }
        rust_type = rust_type.map_any(|s| format!("{}::{}",
            env.namespaces[type_id.ns_id].higher_crate_name, s));
    }

    match ref_mode {
        RefMode::None | RefMode::ByRefFake => {}
        RefMode::ByRef | RefMode::ByRefImmut => rust_type = rust_type.map_any(|s| format!("&{}", s)),
        RefMode::ByRefMut => rust_type = rust_type.map_any(|s| format!("&mut {}", s)),
    }
    if *nullable && !skip_option {
        match ConversionType::of(&env.library, type_id) {
            ConversionType::Pointer
                | ConversionType::Scalar => {
                rust_type = rust_type.map_any(|s| format!("Option<{}>", s))
            }
            _ => (),
        }
    }

    rust_type
}

pub fn used_rust_type(env: &Env, type_id: library::TypeId) -> Result {
    use library::Type::*;
    match *env.library.type_(type_id) {
        Fundamental(library::Fundamental::Type) |
            Fundamental(library::Fundamental::Short) |
            Fundamental(library::Fundamental::UShort) |
            Fundamental(library::Fundamental::Long) |
            Fundamental(library::Fundamental::ULong) |
            Fundamental(library::Fundamental::Filename) |
            Alias(..) |
            Bitfield(..) |
            Record(..) |
            Union(..) |
            Class(..) |
            Enumeration(..) |
            Interface(..) => rust_type(env, type_id),
        List(inner_tid) |
            SList(inner_tid) |
            CArray(inner_tid) => used_rust_type(env, inner_tid),
        _ => Err(TypeError::Ignored("Don't need use".to_owned())),
    }
}

pub fn parameter_rust_type(env: &Env, type_id:library::TypeId,
                           direction: library::ParameterDirection, nullable: Nullable,
                           ref_mode: RefMode) -> Result {
    use library::Type::*;
    let type_ = env.library.type_(type_id);
    let rust_type = rust_type_full(env, type_id, nullable, ref_mode);
    match *type_ {
        Fundamental(fund) => {
            if fund == library::Fundamental::Utf8 || fund == library::Fundamental::Filename {
                match direction {
                    library::ParameterDirection::In |
                        library::ParameterDirection::Return => rust_type,
                    _ => Err(TypeError::Unimplemented(into_inner(rust_type))),
                }
            } else {
                rust_type.map_any(|s| format_parameter(s, direction))
            }
        }

        Alias(ref alias) => {
            rust_type.and_then(|s| {
                parameter_rust_type(env, alias.typ, direction, nullable, ref_mode)
                    .map_any(|_| s)
            })
                .map_any(|s| format_parameter(s, direction))
        }

        Enumeration(..) |
            Union(..) |
            Bitfield(..) => rust_type.map_any(|s| format_parameter(s, direction)),

        Record(..) => {
            if direction == library::ParameterDirection::InOut {
                Err(TypeError::Unimplemented(into_inner(rust_type)))
            } else {
                rust_type
            }
        }

        Class(..) |
            Interface (..) => {
            match direction {
                library::ParameterDirection::In |
                    library::ParameterDirection::Out |
                    library::ParameterDirection::Return => rust_type,
                _ => Err(TypeError::Unimplemented(into_inner(rust_type))),
            }
        }

        List(..) |
            SList(..) |
            CArray(..) => {
            match direction {
                library::ParameterDirection::In |
                    library::ParameterDirection::Return => rust_type,
                _ => Err(TypeError::Unimplemented(into_inner(rust_type))),
            }
        }
        _ => Err(TypeError::Unimplemented(type_.get_name().to_owned())),
    }
}

#[inline]
fn format_parameter(rust_type: String, direction: library::ParameterDirection) -> String {
    if direction.is_out() {
        format!("&mut {}", rust_type)
    } else {
        rust_type
    }
}

//TODO: remove
fn implemented_in_main_namespace(library: &library::Library, type_id: library::TypeId) -> bool {
    match &*type_id.full_name(library) {
        "GLib.Error" => return true,
        _ => (),
    }
    if library.namespace(library::MAIN_NAMESPACE).name != "Gtk" {
        return false;
    }
    match &*type_id.full_name(library) {
        _ => false,
    }
}
<commit_msg>Correctly qualify fundamental types inside the glib crate<commit_after>use std::result;

use analysis::ref_mode::RefMode;
use env::Env;
use library::{self, Nullable};
use super::conversion_type::ConversionType;
use traits::*;

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TypeError {
    Ignored(String),
    Mismatch(String),
    Unimplemented(String),
}

pub type Result = result::Result<String, TypeError>;

fn into_inner(res: Result) -> String {
    use self::TypeError::*;
    match res {
        Ok(s) |
            Err(Ignored(s)) |
            Err(Mismatch(s)) |
            Err(Unimplemented(s)) => s,
    }
}

impl IntoString for Result {
    fn into_string(self) -> String {
        use self::TypeError::*;
        match self {
            Ok(s) => s,
            Err(Ignored(s)) => format!("/*Ignored*/{}", s),
            Err(Mismatch(s)) => format!("/*Metadata mismatch*/{}", s),
            Err(Unimplemented(s)) => format!("/*Unimplemented*/{}", s),
        }
    }
}

impl MapAny<String> for Result {
    fn map_any<F: FnOnce(String) -> String>(self, op: F) -> Result {
        use self::TypeError::*;
        match self {
            Ok(s) => Ok(op(s)),
            Err(Ignored(s)) => Err(Ignored(op(s))),
            Err(Mismatch(s)) => Err(Mismatch(op(s))),
            Err(Unimplemented(s)) => Err(Unimplemented(op(s))),
        }
    }
}

pub fn rust_type(env: &Env, type_id: library::TypeId) -> Result {
    rust_type_full(env, type_id, Nullable(false), RefMode::None)
}

pub fn bounds_rust_type(env: &Env, type_id: library::TypeId) -> Result {
    rust_type_full(env, type_id, Nullable(false), RefMode::ByRefFake)
}

fn rust_type_full(env: &Env, type_id: library::TypeId, nullable: Nullable, ref_mode: RefMode) -> Result {
    use library::Type::*;
    use library::Fundamental::*;
    let ok = |s: &str| Ok(s.into());
    let err = |s: &str| Err(TypeError::Unimplemented(s.into()));
    let mut skip_option = false;
    let type_ = env.library.type_(type_id);
    let mut rust_type = match *type_ {
        Fundamental(fund) => {
            match fund {
                None => err("()"),
                Boolean => ok("bool"),
                Int8 => ok("i8"),
                UInt8 => ok("u8"),
                Int16 => ok("i16"),
                UInt16 => ok("u16"),
                Int32 => ok("i32"),
                UInt32 => ok("u32"),
                Int64 => ok("i64"),
                UInt64 => ok("u64"),

                Int => ok("i32"),      //maybe dependent on target system
                UInt => ok("u32"),     //maybe dependent on target system

                Short => ok("libc::c_short"),   //depends of target system
                UShort => ok("libc::c_ushort"), //depends of target system
                Long => ok("libc::c_long"),     //depends of target system
                ULong => ok("libc::c_ulong"),   //depends of target system

                Float => ok("f32"),
                Double => ok("f64"),

                UniChar => ok("char"),
                Utf8 => if ref_mode.is_ref() { ok("str") } else { ok("String") },
                Filename => {
                    if ref_mode.is_ref() {
                        ok("std::path::Path")
                    } else {
                        ok("std::path::PathBuf")
                    }
                }
                Type if env.namespaces.glib_ns_id == library::MAIN_NAMESPACE => ok("types::Type"),
                Type => ok("glib::types::Type"),
                Unsupported => err("Unsupported"),
                _ => err(&format!("Fundamental: {:?}", fund)),
            }
        }
        Alias(ref alias) => {
            rust_type_full(env, alias.typ, nullable, ref_mode)
                .map_any(|_| alias.name.clone())
        }
        Record(library::Record { ref c_type, .. }) if c_type == "GVariantType" => {
            if ref_mode.is_ref() { ok("VariantTy") } else { ok("VariantType") }
        }
        Enumeration(..) |
            Bitfield(..) |
            Record(..) |
            Union(..) |
            Class(..) |
            Interface(..) => {
            let name = type_.get_name().to_owned();
            if env.type_status(&type_id.full_name(&env.library)).ignored() {
                Err(TypeError::Ignored(name))
            }
            else {
                Ok(name)
            }
        }
        List(inner_tid) |
            SList(inner_tid) |
            CArray(inner_tid)
            if ConversionType::of(&env.library, inner_tid) == ConversionType::Pointer => {
            skip_option = true;
            let inner_ref_mode = match *env.library.type_(inner_tid) {
                Class(..) |
                    Interface(..) => RefMode::None,
                _ => ref_mode,
            };
            rust_type_full(env, inner_tid, Nullable(false), inner_ref_mode)
                .map_any(|s| if ref_mode.is_ref() {
                    format!("[{}]", s)
                } else {
                    format!("Vec<{}>", s)
                })
        }
        _ => Err(TypeError::Unimplemented(type_.get_name().to_owned())),
    };

    if type_id.ns_id != library::MAIN_NAMESPACE && type_id.ns_id != library::INTERNAL_NAMESPACE
        && !implemented_in_main_namespace(&env.library, type_id) {
        if env.type_status(&type_id.full_name(&env.library)).ignored() {
            rust_type = Err(TypeError::Ignored(into_inner(rust_type)));
        }
        rust_type = rust_type.map_any(|s| format!("{}::{}",
            env.namespaces[type_id.ns_id].higher_crate_name, s));
    }

    match ref_mode {
        RefMode::None | RefMode::ByRefFake => {}
        RefMode::ByRef | RefMode::ByRefImmut => rust_type = rust_type.map_any(|s| format!("&{}", s)),
        RefMode::ByRefMut => rust_type = rust_type.map_any(|s| format!("&mut {}", s)),
    }
    if *nullable && !skip_option {
        match ConversionType::of(&env.library, type_id) {
            ConversionType::Pointer
                | ConversionType::Scalar => {
                rust_type = rust_type.map_any(|s| format!("Option<{}>", s))
            }
            _ => (),
        }
    }

    rust_type
}

pub fn used_rust_type(env: &Env, type_id: library::TypeId) -> Result {
    use library::Type::*;
    match *env.library.type_(type_id) {
        Fundamental(library::Fundamental::Type) |
            Fundamental(library::Fundamental::Short) |
            Fundamental(library::Fundamental::UShort) |
            Fundamental(library::Fundamental::Long) |
            Fundamental(library::Fundamental::ULong) |
            Fundamental(library::Fundamental::Filename) |
            Alias(..) |
            Bitfield(..) |
            Record(..) |
            Union(..) |
            Class(..) |
            Enumeration(..) |
            Interface(..) => rust_type(env, type_id),
        List(inner_tid) |
            SList(inner_tid) |
            CArray(inner_tid) => used_rust_type(env, inner_tid),
        _ => Err(TypeError::Ignored("Don't need use".to_owned())),
    }
}

pub fn parameter_rust_type(env: &Env, type_id:library::TypeId,
                           direction: library::ParameterDirection, nullable: Nullable,
                           ref_mode: RefMode) -> Result {
    use library::Type::*;
    let type_ = env.library.type_(type_id);
    let rust_type = rust_type_full(env, type_id, nullable, ref_mode);
    match *type_ {
        Fundamental(fund) => {
            if fund == library::Fundamental::Utf8 || fund == library::Fundamental::Filename {
                match direction {
                    library::ParameterDirection::In |
                        library::ParameterDirection::Return => rust_type,
                    _ => Err(TypeError::Unimplemented(into_inner(rust_type))),
                }
            } else {
                rust_type.map_any(|s| format_parameter(s, direction))
            }
        }

        Alias(ref alias) => {
            rust_type.and_then(|s| {
                parameter_rust_type(env, alias.typ, direction, nullable, ref_mode)
                    .map_any(|_| s)
            })
                .map_any(|s| format_parameter(s, direction))
        }

        Enumeration(..) |
            Union(..) |
            Bitfield(..) => rust_type.map_any(|s| format_parameter(s, direction)),

        Record(..) => {
            if direction == library::ParameterDirection::InOut {
                Err(TypeError::Unimplemented(into_inner(rust_type)))
            } else {
                rust_type
            }
        }

        Class(..) |
            Interface (..) => {
            match direction {
                library::ParameterDirection::In |
                    library::ParameterDirection::Out |
                    library::ParameterDirection::Return => rust_type,
                _ => Err(TypeError::Unimplemented(into_inner(rust_type))),
            }
        }

        List(..) |
            SList(..) |
            CArray(..) => {
            match direction {
                library::ParameterDirection::In |
                    library::ParameterDirection::Return => rust_type,
                _ => Err(TypeError::Unimplemented(into_inner(rust_type))),
            }
        }
        _ => Err(TypeError::Unimplemented(type_.get_name().to_owned())),
    }
}

#[inline]
fn format_parameter(rust_type: String, direction: library::ParameterDirection) -> String {
    if direction.is_out() {
        format!("&mut {}", rust_type)
    } else {
        rust_type
    }
}

//TODO: remove
fn implemented_in_main_namespace(library: &library::Library, type_id: library::TypeId) -> bool {
    match &*type_id.full_name(library) {
        "GLib.Error" => return true,
        _ => (),
    }
    if library.namespace(library::MAIN_NAMESPACE).name != "Gtk" {
        return false;
    }
    match &*type_id.full_name(library) {
        _ => false,
    }
}
<|endoftext|>


<commit_before>mod join;
mod leave;
mod play;
mod stop;

use self::join::JoinCommand;
use self::leave::LeaveCommand;
use self::play::PlayCommand;
use self::stop::StopCommand;

use bot::data::VoiceContainer;

use lalafell::commands::prelude::*;
use lalafell::error::*;

use serenity::prelude::Mutex;
use serenity::client::bridge::voice::ClientVoiceManager;

use std::collections::HashMap;

const USAGE: &str = "!music [subcommand] (args)";

#[derive(Default)]
pub struct MusicCommand;

impl MusicCommand {
  pub fn voice_manager(ctx: &Context) -> Result<Arc<Mutex<ClientVoiceManager>>> {
    match ctx.data.lock().get::<VoiceContainer>() {
      Some(vm) => Ok(Arc::clone(vm)),
      None => return Err("No reference to voice manager. This is a bug.".into())
    }
  }
}

#[derive(Debug, Deserialize)]
pub struct Params {
  subcommand: String,
  args: Option<Vec<String>>
}

impl HasParams for MusicCommand {
  type Params = Params;
}

lazy_static! {
  static ref COMMANDS: HashMap<&'static str, Box<PublicChannelCommand<'static> + Send + Sync>> = {
    let mut map: HashMap<&'static str, Box<PublicChannelCommand<'static> + Send + Sync>> = HashMap::new();
    map.insert("join", box JoinCommand);
    map.insert("leave", box LeaveCommand);
    map.insert("play", box PlayCommand);
    map.insert("stop", box StopCommand);
    map
  };
}

impl<'a> PublicChannelCommand<'a> for MusicCommand {
  fn run(&self, ctx: &Context, msg: &Message, guild: GuildId, channel: Arc<RwLock<GuildChannel>>, str_params: &[&str]) -> CommandResult<'a> {
    let params = self.params(USAGE, str_params)?;

    match COMMANDS.get(&params.subcommand.to_lowercase().as_str()) {
      Some(c) => c.run(ctx, msg, guild, channel, &str_params[1..]),
      None => Err("Invalid subcommand.".into())
    }
  }
}
<commit_msg>refactor: use collected args<commit_after>mod join;
mod leave;
mod play;
mod stop;

use self::join::JoinCommand;
use self::leave::LeaveCommand;
use self::play::PlayCommand;
use self::stop::StopCommand;

use bot::data::VoiceContainer;

use lalafell::commands::prelude::*;
use lalafell::error::*;

use serenity::prelude::Mutex;
use serenity::client::bridge::voice::ClientVoiceManager;

use std::collections::HashMap;

const USAGE: &str = "!music [subcommand] (args)";

#[derive(Default)]
pub struct MusicCommand;

impl MusicCommand {
  pub fn voice_manager(ctx: &Context) -> Result<Arc<Mutex<ClientVoiceManager>>> {
    match ctx.data.lock().get::<VoiceContainer>() {
      Some(vm) => Ok(Arc::clone(vm)),
      None => return Err("No reference to voice manager. This is a bug.".into())
    }
  }
}

#[derive(Debug, Deserialize)]
pub struct Params {
  subcommand: String,
  args: Option<Vec<String>>
}

impl HasParams for MusicCommand {
  type Params = Params;
}

lazy_static! {
  static ref COMMANDS: HashMap<&'static str, Box<PublicChannelCommand<'static> + Send + Sync>> = {
    let mut map: HashMap<&'static str, Box<PublicChannelCommand<'static> + Send + Sync>> = HashMap::new();
    map.insert("join", box JoinCommand);
    map.insert("leave", box LeaveCommand);
    map.insert("play", box PlayCommand);
    map.insert("stop", box StopCommand);
    map
  };
}

impl<'a> PublicChannelCommand<'a> for MusicCommand {
  fn run(&self, ctx: &Context, msg: &Message, guild: GuildId, channel: Arc<RwLock<GuildChannel>>, str_params: &[&str]) -> CommandResult<'a> {
    let params = self.params(USAGE, str_params)?;

    let sub_params = params.args.unwrap_or_default();
    let sub_param_refs: Vec<&str> = sub_params.iter().map(AsRef::as_ref).collect();

    match COMMANDS.get(&params.subcommand.to_lowercase().as_str()) {
      Some(c) => c.run(ctx, msg, guild, channel, &sub_param_refs),
      None => Err("Invalid subcommand.".into())
    }
  }
}
<|endoftext|>


<commit_before>extern crate metl;

use metl::extras::window::{Event, WindowBuilder};
use metl::{ClearColor, PixelFormat};

fn main() {
    let device = metl::Device::system_default_device().unwrap();
    let mut window = WindowBuilder::new(device)
                     .with_dimensions(800, 600)
                     .with_title("Metal Window".into())
                     .build()
                     .unwrap();

    window.view.set_depth_stencil_pixel_format(PixelFormat::Rgba8Unorm);
    window.view.set_clear_color(ClearColor::new(1.0, 0.0, 0.0, 1.0));

    'mainloop: loop {
        for event in window.poll_events() {
            match event {
                Event::Closed => {
                    break 'mainloop
                }
                _ => {}
            }
        }

        window.view.draw();
    }
}
<commit_msg>Add a delegate to the example<commit_after>extern crate metl;

use metl::extras::window::{Event, WindowBuilder, View, ViewDelegate};
use metl::{ClearColor, PixelFormat};

fn main() {
    struct MyViewDelegate;
    impl ViewDelegate for MyViewDelegate {
        fn draw_into_view(&self, view: &mut View) {
            view.draw();
        }
        fn on_resize(&self, _view: &mut View, new_size: (f64, f64)) {
            println!("Resized to {:?}", new_size);
        }
    }

    let device = metl::Device::system_default_device().unwrap();
    let mut window = WindowBuilder::new(device)
                     .with_dimensions(800, 600)
                     .with_title("Metal Window".into())
                     .build()
                     .unwrap();

    window.view.set_depth_stencil_pixel_format(PixelFormat::Rgba8Unorm);
    window.view.set_clear_color(ClearColor::new(1.0, 0.0, 0.0, 1.0));
    window.view.set_delegate(MyViewDelegate);

    'mainloop: loop {
        for event in window.poll_events() {
            match event {
                Event::Closed => {
                    break 'mainloop
                }
                _ => {}
            }
        }

    }
}
<|endoftext|>


<commit_before>extern crate chrono;
extern crate clap;
extern crate fern;
#[macro_use]
extern crate log;
extern crate rand;
extern crate thud;

use ::clap::App;

use ::thud::game;
use ::thud::mcts;
use ::thud::util;

fn main() {
    // Set up arg handling.
    let matches = {
        let app = util::set_common_args(
            App::new("console_mcts")
                .version("0.1.0")
                .author("Stu Black <trurl@freeshell.org>")
                .about("Plays out Thud MCTS iterations"),
            &[util::ITERATION_COUNT_FLAG,
              util::SIMULATION_COUNT_FLAG,
              util::EXPLORATION_BIAS_FLAG,
              util::INITIAL_BOARD_FLAG,
              util::INITIAL_PLAYER_FLAG,
              util::LOG_LEVEL_FLAG,
              util::MOVE_SELECTION_CRITERION_FLAG]);
        app.get_matches()
    };
    let iteration_count =
        match matches.value_of(util::ITERATION_COUNT_FLAG).unwrap().parse::<usize>() {
            Ok(x) => x,
            Err(e) => panic!("Bad iteration count: {}", e),
        };
    let simulation_count =
        match matches.value_of(util::SIMULATION_COUNT_FLAG).unwrap().parse::<usize>() {
            Ok(x) => x,
            Err(e) => panic!("Bad simulation count: {}", e),
        };
    let exploration_bias =
        match matches.value_of(util::EXPLORATION_BIAS_FLAG).unwrap().parse::<f64>() {
            Ok(x) => x,
            Err(e) => panic!("Bad exploration bias: {}", e),
        };
    let initial_cells =
        match matches.value_of(util::INITIAL_BOARD_FLAG).unwrap().parse::<util::InitialBoard>() {
            Ok(x) => x.cells(),
            Err(e) => panic!("Bad initial board configuration: {}", e),
        };
    let toggle_initial_player =
        match matches.value_of(util::INITIAL_PLAYER_FLAG).map(|x| x.parse::<game::Role>()) {
            None | Some(Ok(game::Role::Dwarf)) => false,
            Some(Ok(game::Role::Troll)) => true,
            Some(Err(x)) => panic!("{}", x),
        };
    let logging_level =
        match matches.value_of(util::LOG_LEVEL_FLAG).map(|x| x.parse::<log::LogLevelFilter>()) {
            Some(Ok(x)) => x,
            Some(Err(_)) => panic!("Bad logging level '{}'", matches.value_of(util::LOG_LEVEL_FLAG).unwrap()),
            None => log::LogLevelFilter::Info,
        };
    let move_selection_criterion =
        match matches.value_of(util::MOVE_SELECTION_CRITERION_FLAG).map(|x| x.parse::<util::MoveSelectionCriterion>()) {
            Some(Ok(x)) => x,
            Some(Err(e)) => panic!("Bad move selection criterion: {}", e),
            None => util::MoveSelectionCriterion::VisitCount,
        };

    // Set up logging.
    let logger_config = fern::DispatchConfig {
        format: Box::new(|msg: &str, level: &log::LogLevel, _location: &log::LogLocation| {
            format!("[{}][{}] {}",
                    chrono::Local::now().format("%Y-%m-%d %T%.3f%z").to_string(), level, msg)
        }),
        output: vec![fern::OutputConfig::stdout()],
        level: logging_level,
    };
    if let Err(e) = fern::init_global_logger(logger_config, log::LogLevelFilter::Trace) {
        panic!("Failed to initialize global logger: {}", e);
    }

    // Play game.
    let mut state = mcts::State::new(initial_cells);
    if toggle_initial_player {
        state.toggle_active_role();
    }
    let mut graph = mcts::Graph::new();

    util::initialize_search(state.clone(), &mut graph);
    let mut search_state = mcts::SearchState::new(rand::thread_rng(), exploration_bias);
    let mut turn_number = 0;
    loop {
        info!("begin turn {}; board: {}", turn_number, ::thud::game::board::format_board(state.board()));
        let mut best_action = None;
        for iteration in 0..iteration_count {
            if iteration % 100 == 0 {
                info!("iteration: {} / {} = {}%", iteration, iteration_count,
                      ((10000.0 * (iteration as f64) / (iteration_count as f64)) as usize as f64) / 100.0);
            }
            match search_state.search(&mut graph, state.clone(),
                                      |_: usize| mcts::SearchSettings {
                                          simulation_count: simulation_count,
                                      }) {
                Ok(stats) => {
                    let toplevel_visits = {
                        let mut count = 0;
                        for &(_, stats, _) in stats.iter() {
                            count += stats.visits;
                        }
                        count
                    };
                    trace!("total visits at top level: {}", toplevel_visits);
                    // TODO: this commented-out block is only valid when we haven't
                    // propagated a multi-visit payoff upwards from conneting to an
                    // extant vertex.
                    // if simulation_count == 1 && toplevel_visits != iteration + 1 {
                    //     console_ui::write_board(state.board());
                    //     for (action, stats) in stats.into_iter() {
                    //         println!("{:?}: [{}, {}] = {:?} / {}", action,
                    //                  (stats.payoff.values[0] as f64) / (stats.visits as f64),
                    //                  (stats.payoff.values[1] as f64) / (stats.visits as f64),
                    //                  stats.payoff, stats.visits);
                    //     }
                    //     panic!("total visits at top level is {}, but iteration count is {}",
                    //            toplevel_visits, iteration)
                    // }
                    if iteration % 1000 == 0 || iteration + 1 == iteration_count {
                        println!("root stats:");
                        let mut best_visits = ::std::usize::MIN;
                        let mut best_ucb = ::std::f64::MIN;
                        for (action, stats, ucb) in stats.into_iter() {
                            println!("{:?}: [{}, {}] = {:?} / {}; UCB = {:?}", action,
                                     (stats.payoff.values[0] as f64) / (stats.visits as f64),
                                     (stats.payoff.values[1] as f64) / (stats.visits as f64),
                                     stats.payoff, stats.visits, ucb);
                            best_action = match (best_action, move_selection_criterion) {
                                (None, _) => Some(action),
                                (Some(_), util::MoveSelectionCriterion::VisitCount) if best_visits < stats.visits => {
                                    best_visits = stats.visits;
                                    Some(action)
                                },
                                (Some(_), util::MoveSelectionCriterion::Ucb) =>
                                    match ucb {
                                        Ok(mcts::UcbProxy::Value(x)) if best_ucb < x => {
                                            best_ucb = x;
                                            Some(action)
                                        },
                                        _ => best_action,
                                    },
                                _ => best_action,
                            }
                        }
                    }
                },
                Err(e) => {
                    error!("Error in seach iteration {}: {}", iteration, e);
                    break
                },
            }
        }

        // Finish turn.
        match best_action {
            Some(action) => {
                info!("turn {}: performing best action {:?}", turn_number, action);
                state.do_action(&action);
                graph = mcts::Graph::new();
                util::initialize_search(state.clone(), &mut graph);
                turn_number += 1;
            },
            None => {
                info!("turn {}: no best action. exiting.", turn_number);
                break
            }
        }
    }
    // console_ui::write_search_graph(&graph, &state);
}
<commit_msg>Make default board the default for console_mcts.<commit_after>extern crate chrono;
extern crate clap;
extern crate fern;
#[macro_use]
extern crate log;
extern crate rand;
extern crate thud;

use ::clap::App;

use ::thud::game;
use ::thud::mcts;
use ::thud::util;

fn main() {
    // Set up arg handling.
    let matches = {
        let app = util::set_common_args(
            App::new("console_mcts")
                .version("0.1.0")
                .author("Stu Black <trurl@freeshell.org>")
                .about("Plays out Thud MCTS iterations"),
            &[util::ITERATION_COUNT_FLAG,
              util::SIMULATION_COUNT_FLAG,
              util::EXPLORATION_BIAS_FLAG,
              util::INITIAL_BOARD_FLAG,
              util::INITIAL_PLAYER_FLAG,
              util::LOG_LEVEL_FLAG,
              util::MOVE_SELECTION_CRITERION_FLAG]);
        app.get_matches()
    };
    let iteration_count =
        match matches.value_of(util::ITERATION_COUNT_FLAG).unwrap().parse::<usize>() {
            Ok(x) => x,
            Err(e) => panic!("Bad iteration count: {}", e),
        };
    let simulation_count =
        match matches.value_of(util::SIMULATION_COUNT_FLAG).unwrap().parse::<usize>() {
            Ok(x) => x,
            Err(e) => panic!("Bad simulation count: {}", e),
        };
    let exploration_bias =
        match matches.value_of(util::EXPLORATION_BIAS_FLAG).unwrap().parse::<f64>() {
            Ok(x) => x,
            Err(e) => panic!("Bad exploration bias: {}", e),
        };
    let initial_cells =
        match matches.value_of(util::INITIAL_BOARD_FLAG).map(|x| x.parse::<util::InitialBoard>()) {
            Some(Ok(x)) => x.cells(),
            Some(Err(e)) => panic!("Bad initial board configuration: {}", e),
            None => game::board::Cells::default(),
        };
    let toggle_initial_player =
        match matches.value_of(util::INITIAL_PLAYER_FLAG).map(|x| x.parse::<game::Role>()) {
            None | Some(Ok(game::Role::Dwarf)) => false,
            Some(Ok(game::Role::Troll)) => true,
            Some(Err(x)) => panic!("{}", x),
        };
    let logging_level =
        match matches.value_of(util::LOG_LEVEL_FLAG).map(|x| x.parse::<log::LogLevelFilter>()) {
            Some(Ok(x)) => x,
            Some(Err(_)) => panic!("Bad logging level '{}'", matches.value_of(util::LOG_LEVEL_FLAG).unwrap()),
            None => log::LogLevelFilter::Info,
        };
    let move_selection_criterion =
        match matches.value_of(util::MOVE_SELECTION_CRITERION_FLAG).map(|x| x.parse::<util::MoveSelectionCriterion>()) {
            Some(Ok(x)) => x,
            Some(Err(e)) => panic!("Bad move selection criterion: {}", e),
            None => util::MoveSelectionCriterion::VisitCount,
        };

    // Set up logging.
    let logger_config = fern::DispatchConfig {
        format: Box::new(|msg: &str, level: &log::LogLevel, _location: &log::LogLocation| {
            format!("[{}][{}] {}",
                    chrono::Local::now().format("%Y-%m-%d %T%.3f%z").to_string(), level, msg)
        }),
        output: vec![fern::OutputConfig::stdout()],
        level: logging_level,
    };
    if let Err(e) = fern::init_global_logger(logger_config, log::LogLevelFilter::Trace) {
        panic!("Failed to initialize global logger: {}", e);
    }

    // Play game.
    let mut state = mcts::State::new(initial_cells);
    if toggle_initial_player {
        state.toggle_active_role();
    }
    let mut graph = mcts::Graph::new();

    util::initialize_search(state.clone(), &mut graph);
    let mut search_state = mcts::SearchState::new(rand::thread_rng(), exploration_bias);
    let mut turn_number = 0;
    loop {
        info!("begin turn {}; board: {}", turn_number, ::thud::game::board::format_board(state.board()));
        let mut best_action = None;
        for iteration in 0..iteration_count {
            if iteration % 100 == 0 {
                info!("iteration: {} / {} = {}%", iteration, iteration_count,
                      ((10000.0 * (iteration as f64) / (iteration_count as f64)) as usize as f64) / 100.0);
            }
            match search_state.search(&mut graph, state.clone(),
                                      |_: usize| mcts::SearchSettings {
                                          simulation_count: simulation_count,
                                      }) {
                Ok(stats) => {
                    let toplevel_visits = {
                        let mut count = 0;
                        for &(_, stats, _) in stats.iter() {
                            count += stats.visits;
                        }
                        count
                    };
                    trace!("total visits at top level: {}", toplevel_visits);
                    // TODO: this commented-out block is only valid when we haven't
                    // propagated a multi-visit payoff upwards from conneting to an
                    // extant vertex.
                    // if simulation_count == 1 && toplevel_visits != iteration + 1 {
                    //     console_ui::write_board(state.board());
                    //     for (action, stats) in stats.into_iter() {
                    //         println!("{:?}: [{}, {}] = {:?} / {}", action,
                    //                  (stats.payoff.values[0] as f64) / (stats.visits as f64),
                    //                  (stats.payoff.values[1] as f64) / (stats.visits as f64),
                    //                  stats.payoff, stats.visits);
                    //     }
                    //     panic!("total visits at top level is {}, but iteration count is {}",
                    //            toplevel_visits, iteration)
                    // }
                    if iteration % 1000 == 0 || iteration + 1 == iteration_count {
                        info!("root stats:");
                        let mut best_visits = ::std::usize::MIN;
                        let mut best_ucb = ::std::f64::MIN;
                        for (action, stats, ucb) in stats.into_iter() {
                            info!("{:?}: [{}, {}] = {:?} / {}; UCB = {:?}", action,
                                  (stats.payoff.values[0] as f64) / (stats.visits as f64),
                                  (stats.payoff.values[1] as f64) / (stats.visits as f64),
                                  stats.payoff, stats.visits, ucb);
                            best_action = match (best_action, move_selection_criterion) {
                                (None, _) => Some(action),
                                (Some(_), util::MoveSelectionCriterion::VisitCount) if best_visits < stats.visits => {
                                    best_visits = stats.visits;
                                    Some(action)
                                },
                                (Some(_), util::MoveSelectionCriterion::Ucb) =>
                                    match ucb {
                                        Ok(mcts::UcbProxy::Value(x)) if best_ucb < x => {
                                            best_ucb = x;
                                            Some(action)
                                        },
                                        _ => best_action,
                                    },
                                _ => best_action,
                            }
                        }
                    }
                },
                Err(e) => {
                    error!("Error in seach iteration {}: {}", iteration, e);
                    break
                },
            }
        }

        // Finish turn.
        match best_action {
            Some(action) => {
                info!("turn {}: performing best action {:?}", turn_number, action);
                state.do_action(&action);
                graph = mcts::Graph::new();
                util::initialize_search(state.clone(), &mut graph);
                turn_number += 1;
            },
            None => {
                info!("turn {}: no best action. exiting.", turn_number);
                break
            }
        }
    }
    // console_ui::write_search_graph(&graph, &state);
}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A wrapper around any Reader to treat it as an RNG.

use old_io::Reader;
use rand::Rng;
use result::Result::{Ok, Err};
use slice::SliceExt;

/// An RNG that reads random bytes straight from a `Reader`. This will
/// work best with an infinite reader, but this is not required.
///
/// # Panics
///
/// It will panic if it there is insufficient data to fulfill a request.
///
/// # Example
///
/// ```rust
/// use std::rand::{reader, Rng};
/// use std::old_io::MemReader;
///
/// let mut rng = reader::ReaderRng::new(MemReader::new(vec!(1,2,3,4,5,6,7,8)));
/// println!("{:x}", rng.gen::<uint>());
/// ```
pub struct ReaderRng<R> {
    reader: R
}

impl<R: Reader> ReaderRng<R> {
    /// Create a new `ReaderRng` from a `Reader`.
    pub fn new(r: R) -> ReaderRng<R> {
        ReaderRng {
            reader: r
        }
    }
}

impl<R: Reader> Rng for ReaderRng<R> {
    fn next_u32(&mut self) -> u32 {
        // This is designed for speed: reading a LE integer on a LE
        // platform just involves blitting the bytes into the memory
        // of the u32, similarly for BE on BE; avoiding byteswapping.
        if cfg!(target_endian="little") {
            self.reader.read_le_u32().unwrap()
        } else {
            self.reader.read_be_u32().unwrap()
        }
    }
    fn next_u64(&mut self) -> u64 {
        // see above for explanation.
        if cfg!(target_endian="little") {
            self.reader.read_le_u64().unwrap()
        } else {
            self.reader.read_be_u64().unwrap()
        }
    }
    fn fill_bytes(&mut self, v: &mut [u8]) {
        if v.len() == 0 { return }
        match self.reader.read_at_least(v.len(), v) {
            Ok(_) => {}
            Err(e) => panic!("ReaderRng.fill_bytes error: {:?}", e)
        }
    }
}

#[cfg(test)]
mod test {
    use prelude::v1::*;

    use super::ReaderRng;
    use old_io::MemReader;
    use num::Int;
    use rand::Rng;

    #[test]
    fn test_reader_rng_u64() {
        // transmute from the target to avoid endianness concerns.
        let v = vec![0u8, 0, 0, 0, 0, 0, 0, 1,
                     0  , 0, 0, 0, 0, 0, 0, 2,
                     0,   0, 0, 0, 0, 0, 0, 3];
        let mut rng = ReaderRng::new(MemReader::new(v));

        assert_eq!(rng.next_u64(), 1_u64.to_be());
        assert_eq!(rng.next_u64(), 2_u64.to_be());
        assert_eq!(rng.next_u64(), 3_u64.to_be());
    }
    #[test]
    fn test_reader_rng_u32() {
        let v = vec![0u8, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3];
        let mut rng = ReaderRng::new(MemReader::new(v));

        assert_eq!(rng.next_u32(), 1_u32.to_be());
        assert_eq!(rng.next_u32(), 2_u32.to_be());
        assert_eq!(rng.next_u32(), 3_u32.to_be());
    }
    #[test]
    fn test_reader_rng_fill_bytes() {
        let v = [1u8, 2, 3, 4, 5, 6, 7, 8];
        let mut w = [0u8; 8];

        let mut rng = ReaderRng::new(MemReader::new(v.as_slice().to_vec()));
        rng.fill_bytes(&mut w);

        assert!(v == w);
    }

    #[test]
    #[should_fail]
    fn test_reader_rng_insufficient_bytes() {
        let mut rng = ReaderRng::new(MemReader::new(vec!()));
        let mut v = [0u8; 3];
        rng.fill_bytes(&mut v);
    }
}
<commit_msg>cleanup: s/`v.slice*()`/`&v[a..b]`/g + remove redundant  `as_slice()` calls<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A wrapper around any Reader to treat it as an RNG.

use old_io::Reader;
use rand::Rng;
use result::Result::{Ok, Err};
use slice::SliceExt;

/// An RNG that reads random bytes straight from a `Reader`. This will
/// work best with an infinite reader, but this is not required.
///
/// # Panics
///
/// It will panic if it there is insufficient data to fulfill a request.
///
/// # Example
///
/// ```rust
/// use std::rand::{reader, Rng};
/// use std::old_io::MemReader;
///
/// let mut rng = reader::ReaderRng::new(MemReader::new(vec!(1,2,3,4,5,6,7,8)));
/// println!("{:x}", rng.gen::<uint>());
/// ```
pub struct ReaderRng<R> {
    reader: R
}

impl<R: Reader> ReaderRng<R> {
    /// Create a new `ReaderRng` from a `Reader`.
    pub fn new(r: R) -> ReaderRng<R> {
        ReaderRng {
            reader: r
        }
    }
}

impl<R: Reader> Rng for ReaderRng<R> {
    fn next_u32(&mut self) -> u32 {
        // This is designed for speed: reading a LE integer on a LE
        // platform just involves blitting the bytes into the memory
        // of the u32, similarly for BE on BE; avoiding byteswapping.
        if cfg!(target_endian="little") {
            self.reader.read_le_u32().unwrap()
        } else {
            self.reader.read_be_u32().unwrap()
        }
    }
    fn next_u64(&mut self) -> u64 {
        // see above for explanation.
        if cfg!(target_endian="little") {
            self.reader.read_le_u64().unwrap()
        } else {
            self.reader.read_be_u64().unwrap()
        }
    }
    fn fill_bytes(&mut self, v: &mut [u8]) {
        if v.len() == 0 { return }
        match self.reader.read_at_least(v.len(), v) {
            Ok(_) => {}
            Err(e) => panic!("ReaderRng.fill_bytes error: {:?}", e)
        }
    }
}

#[cfg(test)]
mod test {
    use prelude::v1::*;

    use super::ReaderRng;
    use old_io::MemReader;
    use num::Int;
    use rand::Rng;

    #[test]
    fn test_reader_rng_u64() {
        // transmute from the target to avoid endianness concerns.
        let v = vec![0u8, 0, 0, 0, 0, 0, 0, 1,
                     0  , 0, 0, 0, 0, 0, 0, 2,
                     0,   0, 0, 0, 0, 0, 0, 3];
        let mut rng = ReaderRng::new(MemReader::new(v));

        assert_eq!(rng.next_u64(), 1_u64.to_be());
        assert_eq!(rng.next_u64(), 2_u64.to_be());
        assert_eq!(rng.next_u64(), 3_u64.to_be());
    }
    #[test]
    fn test_reader_rng_u32() {
        let v = vec![0u8, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3];
        let mut rng = ReaderRng::new(MemReader::new(v));

        assert_eq!(rng.next_u32(), 1_u32.to_be());
        assert_eq!(rng.next_u32(), 2_u32.to_be());
        assert_eq!(rng.next_u32(), 3_u32.to_be());
    }
    #[test]
    fn test_reader_rng_fill_bytes() {
        let v = [1u8, 2, 3, 4, 5, 6, 7, 8];
        let mut w = [0u8; 8];

        let mut rng = ReaderRng::new(MemReader::new(v.to_vec()));
        rng.fill_bytes(&mut w);

        assert!(v == w);
    }

    #[test]
    #[should_fail]
    fn test_reader_rng_insufficient_bytes() {
        let mut rng = ReaderRng::new(MemReader::new(vec!()));
        let mut v = [0u8; 3];
        rng.fill_bytes(&mut v);
    }
}
<|endoftext|>