<commit_before>use std::sync::mpsc::{Receiver, Sender};
use std::rc::Rc;

use action::ExecResult;
use super::{config, Condition, Context, Message, TimerEvent};
use reactor::{self, Event, EventDemultiplexer, EventHandler, Reactor};

#[derive(Debug)]
pub enum Request {
    Event(super::Event),
    Exit
}

#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum RequestHandler {
    Event,
    Exit
}

impl reactor::Event for Request {
    type Handler = RequestHandler;
    fn handler(&self) -> Self::Handler {
        match *self {
            Request::Event(_) => RequestHandler::Event,
            Request::Exit => RequestHandler::Exit,
        }
    }
}

#[derive(Debug)]
pub enum Response {
    Event(ExecResult),
    Exit
}

pub struct Dispatcher {
    contexts: Vec<Context>,
    output_channel: Sender<Response>,
    exits_received: u32
}

impl Dispatcher {
    pub fn new(contexts: Vec<config::Context>, action_output_channel: Sender<Response>) -> Dispatcher {
        let contexts = contexts.into_iter().map(|ctx| Context::from(ctx)).collect::<Vec<Context>>();
        Dispatcher {
            contexts: contexts,
            output_channel: action_output_channel,
            exits_received: 0
        }
    }

    pub fn start_loop(&mut self, channel: Receiver<Request>) {
        for i in channel.iter() {
            match i {
                Request::Event(event) => self.dispatch(event),
                Request::Exit => {
                    if self.on_exit() {
                        break;
                    }
                }
            }
        }
    }

    fn on_exit(&mut self) -> bool {
        self.exits_received += 1;
        let _ = self.output_channel.send(Response::Exit);
        self.exits_received >= 2
    }

    pub fn dispatch(&mut self, event: super::Event) {
        match event {
            super::Event::Message(event) => {
                let event = Rc::new(event);
                self.on_message(event);
            },
            super::Event::Timer(ref event) => {
                self.on_timer(event);
            }
        };
    }

    fn on_message(&mut self, event: Rc<Message>) {
        for context in self.contexts.iter_mut() {
            if let Some(result) = context.on_message(event.clone()) {
                for i in result.into_iter() {
                    let _ = self.output_channel.send(i.into());
                }
            }
        }
    }

    fn on_timer(&mut self, event: &TimerEvent) {
        for context in self.contexts.iter_mut() {
            if let Some(result) = context.on_timer(event) {
                for i in result.into_iter() {
                    let _ = self.output_channel.send(i.into());
                }
            }
        }
    }
}

use std::collections::BTreeMap;

pub struct RequestReactor {
    handlers: BTreeMap<RequestHandler, Box<reactor::EventHandler<Request, Handler=RequestHandler>>>,
    demultiplexer: Demultiplexer<Request>,
    exit_condition: Condition
}

impl RequestReactor {
    fn new(demultiplexer: Demultiplexer<Request>) -> RequestReactor {
        let exit_condition = Condition::new(false);
        let exit_handler = Box::new(handlers::exit::ExitHandler::new(exit_condition.clone()));
        let event_handler = Box::new(handlers::event::EventHandler::new());

        let mut reactor = RequestReactor {
            demultiplexer: demultiplexer,
            exit_condition: exit_condition,
            handlers: BTreeMap::new()
        };

        reactor.register_handler(exit_handler);
        reactor.register_handler(event_handler);
        reactor
    }
}

impl Reactor for RequestReactor {
    type Event = Request;
    type Handler = RequestHandler;
    fn handle_events(&mut self) {
        while !self.exit_condition.is_active() {
            if let Some(request) = self.demultiplexer.select() {
                let mut handler = self.handlers.get_mut(&request.handler()).unwrap();
                handler.handle_event(request);
            } else {
                break;
            }
        }
    }
    fn register_handler(&mut self, handler: Box<reactor::EventHandler<Self::Event, Handler=RequestHandler>>) {
        self.handlers.insert(handler.handler(), handler);
    }
    fn remove_handler(&mut self, handler: &reactor::EventHandler<Self::Event, Handler=RequestHandler>){}
}

struct Demultiplexer<T>(Receiver<T>);

impl reactor::EventDemultiplexer for Demultiplexer<Request> {
    type Event = Request;
    fn select(&mut self) -> Option<Self::Event> {
        self.0.recv().ok()
    }
}

mod handlers {
    pub mod exit {
        use dispatcher::{Request, RequestHandler};
        use condition::Condition;
        use reactor::EventHandler;

        pub struct ExitHandler{
            condition: Condition,
            stops: u32
        }

        impl ExitHandler {
            pub fn new(condition: Condition) -> ExitHandler {
                ExitHandler {
                    condition: condition,
                    stops: 0
                }
            }
        }

        impl EventHandler<Request> for ExitHandler {
            type Handler = RequestHandler;
            fn handle_event(&mut self, event: Request) {
                if let Request::Exit = event {
                    self.stops += 1;

                    if self.stops >= 2 {
                        self.condition.activate();
                    }
                } else {
                    unreachable!("An ExitHandler should only receive Exit events");
                }
            }
            fn handler(&self) -> Self::Handler {
                RequestHandler::Exit
            }
        }
    }

    pub mod event {
        use dispatcher::{Request, RequestHandler};
        use reactor;

        pub struct EventHandler;

        impl EventHandler {
            pub fn new() -> EventHandler {
                EventHandler
            }
        }

        impl reactor::EventHandler<Request> for EventHandler {
            type Handler = RequestHandler;
            fn handle_event(&mut self, event: Request) {
                if let Request::Event(_) = event {
                    println!("Event recvd");
                } else {
                    unreachable!("An EventHandler should only receive Event events");
                }
            }
            fn handler(&self) -> Self::Handler {
                RequestHandler::Event
            }
        }
    }
}
<commit_msg>dispatcher: add linear event handler<commit_after>use std::sync::mpsc::{Receiver, Sender};
use std::rc::Rc;

use action::ExecResult;
use super::{config, Condition, Context, Message, TimerEvent};
use reactor::{self, Event, EventDemultiplexer, EventHandler, Reactor};

#[derive(Debug)]
pub enum Request {
    Event(super::Event),
    Exit
}

#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum RequestHandler {
    Event,
    Exit
}

impl reactor::Event for Request {
    type Handler = RequestHandler;
    fn handler(&self) -> Self::Handler {
        match *self {
            Request::Event(_) => RequestHandler::Event,
            Request::Exit => RequestHandler::Exit,
        }
    }
}

#[derive(Debug)]
pub enum Response {
    Event(ExecResult),
    Exit
}

pub struct Dispatcher {
    contexts: Vec<Context>,
    output_channel: Sender<Response>,
    exits_received: u32
}

impl Dispatcher {
    pub fn new(contexts: Vec<config::Context>, action_output_channel: Sender<Response>) -> Dispatcher {
        let contexts = contexts.into_iter().map(|ctx| Context::from(ctx)).collect::<Vec<Context>>();
        Dispatcher {
            contexts: contexts,
            output_channel: action_output_channel,
            exits_received: 0
        }
    }

    pub fn start_loop(&mut self, channel: Receiver<Request>) {
        for i in channel.iter() {
            match i {
                Request::Event(event) => self.dispatch(event),
                Request::Exit => {
                    if self.on_exit() {
                        break;
                    }
                }
            }
        }
    }

    fn on_exit(&mut self) -> bool {
        self.exits_received += 1;
        let _ = self.output_channel.send(Response::Exit);
        self.exits_received >= 2
    }

    pub fn dispatch(&mut self, event: super::Event) {
        match event {
            super::Event::Message(event) => {
                let event = Rc::new(event);
                self.on_message(event);
            },
            super::Event::Timer(ref event) => {
                self.on_timer(event);
            }
        };
    }

    fn on_message(&mut self, event: Rc<Message>) {
        for context in self.contexts.iter_mut() {
            if let Some(result) = context.on_message(event.clone()) {
                for i in result.into_iter() {
                    let _ = self.output_channel.send(i.into());
                }
            }
        }
    }

    fn on_timer(&mut self, event: &TimerEvent) {
        for context in self.contexts.iter_mut() {
            if let Some(result) = context.on_timer(event) {
                for i in result.into_iter() {
                    let _ = self.output_channel.send(i.into());
                }
            }
        }
    }
}

use std::collections::BTreeMap;

pub struct RequestReactor {
    handlers: BTreeMap<RequestHandler, Box<reactor::EventHandler<Request, Handler=RequestHandler>>>,
    demultiplexer: Demultiplexer<Request>,
    exit_condition: Condition
}

impl RequestReactor {
    fn new(demultiplexer: Demultiplexer<Request>) -> RequestReactor {
        let exit_condition = Condition::new(false);
        let exit_handler = Box::new(handlers::exit::ExitHandler::new(exit_condition.clone()));
        let event_handler = Box::new(handlers::event::EventHandler::new());

        let mut reactor = RequestReactor {
            demultiplexer: demultiplexer,
            exit_condition: exit_condition,
            handlers: BTreeMap::new()
        };

        reactor.register_handler(exit_handler);
        reactor.register_handler(event_handler);
        reactor
    }
}

impl Reactor for RequestReactor {
    type Event = Request;
    type Handler = RequestHandler;
    fn handle_events(&mut self) {
        while !self.exit_condition.is_active() {
            if let Some(request) = self.demultiplexer.select() {
                let mut handler = self.handlers.get_mut(&request.handler()).unwrap();
                handler.handle_event(request);
            } else {
                break;
            }
        }
    }
    fn register_handler(&mut self, handler: Box<reactor::EventHandler<Self::Event, Handler=RequestHandler>>) {
        self.handlers.insert(handler.handler(), handler);
    }
    fn remove_handler(&mut self, handler: &reactor::EventHandler<Self::Event, Handler=RequestHandler>){}
}

struct Demultiplexer<T>(Receiver<T>);

impl reactor::EventDemultiplexer for Demultiplexer<Request> {
    type Event = Request;
    fn select(&mut self) -> Option<Self::Event> {
        self.0.recv().ok()
    }
}

mod handlers {
    pub mod exit {
        use dispatcher::{Request, RequestHandler};
        use condition::Condition;
        use reactor::EventHandler;

        pub struct ExitHandler{
            condition: Condition,
            stops: u32
        }

        impl ExitHandler {
            pub fn new(condition: Condition) -> ExitHandler {
                ExitHandler {
                    condition: condition,
                    stops: 0
                }
            }
        }

        impl EventHandler<Request> for ExitHandler {
            type Handler = RequestHandler;
            fn handle_event(&mut self, event: Request) {
                if let Request::Exit = event {
                    self.stops += 1;

                    if self.stops >= 2 {
                        self.condition.activate();
                    }
                } else {
                    unreachable!("An ExitHandler should only receive Exit events");
                }
            }
            fn handler(&self) -> Self::Handler {
                RequestHandler::Exit
            }
        }
    }

    pub mod event {
        use dispatcher::{Request, RequestHandler};
        use reactor;

        pub struct EventHandler;

        impl EventHandler {
            pub fn new() -> EventHandler {
                EventHandler
            }
        }

        impl reactor::EventHandler<Request> for EventHandler {
            type Handler = RequestHandler;
            fn handle_event(&mut self, event: Request) {
                if let Request::Event(_) = event {
                    println!("Event recvd");
                } else {
                    unreachable!("An EventHandler should only receive Event events");
                }
            }
            fn handler(&self) -> Self::Handler {
                RequestHandler::Event
            }
        }
    }

    mod linear {
        use dispatcher::{Request, RequestHandler};
        use EventHandler;
        use Event;
        use reactor;

        pub struct LinearHandler<C, H> {
            contexts: Vec<C>,
            handler: H
        }

        impl<C, H> LinearHandler<C, H> {
            pub fn new(handler: H) -> LinearHandler<C, H> {
                LinearHandler {
                    contexts: Vec::new(),
                    handler: handler
                }
            }
        }

        /*impl<C, H, E> reactor::EventHandler<E> for LinearHandler<C, H> {
            type Handler = H;
            fn handle_event(&mut self, event: E) {

            }
            fn handler(&self) -> Self::Handler {
                self.handler
            }
        }*/
    }
}
<|endoftext|>


<commit_before>//	MIT License
//
//  Copyright © 2017 Michael J Simms. All rights reserved.
//
//	Permission is hereby granted, free of charge, to any person obtaining a copy
//	of this software and associated documentation files (the "Software"), to deal
//	in the Software without restriction, including without limitation the rights
//	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//	copies of the Software, and to permit persons to whom the Software is
//	furnished to do so, subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in all
//	copies or substantial portions of the Software.
//
//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//	SOFTWARE.

use std::collections::HashSet;
use std::collections::HashMap;

/// Each feature has a name and value.
pub struct Feature {
    name: String,
    value: u64,
}

impl Feature {
    pub fn new (name: &str, value: u64) -> Feature {
        Feature { name: name.to_string(), value: value }
    }

    pub fn set_name(&mut self, name: String) {
        self.name = name;
    }

    pub fn get_name(&self) -> String {
        self.name
    }

    pub fn set_value(&mut self, value: u64) {
        self.value = value;
    }

    pub fn get_value(&self) -> u64 {
        self.value
    }
}

pub type FeatureList = Vec<Feature>;
pub type Uint64Set = HashSet<u64>;
pub type FeatureNameToValuesMap<'a> = HashMap<&'a str, Uint64Set>;

/// This class represents a sample.
/// Each sample has a name and list of features.
pub struct Sample {
    name: String,
    features: FeatureList,
}

impl Sample {
    pub fn new (name: &str) -> Sample {
        Sample { name: name.to_string(), features: Sample::create_feature_list() }
    }

    fn create_feature_list() -> FeatureList {
        let mut v: FeatureList = vec![];
        v
    }

    pub fn add_features(&mut self, features: &mut FeatureList) {
        self.features.append(features);
    }

    pub fn add_feature(&mut self, feature: Feature) {
        self.features.push(feature);
    }

    pub fn features(&self) -> FeatureList {
        self.features
    }
}

pub type SampleList = Vec<Sample>;

/// Tree node, used internally.
struct Node {
    feature_name: String,
    left: NodeLink,
    right: NodeLink,
}

impl Node {
    pub fn new (feature_name: &str) -> Node {
        Node { feature_name: feature_name.to_string(), left: None, right: None }
    }

    fn get_feature_name(&self) -> String {
        self.feature_name
    }

	fn set_left_subtree(&mut self, subtree: NodeLink) {
		self.left = subtree;
	}

    fn get_left_subtree(&self) -> NodeLink {
        self.left
    }

	fn set_right_subtree(&mut self, subtree: NodeLink) {
		self.right = subtree;
	}

    fn get_right_subtree(&self) -> NodeLink {
        self.right
    }
}

type NodeLink = Option<Box<Node>>;
pub type NodeList = Vec<Node>;

/// Isolation Forest implementation.
pub struct Forest<'a> {
    feature_values: FeatureNameToValuesMap<'a>, // Lists each feature and maps it to all unique values in the training set
    trees: NodeList, // The decision trees that comprise the forest
    num_trees_to_create: u32, // The maximum number of trees to create
    sub_sampling_size: u32, // The maximum depth of a tree
}

impl<'a> Forest<'a> {
    pub fn new (num_trees_to_create: u32, sub_sampling_size: u32) -> Forest<'a> {
        Forest { num_trees_to_create: num_trees_to_create, sub_sampling_size: sub_sampling_size, trees: Forest::initialize_trees(), feature_values: Forest::create_feature_name_to_values_map() }
    }

    fn initialize_trees() -> NodeList {
        let mut v: NodeList = vec![];
        v
    }

    fn create_feature_name_to_values_map() -> FeatureNameToValuesMap<'a> {
        let mut m = HashMap::new();
        m
    }

    pub fn add_sample(&self, sample: Sample) {
		// Add each of this sample's features to the list of known features
		// with the corresponding set of unique values.
		let mut features = sample.features();
        for feature in &features {
            let mut found_feature = false;
        }
    }

    pub fn create_tree(&self, feature_values: FeatureNameToValuesMap<'a>, depth: u32) -> NodeList {
        let mut tree = NodeList::new();

		// Sanity check.
		if feature_values.len() <= 1 {
			return tree;
		}

		// If we've exceeded the maximum desired depth, then stop.
		if (self.sub_sampling_size > 0) && (depth >= self.sub_sampling_size) {
			return tree;
		}

		// Randomly select a feature.
		let mut selected_feature_index = 0;
		if feature_values.len() > 1 {
			return tree;
		}

		// Get the value list to split on.

		// Randomly select a split value.
		let mut split_value_index = 0;

		// Create a tree node to hold the split value.

        tree
    }

    pub fn create(&self) {
    	for _i in 0..self.num_trees_to_create {
            let tree = self.create_tree(self.feature_values, 0);
            if tree.len() > 0 {
            }
        }
    }

    fn score_tree(&self, sample: Sample, tree: NodeLink) -> f64 {
        let mut depth = 0.0;
        let mut current_node = tree;
        let mut done = false;

        while !done {
            let mut found_feature = false;
            let current_node_deref = current_node.deref();
            let node_feature_name = current_node_deref.get_feature_name();
            let features = sample.features();

            for feature in features {
                let feature_name = feature.get_name();

                if feature_name == node_feature_name {
					if feature.get_value() < current_node_deref.split_value() {
						current_node = current_node_deref.get_left_subtree();
                    } else {
						current_node = current_node_deref.get_right_subtree();
                    }
                    found_feature = false;
                }
            }
        }
        depth
    }

    pub fn score(&self, sample: Sample) -> f64 {
        let mut score = 0.0;

        if self.trees.len() > 0 {
            for tree in self.trees {
                score += self.score_tree(sample, tree);
            }
            score /= self.trees.len() as f64;
        }
        score
    }
}
<commit_msg>Backup commit.<commit_after>//	MIT License
//
//  Copyright © 2017 Michael J Simms. All rights reserved.
//
//	Permission is hereby granted, free of charge, to any person obtaining a copy
//	of this software and associated documentation files (the "Software"), to deal
//	in the Software without restriction, including without limitation the rights
//	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//	copies of the Software, and to permit persons to whom the Software is
//	furnished to do so, subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in all
//	copies or substantial portions of the Software.
//
//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//	SOFTWARE.

use std::collections::HashSet;
use std::collections::HashMap;

/// Each feature has a name and value.
pub struct Feature {
    name: String,
    value: u64,
}

impl Feature {
    pub fn new (name: &str, value: u64) -> Feature {
        Feature { name: name.to_string(), value: value }
    }

    pub fn set_name(&mut self, name: String) {
        self.name = name;
    }

    pub fn get_name(&self) -> String {
        self.name
    }

    pub fn set_value(&mut self, value: u64) {
        self.value = value;
    }

    pub fn get_value(&self) -> u64 {
        self.value
    }
}

pub type FeatureList = Vec<Feature>;
pub type Uint64Set = HashSet<u64>;
pub type FeatureNameToValuesMap<'a> = HashMap<&'a str, Uint64Set>;

/// This class represents a sample.
/// Each sample has a name and list of features.
pub struct Sample {
    name: String,
    features: FeatureList,
}

impl Sample {
    pub fn new (name: &str) -> Sample {
        Sample { name: name.to_string(), features: Sample::create_feature_list() }
    }

    fn create_feature_list() -> FeatureList {
        let mut v: FeatureList = vec![];
        v
    }

    pub fn add_features(&mut self, features: &mut FeatureList) {
        self.features.append(features);
    }

    pub fn add_feature(&mut self, feature: Feature) {
        self.features.push(feature);
    }

    pub fn features(&self) -> FeatureList {
        self.features
    }
}

pub type SampleList = Vec<Sample>;

/// Tree node, used internally.
struct Node<'a> {
    feature_name: String,
    left: NodeLink<'a>,
    right: NodeLink<'a>,
}

impl<'a> Node<'a> {
    pub fn new (feature_name: &str) -> Node {
        Node { feature_name: feature_name.to_string(), left: None, right: None }
    }

    fn get_feature_name(&self) -> String {
        self.feature_name
    }

	fn set_left_subtree(&mut self, subtree: NodeLink<'a>) {
		self.left = subtree;
	}

    fn get_left_subtree(&self) -> NodeLink<'a> {
        self.left
    }

	fn set_right_subtree(&mut self, subtree: NodeLink<'a>) {
		self.right = subtree;
	}

    fn get_right_subtree(&self) -> NodeLink<'a> {
        self.right
    }
}

pub type NodeLink<'a> = Option<Box<Node<'a>>>;
pub type NodeList<'a> = Vec<Node<'a>>;

/// Isolation Forest implementation.
pub struct Forest<'a> {
    feature_values: FeatureNameToValuesMap<'a>, // Lists each feature and maps it to all unique values in the training set
    trees: NodeList<'a>, // The decision trees that comprise the forest
    num_trees_to_create: u32, // The maximum number of trees to create
    sub_sampling_size: u32, // The maximum depth of a tree
}

impl<'a> Forest<'a> {
    pub fn new (num_trees_to_create: u32, sub_sampling_size: u32) -> Forest<'a> {
        Forest { num_trees_to_create: num_trees_to_create, sub_sampling_size: sub_sampling_size, trees: Forest::initialize_trees(), feature_values: Forest::create_feature_name_to_values_map() }
    }

    fn initialize_trees() -> NodeList<'a> {
        let mut v: NodeList = vec![];
        v
    }

    fn create_feature_name_to_values_map() -> FeatureNameToValuesMap<'a> {
        let mut m = HashMap::new();
        m
    }

    pub fn add_sample(&self, sample: Sample) {
		// Add each of this sample's features to the list of known features
		// with the corresponding set of unique values.
		let mut features = sample.features();
        for feature in &features {
            let mut found_feature = false;
        }
    }

    pub fn create_tree(&self, feature_values: FeatureNameToValuesMap<'a>, depth: u32) -> NodeList {
        let mut tree = NodeList::new();

		// Sanity check.
		if feature_values.len() <= 1 {
			return tree;
		}

		// If we've exceeded the maximum desired depth, then stop.
		if (self.sub_sampling_size > 0) && (depth >= self.sub_sampling_size) {
			return tree;
		}

		// Randomly select a feature.
		let mut selected_feature_index = 0;
		if feature_values.len() > 1 {
			return tree;
		}

		// Get the value list to split on.

		// Randomly select a split value.
		let mut split_value_index = 0;

		// Create a tree node to hold the split value.

        tree
    }

    pub fn create(&self) {
    	for _i in 0..self.num_trees_to_create {
            let tree = self.create_tree(self.feature_values, 0);
            if tree.len() > 0 {
            }
        }
    }

    fn score_tree(&self, sample: Sample, tree: NodeLink) -> f64 {
        let mut depth = 0.0;
        let mut current_node = tree;
        let mut done = false;

        while !done {
            let mut found_feature = false;
            let current_node_deref = current_node.deref();
            let node_feature_name = current_node_deref.get_feature_name();
            let features = sample.features();

            for feature in features {
                let feature_name = feature.get_name();

                if feature_name == node_feature_name {
					if feature.get_value() < current_node_deref.split_value() {
						current_node = current_node_deref.get_left_subtree();
                    } else {
						current_node = current_node_deref.get_right_subtree();
                    }
                    found_feature = false;
                }
            }
        }
        depth
    }

    pub fn score(&self, sample: Sample) -> f64 {
        let mut score = 0.0;

        if self.trees.len() > 0 {
            for tree in self.trees {
                score += self.score_tree(sample, tree);
            }
            score /= self.trees.len() as f64;
        }
        score
    }
}
<|endoftext|>


<commit_before>//	MIT License
//
//  Copyright © 2017 Michael J Simms. All rights reserved.
//
//	Permission is hereby granted, free of charge, to any person obtaining a copy
//	of this software and associated documentation files (the "Software"), to deal
//	in the Software without restriction, including without limitation the rights
//	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//	copies of the Software, and to permit persons to whom the Software is
//	furnished to do so, subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in all
//	copies or substantial portions of the Software.
//
//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//	SOFTWARE.

extern crate rand;
use rand::distributions::IndependentSample;
use std::collections::HashMap;

/// Each feature has a name and value.
pub struct Feature {
    name: String,
    value: u64,
}

impl Feature {
    pub fn new (name: &str, value: u64) -> Feature {
        Feature { name: name.to_string(), value: value }
    }
}

pub type FeatureList = Vec<Feature>;
pub type Uint64Vec = Vec<u64>;
pub type FeatureNameToValuesMap = HashMap<String, Uint64Vec>;

/// This class represents a sample.
/// Each sample has a name and list of features.
pub struct Sample {
    features: FeatureList,
}

impl Sample {
    pub fn new () -> Sample {
        Sample { features: Sample::create_feature_list() }
    }

    fn create_feature_list() -> FeatureList {
        let v: FeatureList = vec![];
        v
    }

    pub fn add_features(&mut self, features: &mut FeatureList) {
        self.features.append(features);
    }

    pub fn add_feature(&mut self, feature: Feature) {
        self.features.push(feature);
    }
}

/// Tree node, used internally.
struct Node {
    feature_name: String,
    split_value: u64,
    left: NodeLink,
    right: NodeLink,
}

impl Node {
    pub fn new (feature_name: &str, split_value: u64) -> Node {
        Node { feature_name: feature_name.to_string(), split_value: split_value, left: None, right: None }
    }
}

type NodeBox = Box<Node>;
type NodeLink = Option<Box<Node>>;
type NodeList = Vec<Box<Node>>;

/// Isolation Forest implementation.
pub struct Forest {
    feature_values: FeatureNameToValuesMap, // Lists each feature and maps it to all unique values in the training set
    trees: NodeList, // The decision trees that comprise the forest
    num_trees_to_create: u32, // The maximum number of trees to create
    sub_sampling_size: u32, // The maximum depth of a tree
    rng: rand::ThreadRng,
}

impl Forest {
    pub fn new (num_trees_to_create: u32, sub_sampling_size: u32) -> Forest {
        Forest { num_trees_to_create: num_trees_to_create, sub_sampling_size: sub_sampling_size, trees: Forest::initialize_trees(), feature_values: Forest::create_feature_name_to_values_map(), rng: rand::thread_rng() }
    }

    fn initialize_trees() -> NodeList {
        let v: NodeList = vec![];
        v
    }

    fn create_feature_name_to_values_map() -> FeatureNameToValuesMap {
        let m = FeatureNameToValuesMap::new();
        m
    }

    pub fn add_sample(&mut self, sample: Sample) {
		// Add each of this sample's features to the list of known features
		// with the corresponding set of unique values.

        for feature in &sample.features {
            if self.feature_values.contains_key(&feature.name) {
                let mut feature_value_set = self.feature_values[&feature.name].clone();
                feature_value_set.push(feature.value);
                feature_value_set.sort_unstable();
                self.feature_values.insert(feature.name.clone(), feature_value_set);
            }
            else {
                let mut feature_value_set = Vec::new();
                feature_value_set.push(feature.value);
                self.feature_values.insert(feature.name.clone(), feature_value_set);
            }
        }
    }

    fn create_tree(&mut self, feature_values: FeatureNameToValuesMap, depth: u32) -> NodeLink {
        // Creates and returns a single tree. As this is a recursive function, depth indicates the current depth of the recursion.

		// Sanity check.
        let feature_values_len = feature_values.len();
		if feature_values_len <= 1 {
			return None;
		}

		// If we've exceeded the maximum desired depth, then stop.
		if (self.sub_sampling_size > 0) && (depth >= self.sub_sampling_size) {
			return None;
		}

		// Randomly select a feature.
        let range = rand::distributions::Range::new(0, feature_values_len);
		let selected_feature_index = range.ind_sample(&mut self.rng) as usize;
        let selected_feature_name = feature_values.keys().nth(selected_feature_index);
        let unwrapped_feature_name = selected_feature_name.unwrap();

        // Randomly select a split value.
        let mut split_value_index = 0;
        let feature_value_set = &feature_values[unwrapped_feature_name];
        let feature_value_set_len = feature_value_set.len();
        if feature_value_set_len <= 0 {
            return None;
        }
        else if feature_value_set_len >= 1 {
            let range2 = rand::distributions::Range::new(0, feature_value_set_len);
            split_value_index = range2.ind_sample(&mut self.rng) as usize;
        }
        let split_value = feature_value_set[split_value_index];

        // Create a tree node to hold the split value.
        let mut tree_root = Node::new(unwrapped_feature_name, split_value);

        // Create two versions of the feature value set that we just used,
        // one for the left side of the tree and one for the right.
        let mut temp_feature_values = feature_values.clone();
        let (left_features, right_features) = feature_value_set.split_at(split_value_index);

        // Create the left subtree.
        if left_features.len() > 0 {
            temp_feature_values.insert(unwrapped_feature_name.to_string(), left_features.to_vec());
            tree_root.left = self.create_tree(temp_feature_values.clone(), depth + 1);
        }

        // Create the right subtree.
        if right_features.len() > 0 {
            temp_feature_values.insert(unwrapped_feature_name.to_string(), right_features.to_vec());
            tree_root.right = self.create_tree(temp_feature_values.clone(), depth + 1);
        }

        let tree = Some(Box::new(tree_root));
        tree
    }

    pub fn create(&mut self) {
        // Creates a forest containing the number of trees specified to the constructor.

    	for _i in 0..self.num_trees_to_create {
            let temp_feature_values = self.feature_values.clone();
            let tree = self.create_tree(temp_feature_values, 0);
            if tree.is_some() {
                self.trees.push(tree.unwrap());
            }
        }
    }

    fn score_tree(&self, sample: &Sample, tree: &NodeBox) -> f64 {
        // Scores the sample against the specified tree.

        let mut depth = 0.0;
        let mut current_node = tree;
        let mut done = false;

        while !done {
            let mut found_feature = false;

            for current_feature in &sample.features {
                if current_feature.name == current_node.feature_name {
					if current_feature.value < current_node.split_value {
                        match current_node.left {
                            None => {
                                done = true;
                            }
                            Some(ref next_node) => {
                                current_node = next_node;
                            }
                        }
                    } else {
                        match current_node.right {
                            None => {
                                done = true;
                            }
                            Some(ref next_node) => {
                                current_node = next_node;
                            }
                        }
                    }

                    depth = depth + 1.0;
                    found_feature = true;
                }
            }

			// If the tree contained a feature not in the sample then take
			// both sides of the tree and average the scores together.
			if found_feature == false {
                let left_tree = &current_node.left;
                let right_tree = &current_node.right;
                let mut left_depth = depth;
                let mut right_depth = depth;

                match left_tree {
                    &None => {
                    }
                    &Some(ref left_tree) => {
        			    left_depth = left_depth + self.score_tree(sample, left_tree);
                    }
                }
                match right_tree {
                    &None => {
                    }
                    &Some(ref right_tree) => {
        			    right_depth = right_depth + self.score_tree(sample, right_tree);
                    }
                }
				depth = (left_depth + right_depth) / 2.0;
                return depth;
            }
        }
        depth
    }

    pub fn score(&self, sample: &Sample) -> f64 {
        // Scores the sample against the entire forest of trees.

        let mut score = 0.0;

        if self.trees.len() > 0 {
            for tree in &self.trees {
                score += self.score_tree(sample, tree) as f64;
            }
            score /= self.trees.len() as f64;
        }
        score
    }
}
<commit_msg>Backup commit.<commit_after>//	MIT License
//
//  Copyright © 2017 Michael J Simms. All rights reserved.
//
//	Permission is hereby granted, free of charge, to any person obtaining a copy
//	of this software and associated documentation files (the "Software"), to deal
//	in the Software without restriction, including without limitation the rights
//	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//	copies of the Software, and to permit persons to whom the Software is
//	furnished to do so, subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in all
//	copies or substantial portions of the Software.
//
//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//	SOFTWARE.

extern crate rand;
use rand::distributions::IndependentSample;
use std::collections::HashMap;

/// Each feature has a name and value.
pub struct Feature {
    name: String,
    value: u64,
}

impl Feature {
    pub fn new (name: &str, value: u64) -> Feature {
        Feature { name: name.to_string(), value: value }
    }
}

pub type FeatureList = Vec<Feature>;
pub type Uint64Vec = Vec<u64>;
pub type FeatureNameToValuesMap = HashMap<String, Uint64Vec>;

/// This class represents a sample.
/// Each sample has a name and list of features.
pub struct Sample {
    features: FeatureList,
}

impl Sample {
    pub fn new () -> Sample {
        Sample { features: Sample::create_feature_list() }
    }

    fn create_feature_list() -> FeatureList {
        let v: FeatureList = vec![];
        v
    }

    pub fn add_features(&mut self, features: &mut FeatureList) {
        self.features.append(features);
    }
}

/// Tree node, used internally.
struct Node {
    feature_name: String,
    split_value: u64,
    left: NodeLink,
    right: NodeLink,
}

impl Node {
    pub fn new (feature_name: &str, split_value: u64) -> Node {
        Node { feature_name: feature_name.to_string(), split_value: split_value, left: None, right: None }
    }
}

type NodeBox = Box<Node>;
type NodeLink = Option<Box<Node>>;
type NodeList = Vec<Box<Node>>;

/// Isolation Forest implementation.
pub struct Forest {
    feature_values: FeatureNameToValuesMap, // Lists each feature and maps it to all unique values in the training set
    trees: NodeList, // The decision trees that comprise the forest
    num_trees_to_create: u32, // The maximum number of trees to create
    sub_sampling_size: u32, // The maximum depth of a tree
    rng: rand::ThreadRng,
}

impl Forest {
    pub fn new (num_trees_to_create: u32, sub_sampling_size: u32) -> Forest {
        Forest { num_trees_to_create: num_trees_to_create, sub_sampling_size: sub_sampling_size, trees: Forest::initialize_trees(), feature_values: Forest::create_feature_name_to_values_map(), rng: rand::thread_rng() }
    }

    fn initialize_trees() -> NodeList {
        let v: NodeList = vec![];
        v
    }

    fn create_feature_name_to_values_map() -> FeatureNameToValuesMap {
        let m = FeatureNameToValuesMap::new();
        m
    }

    pub fn add_sample(&mut self, sample: Sample) {
		// Add each of this sample's features to the list of known features
		// with the corresponding set of unique values.

        for feature in &sample.features {
            if self.feature_values.contains_key(&feature.name) {
                let mut feature_value_set = self.feature_values[&feature.name].clone();
                feature_value_set.push(feature.value);
                feature_value_set.sort_unstable();
                self.feature_values.insert(feature.name.clone(), feature_value_set);
            }
            else {
                let mut feature_value_set = Vec::new();
                feature_value_set.push(feature.value);
                self.feature_values.insert(feature.name.clone(), feature_value_set);
            }
        }
    }

    fn create_tree(&mut self, feature_values: FeatureNameToValuesMap, depth: u32) -> NodeLink {
        // Creates and returns a single tree. As this is a recursive function, depth indicates the current depth of the recursion.

		// Sanity check.
        let feature_values_len = feature_values.len();
		if feature_values_len <= 1 {
			return None;
		}

		// If we've exceeded the maximum desired depth, then stop.
		if (self.sub_sampling_size > 0) && (depth >= self.sub_sampling_size) {
			return None;
		}

		// Randomly select a feature.
        let range = rand::distributions::Range::new(0, feature_values_len);
		let selected_feature_index = range.ind_sample(&mut self.rng) as usize;
        let selected_feature_name = feature_values.keys().nth(selected_feature_index);
        let unwrapped_feature_name = selected_feature_name.unwrap();

        // Randomly select a split value.
        let mut split_value_index = 0;
        let feature_value_set = &feature_values[unwrapped_feature_name];
        let feature_value_set_len = feature_value_set.len();
        if feature_value_set_len <= 0 {
            return None;
        }
        else if feature_value_set_len >= 1 {
            let range2 = rand::distributions::Range::new(0, feature_value_set_len);
            split_value_index = range2.ind_sample(&mut self.rng) as usize;
        }
        let split_value = feature_value_set[split_value_index];

        // Create a tree node to hold the split value.
        let mut tree_root = Node::new(unwrapped_feature_name, split_value);

        // Create two versions of the feature value set that we just used,
        // one for the left side of the tree and one for the right.
        let mut temp_feature_values = feature_values.clone();
        let (left_features, right_features) = feature_value_set.split_at(split_value_index);

        // Create the left subtree.
        temp_feature_values.insert(unwrapped_feature_name.to_string(), left_features.to_vec());
        tree_root.left = self.create_tree(temp_feature_values.clone(), depth + 1);

        // Create the right subtree.
        if right_features.len() > 0 {
            temp_feature_values.insert(unwrapped_feature_name.to_string(), right_features.to_vec());
            tree_root.right = self.create_tree(temp_feature_values.clone(), depth + 1);
        }

        let tree = Some(Box::new(tree_root));
        tree
    }

    pub fn create(&mut self) {
        // Creates a forest containing the number of trees specified to the constructor.

    	for _i in 0..self.num_trees_to_create {
            let temp_feature_values = self.feature_values.clone();
            let tree = self.create_tree(temp_feature_values, 0);
            if tree.is_some() {
                self.trees.push(tree.unwrap());
            }
        }
    }

    fn score_tree(&self, sample: &Sample, tree: &NodeBox) -> f64 {
        // Scores the sample against the specified tree.

        let mut depth = 0.0;
        let mut current_node = tree;
        let mut done = false;

        while !done {
            let mut found_feature = false;

            for current_feature in &sample.features {

                // If the current node has the feature in question.
                if current_feature.name == current_node.feature_name {
					if current_feature.value < current_node.split_value {
                        match current_node.left {
                            None => {
                                done = true;
                            }
                            Some(ref next_node) => {
                                current_node = next_node;
                            }
                        }
                    } else {
                        match current_node.right {
                            None => {
                                done = true;
                            }
                            Some(ref next_node) => {
                                current_node = next_node;
                            }
                        }
                    }

                    depth = depth + 1.0;
                    found_feature = true;
                }
            }

			// If the tree contained a feature not in the sample then take
			// both sides of the tree and average the scores together.
			if found_feature == false {
                let left_tree = &current_node.left;
                let right_tree = &current_node.right;
                let mut left_depth = depth;
                let mut right_depth = depth;

                match left_tree {
                    &None => {
                    }
                    &Some(ref left_tree) => {
        			    left_depth = left_depth + self.score_tree(sample, left_tree);
                    }
                }
                match right_tree {
                    &None => {
                    }
                    &Some(ref right_tree) => {
        			    right_depth = right_depth + self.score_tree(sample, right_tree);
                    }
                }
				depth = (left_depth + right_depth) / 2.0;
                return depth;
            }
        }
        depth
    }

    pub fn score(&self, sample: &Sample) -> f64 {
        // Scores the sample against the entire forest of trees.

        let mut score = 0.0;

        if self.trees.len() > 0 {
            for tree in &self.trees {
                score += self.score_tree(sample, tree) as f64;
            }
            score /= self.trees.len() as f64;
        }
        score
    }
}
<|endoftext|>


<commit_before>use mio::{Evented,Poll,PollOpt,Ready,Token};
use mio_uds::UnixStream;
use std::fmt::Debug;
use std::iter::Iterator;
use std::str::from_utf8;
use std::marker::PhantomData;
use std::io::{self,Read,Write,ErrorKind};
use std::os::unix::net;
use std::os::unix::io::{AsRawFd,FromRawFd,IntoRawFd,RawFd};
use std::cmp::min;
use serde_json;
use serde::ser::Serialize;
use serde::de::Deserialize;

use network::buffer::Buffer;

#[derive(Debug,PartialEq)]
pub enum ConnError {
  Continue,
  ParseError,
  SocketError,
}

pub struct Channel<Tx,Rx> {
  pub sock:        UnixStream,
  front_buf:       Buffer,
  back_buf:        Buffer,
  max_buffer_size: usize,
  pub readiness:   Ready,
  pub interest:    Ready,
  blocking:        bool,
  phantom_tx:      PhantomData<Tx>,
  phantom_rx:      PhantomData<Rx>,
}

impl<'de, Tx: Debug+Serialize, Rx: Debug+Deserialize<'de>> Channel<Tx,Rx> {
  pub fn new(sock: UnixStream, buffer_size: usize, max_buffer_size: usize) -> Channel<Tx,Rx> {
    Channel {
      sock:            sock,
      front_buf:       Buffer::with_capacity(buffer_size),
      back_buf:        Buffer::with_capacity(buffer_size),
      max_buffer_size: max_buffer_size,
      readiness:       Ready::empty(),
      interest:        Ready::readable(),
      blocking:        false,
      phantom_tx:      PhantomData,
      phantom_rx:      PhantomData,
    }
  }

  pub fn into<Tx2: Debug+Serialize, Rx2: Debug+Deserialize<'de>>(self) -> Channel<Tx2,Rx2> {
    Channel {
      sock:            self.sock,
      front_buf:       self.front_buf,
      back_buf:        self.back_buf,
      max_buffer_size: self.max_buffer_size,
      readiness:       self.readiness,
      interest:        self.interest,
      blocking:        self.blocking,
      phantom_tx:      PhantomData,
      phantom_rx:      PhantomData,
    }
  }

  pub fn set_nonblocking(&mut self, nonblocking: bool) {
    unsafe {
      let fd = self.sock.as_raw_fd();
      let stream = net::UnixStream::from_raw_fd(fd);
      stream.set_nonblocking(nonblocking);
      let fd = stream.into_raw_fd();
    }
    self.blocking = !nonblocking;
  }

  pub fn set_blocking(&mut self, blocking: bool) {
    self.set_nonblocking(!blocking)
  }

  pub fn fd(&self) -> RawFd {
    self.sock.as_raw_fd()
  }

  pub fn handle_events(&mut self, events: Ready) {
    self.readiness = self.readiness | events;
  }

  pub fn run(&mut self) {
    let interest = self.interest & self.readiness;

    if interest.is_readable() {
      self.readable();
    }

    if interest.is_writable() {
      self.writable();
    }
  }

  pub fn readable(&mut self) -> Result<usize,ConnError> {
    if !(self.interest & self.readiness).is_readable() {
      return Err(ConnError::Continue);
    }

    let mut count = 0usize;
    loop {
      let size = self.front_buf.available_space();
      if size == 0 {
        self.interest.remove(Ready::readable());
        break;
      }

      match self.sock.read(self.front_buf.space()) {
        Ok(0) => {
          break;
        },
        Err(e) => {
          match e.kind() {
            ErrorKind::WouldBlock => {
              self.readiness.remove(Ready::readable());
              break;
            },
            _ => {
              //log!(log::LogLevel::Error, "UNIX CLIENT[{}] read error (kind: {:?}): {:?}", tok.0, code, e);
              self.interest  = Ready::empty();
              self.readiness = Ready::empty();
              return Err(ConnError::SocketError);
            }
          }
        },
        Ok(r) => {
          count += r;
          self.front_buf.fill(r);
          //debug!("UNIX CLIENT[{}] sent {} bytes: {:?}", tok.0, r, from_utf8(self.buf.data()));
        },
      };
    }

    Ok(count)
  }

  pub fn writable(&mut self) -> Result<usize,ConnError> {
    if !(self.interest & self.readiness).is_writable() {
      return Err(ConnError::Continue);
    }

    let mut count = 0usize;
    loop {
      let size = self.back_buf.available_data();
      if size == 0 {
        self.interest.remove(Ready::writable());
        break;
      }

      match self.sock.write(self.back_buf.data()) {
        Ok(0) => {
          break;
        },
        Ok(r) => {
          count += r;
          self.back_buf.consume(r);
        },
        Err(e) => {
          match e.kind() {
            ErrorKind::WouldBlock => {
              self.interest.remove(Ready::writable());
              break;
            },
            _ => {
              self.interest  = Ready::empty();
              self.readiness = Ready::empty();
              return Err(ConnError::SocketError);
            }
          }
        }
      }
    }

    Ok(count)
  }

  pub fn read_message(&mut self) -> Option<Rx> {
    if self.blocking {
      self.read_message_blocking()
    } else {
      self.read_message_nonblocking()
    }
  }

  pub fn read_message_nonblocking(&mut self) -> Option<Rx> {
    if let Some(pos) = self.front_buf.data().iter().position(|&x| x == 0) {
      let mut res = None;

      if let Ok(s) = from_utf8(&self.front_buf.data()[..pos]) {
        match serde_json::from_str(s) {
          Ok(message) => res = Some(message),
          Err(e) => error!("could not parse message (error={:?}), ignoring:\n{}", e, s),
        }
      } else {
        error!("invalid utf-8 encoding in command message, ignoring");
      }

      self.front_buf.consume(pos+1);
      res
    } else {
      if self.front_buf.available_space() == 0 {
        if self.front_buf.capacity() == self.max_buffer_size {
          error!("command buffer full, cannot grow more, ignoring");
        } else {
          let new_size = min(self.front_buf.capacity()+5000, self.max_buffer_size);
          self.front_buf.grow(new_size);
        }
      }

      self.interest.insert(Ready::readable());
      None
    }
  }

  pub fn read_message_blocking(&mut self) -> Option<Rx> {
    loop {
      if let Some(pos) = self.front_buf.data().iter().position(|&x| x == 0) {
        let mut res = None;

        if let Ok(s) = from_utf8(&self.front_buf.data()[..pos]) {
          match serde_json::from_str(s) {
            Ok(message) => res = Some(message),
            Err(e) => error!("could not parse message (error={:?}), ignoring:\n{}", e, s),
          }
        } else {
          error!("invalid utf-8 encoding in command message, ignoring");
        }

        self.front_buf.consume(pos+1);
        return res;
      } else {
        if self.front_buf.available_space() == 0 {
          if self.front_buf.capacity() == self.max_buffer_size {
            error!("command buffer full, cannot grow more, ignoring");
            return None;
          } else {
            let new_size = min(self.front_buf.capacity()+5000, self.max_buffer_size);
            self.front_buf.grow(new_size);
          }
        }

        match self.sock.read(self.front_buf.space()) {
          Ok(0) => {
          },
          Err(_) => { return None; },
          Ok(r) => {
            self.front_buf.fill(r);
          },
        };
      }
    }
  }

  pub fn write_message(&mut self, message: &Tx) -> bool {
    if self.blocking {
      self.write_message_blocking(message)
    } else {
      self.write_message_nonblocking(message)
    }
  }

  pub fn write_message_nonblocking(&mut self, message: &Tx) -> bool {
    let message = &serde_json::to_string(message).map(|s| s.into_bytes()).unwrap_or(vec!());

    let msg_len = message.len() + 1;
    if msg_len > self.back_buf.available_space() {
      self.back_buf.shift();
    }

    if msg_len > self.back_buf.available_space() {
      if msg_len - self.back_buf.available_space() + self.back_buf.capacity() > self.max_buffer_size {
        error!("message is too large to write to back buffer. Consider increasing proxy channel buffer size, current value is {}", self.back_buf.capacity());
        return false;
      }

      let new_len = msg_len - self.back_buf.available_space() + self.back_buf.capacity();
      self.back_buf.grow( new_len );
    }

    self.back_buf.write(message);
    self.back_buf.write(&b"\0"[..]);
    self.interest.insert(Ready::writable());

    true
  }

  pub fn write_message_blocking(&mut self, message: &Tx) -> bool {
    let message = &serde_json::to_string(message).map(|s| s.into_bytes()).unwrap_or(vec!());

    let msg_len = message.len() + 1;
    if msg_len > self.back_buf.available_space() {
      self.back_buf.shift();
    }

    if msg_len > self.back_buf.available_space() {
      if msg_len - self.back_buf.available_space() + self.back_buf.capacity() > self.max_buffer_size {
        error!("message is too large to write to back buffer. Consider increasing proxy channel buffer size, current value is {}", self.back_buf.capacity());
        return false;
      }

      let new_len = msg_len - self.back_buf.available_space() + self.back_buf.capacity();
      self.back_buf.grow( new_len );
    }

    self.back_buf.write(message);
    self.back_buf.write(&b"\0"[..]);

    loop {
      let size = self.back_buf.available_data();
      if size == 0 {
        break;
      }

      match self.sock.write(self.back_buf.data()) {
        Ok(r) => {
          self.back_buf.consume(r);
        },
        Err(_) => {
          return true;
        }
      }
    }
    true
  }
}

impl<'de, Tx: Debug+Deserialize<'de>+Serialize, Rx: Debug+Deserialize<'de>+Serialize> Channel<Tx,Rx> {
  pub fn generate(buffer_size: usize, max_buffer_size: usize) -> io::Result<(Channel<Tx,Rx>, Channel<Rx,Tx>)> {
    let     (command,proxy) = try!(UnixStream::pair());
    let     proxy_channel   = Channel::new(proxy, buffer_size, max_buffer_size);
    let mut command_channel = Channel::new(command, buffer_size, max_buffer_size);
    command_channel.set_nonblocking(false);
    Ok((command_channel, proxy_channel))
  }

  pub fn generate_nonblocking(buffer_size: usize, max_buffer_size: usize) -> io::Result<(Channel<Tx,Rx>, Channel<Rx,Tx>)> {
    let (command,proxy) = try!(UnixStream::pair());
    let proxy_channel   = Channel::new(proxy, buffer_size, max_buffer_size);
    let command_channel = Channel::new(command, buffer_size, max_buffer_size);
    Ok((command_channel, proxy_channel))
  }
}

impl<'de, Tx: Debug+Serialize, Rx: Debug+Deserialize<'de>> Iterator for Channel<Tx,Rx> {
  type Item = Rx;
  fn next(&mut self) -> Option<Self::Item> {
    self.read_message()
  }
}

impl<Tx,Rx> Evented for Channel<Tx,Rx> {
  fn register(&self,
              poll: &Poll,
              token: Token,
              interest: Ready,
              opts: PollOpt)
              -> io::Result<()> {
    self.sock.register(poll, token, interest, opts)
  }

  fn reregister(&self,
                poll: &Poll,
                token: Token,
                interest: Ready,
                opts: PollOpt)
                -> io::Result<()> {
    self.sock.reregister(poll, token, interest, opts)
  }

  fn deregister(&self, poll: &Poll) -> io::Result<()> {
    self.sock.deregister(poll)
  }
}
<commit_msg>Use DeserializeOwned instead of Deserialize trait<commit_after>use mio::{Evented,Poll,PollOpt,Ready,Token};
use mio_uds::UnixStream;
use std::fmt::Debug;
use std::iter::Iterator;
use std::str::from_utf8;
use std::marker::PhantomData;
use std::io::{self,Read,Write,ErrorKind};
use std::os::unix::net;
use std::os::unix::io::{AsRawFd,FromRawFd,IntoRawFd,RawFd};
use std::cmp::min;
use serde_json;
use serde::ser::Serialize;
use serde::de::DeserializeOwned;

use network::buffer::Buffer;

#[derive(Debug,PartialEq)]
pub enum ConnError {
  Continue,
  ParseError,
  SocketError,
}

pub struct Channel<Tx,Rx> {
  pub sock:        UnixStream,
  front_buf:       Buffer,
  back_buf:        Buffer,
  max_buffer_size: usize,
  pub readiness:   Ready,
  pub interest:    Ready,
  blocking:        bool,
  phantom_tx:      PhantomData<Tx>,
  phantom_rx:      PhantomData<Rx>,
}

impl<Tx: Debug+Serialize, Rx: Debug+DeserializeOwned> Channel<Tx,Rx> {
  pub fn new(sock: UnixStream, buffer_size: usize, max_buffer_size: usize) -> Channel<Tx,Rx> {
    Channel {
      sock:            sock,
      front_buf:       Buffer::with_capacity(buffer_size),
      back_buf:        Buffer::with_capacity(buffer_size),
      max_buffer_size: max_buffer_size,
      readiness:       Ready::empty(),
      interest:        Ready::readable(),
      blocking:        false,
      phantom_tx:      PhantomData,
      phantom_rx:      PhantomData,
    }
  }

  pub fn into<Tx2: Debug+Serialize, Rx2: Debug+DeserializeOwned>(self) -> Channel<Tx2,Rx2> {
    Channel {
      sock:            self.sock,
      front_buf:       self.front_buf,
      back_buf:        self.back_buf,
      max_buffer_size: self.max_buffer_size,
      readiness:       self.readiness,
      interest:        self.interest,
      blocking:        self.blocking,
      phantom_tx:      PhantomData,
      phantom_rx:      PhantomData,
    }
  }

  pub fn set_nonblocking(&mut self, nonblocking: bool) {
    unsafe {
      let fd = self.sock.as_raw_fd();
      let stream = net::UnixStream::from_raw_fd(fd);
      stream.set_nonblocking(nonblocking);
      let fd = stream.into_raw_fd();
    }
    self.blocking = !nonblocking;
  }

  pub fn set_blocking(&mut self, blocking: bool) {
    self.set_nonblocking(!blocking)
  }

  pub fn fd(&self) -> RawFd {
    self.sock.as_raw_fd()
  }

  pub fn handle_events(&mut self, events: Ready) {
    self.readiness = self.readiness | events;
  }

  pub fn run(&mut self) {
    let interest = self.interest & self.readiness;

    if interest.is_readable() {
      self.readable();
    }

    if interest.is_writable() {
      self.writable();
    }
  }

  pub fn readable(&mut self) -> Result<usize,ConnError> {
    if !(self.interest & self.readiness).is_readable() {
      return Err(ConnError::Continue);
    }

    let mut count = 0usize;
    loop {
      let size = self.front_buf.available_space();
      if size == 0 {
        self.interest.remove(Ready::readable());
        break;
      }

      match self.sock.read(self.front_buf.space()) {
        Ok(0) => {
          break;
        },
        Err(e) => {
          match e.kind() {
            ErrorKind::WouldBlock => {
              self.readiness.remove(Ready::readable());
              break;
            },
            _ => {
              //log!(log::LogLevel::Error, "UNIX CLIENT[{}] read error (kind: {:?}): {:?}", tok.0, code, e);
              self.interest  = Ready::empty();
              self.readiness = Ready::empty();
              return Err(ConnError::SocketError);
            }
          }
        },
        Ok(r) => {
          count += r;
          self.front_buf.fill(r);
          //debug!("UNIX CLIENT[{}] sent {} bytes: {:?}", tok.0, r, from_utf8(self.buf.data()));
        },
      };
    }

    Ok(count)
  }

  pub fn writable(&mut self) -> Result<usize,ConnError> {
    if !(self.interest & self.readiness).is_writable() {
      return Err(ConnError::Continue);
    }

    let mut count = 0usize;
    loop {
      let size = self.back_buf.available_data();
      if size == 0 {
        self.interest.remove(Ready::writable());
        break;
      }

      match self.sock.write(self.back_buf.data()) {
        Ok(0) => {
          break;
        },
        Ok(r) => {
          count += r;
          self.back_buf.consume(r);
        },
        Err(e) => {
          match e.kind() {
            ErrorKind::WouldBlock => {
              self.interest.remove(Ready::writable());
              break;
            },
            _ => {
              self.interest  = Ready::empty();
              self.readiness = Ready::empty();
              return Err(ConnError::SocketError);
            }
          }
        }
      }
    }

    Ok(count)
  }

  pub fn read_message(&mut self) -> Option<Rx> {
    if self.blocking {
      self.read_message_blocking()
    } else {
      self.read_message_nonblocking()
    }
  }

  pub fn read_message_nonblocking(&mut self) -> Option<Rx> {
    if let Some(pos) = self.front_buf.data().iter().position(|&x| x == 0) {
      let mut res = None;

      if let Ok(s) = from_utf8(&self.front_buf.data()[..pos]) {
        match serde_json::from_str(s) {
          Ok(message) => res = Some(message),
          Err(e) => error!("could not parse message (error={:?}), ignoring:\n{}", e, s),
        }
      } else {
        error!("invalid utf-8 encoding in command message, ignoring");
      }

      self.front_buf.consume(pos+1);
      res
    } else {
      if self.front_buf.available_space() == 0 {
        if self.front_buf.capacity() == self.max_buffer_size {
          error!("command buffer full, cannot grow more, ignoring");
        } else {
          let new_size = min(self.front_buf.capacity()+5000, self.max_buffer_size);
          self.front_buf.grow(new_size);
        }
      }

      self.interest.insert(Ready::readable());
      None
    }
  }

  pub fn read_message_blocking(&mut self) -> Option<Rx> {
    loop {
      if let Some(pos) = self.front_buf.data().iter().position(|&x| x == 0) {
        let mut res = None;

        if let Ok(s) = from_utf8(&self.front_buf.data()[..pos]) {
          match serde_json::from_str(s) {
            Ok(message) => res = Some(message),
            Err(e) => error!("could not parse message (error={:?}), ignoring:\n{}", e, s),
          }
        } else {
          error!("invalid utf-8 encoding in command message, ignoring");
        }

        self.front_buf.consume(pos+1);
        return res;
      } else {
        if self.front_buf.available_space() == 0 {
          if self.front_buf.capacity() == self.max_buffer_size {
            error!("command buffer full, cannot grow more, ignoring");
            return None;
          } else {
            let new_size = min(self.front_buf.capacity()+5000, self.max_buffer_size);
            self.front_buf.grow(new_size);
          }
        }

        match self.sock.read(self.front_buf.space()) {
          Ok(0) => {
          },
          Err(_) => { return None; },
          Ok(r) => {
            self.front_buf.fill(r);
          },
        };
      }
    }
  }

  pub fn write_message(&mut self, message: &Tx) -> bool {
    if self.blocking {
      self.write_message_blocking(message)
    } else {
      self.write_message_nonblocking(message)
    }
  }

  pub fn write_message_nonblocking(&mut self, message: &Tx) -> bool {
    let message = &serde_json::to_string(message).map(|s| s.into_bytes()).unwrap_or(vec!());

    let msg_len = message.len() + 1;
    if msg_len > self.back_buf.available_space() {
      self.back_buf.shift();
    }

    if msg_len > self.back_buf.available_space() {
      if msg_len - self.back_buf.available_space() + self.back_buf.capacity() > self.max_buffer_size {
        error!("message is too large to write to back buffer. Consider increasing proxy channel buffer size, current value is {}", self.back_buf.capacity());
        return false;
      }

      let new_len = msg_len - self.back_buf.available_space() + self.back_buf.capacity();
      self.back_buf.grow( new_len );
    }

    self.back_buf.write(message);
    self.back_buf.write(&b"\0"[..]);
    self.interest.insert(Ready::writable());

    true
  }

  pub fn write_message_blocking(&mut self, message: &Tx) -> bool {
    let message = &serde_json::to_string(message).map(|s| s.into_bytes()).unwrap_or(vec!());

    let msg_len = message.len() + 1;
    if msg_len > self.back_buf.available_space() {
      self.back_buf.shift();
    }

    if msg_len > self.back_buf.available_space() {
      if msg_len - self.back_buf.available_space() + self.back_buf.capacity() > self.max_buffer_size {
        error!("message is too large to write to back buffer. Consider increasing proxy channel buffer size, current value is {}", self.back_buf.capacity());
        return false;
      }

      let new_len = msg_len - self.back_buf.available_space() + self.back_buf.capacity();
      self.back_buf.grow( new_len );
    }

    self.back_buf.write(message);
    self.back_buf.write(&b"\0"[..]);

    loop {
      let size = self.back_buf.available_data();
      if size == 0 {
        break;
      }

      match self.sock.write(self.back_buf.data()) {
        Ok(r) => {
          self.back_buf.consume(r);
        },
        Err(_) => {
          return true;
        }
      }
    }
    true
  }
}

impl<Tx: Debug+DeserializeOwned+Serialize, Rx: Debug+DeserializeOwned+Serialize> Channel<Tx,Rx> {
  pub fn generate(buffer_size: usize, max_buffer_size: usize) -> io::Result<(Channel<Tx,Rx>, Channel<Rx,Tx>)> {
    let     (command,proxy) = try!(UnixStream::pair());
    let     proxy_channel   = Channel::new(proxy, buffer_size, max_buffer_size);
    let mut command_channel = Channel::new(command, buffer_size, max_buffer_size);
    command_channel.set_nonblocking(false);
    Ok((command_channel, proxy_channel))
  }

  pub fn generate_nonblocking(buffer_size: usize, max_buffer_size: usize) -> io::Result<(Channel<Tx,Rx>, Channel<Rx,Tx>)> {
    let (command,proxy) = try!(UnixStream::pair());
    let proxy_channel   = Channel::new(proxy, buffer_size, max_buffer_size);
    let command_channel = Channel::new(command, buffer_size, max_buffer_size);
    Ok((command_channel, proxy_channel))
  }
}

impl<Tx: Debug+Serialize, Rx: Debug+DeserializeOwned> Iterator for Channel<Tx,Rx> {
  type Item = Rx;
  fn next(&mut self) -> Option<Self::Item> {
    self.read_message()
  }
}

impl<Tx,Rx> Evented for Channel<Tx,Rx> {
  fn register(&self,
              poll: &Poll,
              token: Token,
              interest: Ready,
              opts: PollOpt)
              -> io::Result<()> {
    self.sock.register(poll, token, interest, opts)
  }

  fn reregister(&self,
                poll: &Poll,
                token: Token,
                interest: Ready,
                opts: PollOpt)
                -> io::Result<()> {
    self.sock.reregister(poll, token, interest, opts)
  }

  fn deregister(&self, poll: &Poll) -> io::Result<()> {
    self.sock.deregister(poll)
  }
}
<|endoftext|>


<commit_before>pub mod search;

use std::thread;
use std::sync::Arc;
use std::sync::mpsc::{channel, Sender, Receiver};
use basetypes::*;
use uci::{UciEngine, UciEngineFactory, EngineReply, OptionName, OptionDescription};
use position::Position;
use chess_move::*;
use tt::TranspositionTable;

// use rand;
// use rand::distributions::{Sample, Range};
// let mut rng = rand::thread_rng();
// let mut between = Range::new(0, 10);
// let x = between.sample(&mut rng);

const VERSION: &'static str = "0.1";

/// Implements `UciEngine` trait.
pub struct Engine {
    position: Position,
    pondering_is_allowed: bool,
    multi_pv: usize,
    is_thinking: bool,
    is_pondering: bool,
    replies: Vec<EngineReply>,
    infinite: bool,
    tt: Arc<TranspositionTable>,
    commands: Sender<search::Command>,
    reports: Receiver<search::Progress>,
    results: Receiver<search::Done>,
    searcher: thread::JoinHandle<()>,
}

impl Engine {
    /// Creates a new instance.
    ///
    /// `tt_size_mb` is the preferred size of the transposition
    /// table in Mbytes.
    pub fn new(tt_size_mb: usize) -> Engine {
        let (commands_tx, commands_rx) = channel();
        let (reports_tx, reports_rx) = channel();
        let (results_tx, results_rx) = channel();
        let mut tt = TranspositionTable::new();
        tt.resize(tt_size_mb);
        let tt = Arc::new(tt);
        Engine {
            position: Position::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w QKqk - 0 \
                                          1")
                          .ok()
                          .unwrap(),
            pondering_is_allowed: false,
            multi_pv: 1,
            is_thinking: false,
            is_pondering: false,
            replies: vec![],
            infinite: false,
            tt: tt.clone(),
            commands: commands_tx,
            reports: reports_rx,
            results: results_rx,
            searcher: thread::spawn(move || {
                search::run(&tt, commands_rx, reports_tx, results_tx);
            }),
        }
    }
}

impl UciEngine for Engine {
    fn set_option(&mut self, name: &str, value: &str) {
        match name {
            // We do not support re-sizing of the transposition table
            // once the engine had started, so we do nothing.
            "Hash" => (),

            // Tells the engine that it will be allowed to ponder.
            // This option is needed because the engine might change
            // its time management algorithm when pondering is
            // allowed.
            "Ponder" => {
                self.pondering_is_allowed = value == "true";
            }

            // Tells the engine to output multiple best lines.
            // the default value is `1`.)
            "MultiPV" => {
                self.multi_pv = value.parse::<usize>().ok().unwrap_or(1);
            }

            // An invalid option.
            _ => {
                self.replies.push(EngineReply::Info(vec![("string".to_string(),
                                                          format!("Invalid option \"{}\"", name))]));
            }
        }
    }

    fn new_game(&mut self) {
        // Clearing the transposition table would not change anything,
        // so we do nothing.
    }

    fn position(&mut self, fen: &str, moves: &mut Iterator<Item = &str>) {
        if !self.is_thinking {
            if let Ok(p) = Position::from_history(fen, moves) {
                self.position = p;
            }
        }
    }

    #[allow(unused_variables)]
    fn go(&mut self,
          searchmoves: Option<Vec<String>>,
          ponder: bool,
          wtime: Option<u64>,
          btime: Option<u64>,
          winc: Option<u64>,
          binc: Option<u64>,
          movestogo: Option<u64>,
          depth: Option<u64>,
          nodes: Option<u64>,
          mate: Option<u64>,
          movetime: Option<u64>,
          infinite: bool) {
        if !self.is_thinking {
            self.commands
                .send(search::Command::Search(search::Parameters {
                    id: 0,
                    position: self.position.clone(),
                    depth: 5,
                    lower_bound: -20000,
                    upper_bound: 20000,
                }))
                .unwrap();
            self.is_thinking = true;
            self.is_pondering = ponder;
            self.infinite = infinite;
        }
    }

    fn ponder_hit(&mut self) {
        if self.is_thinking && self.is_pondering {
            self.is_pondering = false;
        }
    }

    fn stop(&mut self) {
        if self.is_thinking {
            self.commands.send(search::Command::Stop).unwrap();
            let best_move = self.get_best_move();
            self.replies.push(EngineReply::BestMove {
                best_move: best_move,
                ponder_move: None,
            });
            self.is_thinking = false;
        }
    }

    fn is_thinking(&self) -> bool {
        self.is_thinking
    }

    fn get_reply(&mut self) -> Option<EngineReply> {
        // TODO: do interactive deepening instead.
        if !self.is_pondering {
            if let Ok(_) = self.results.try_recv() {
                self.stop();
            }
        }

        self.replies.pop()
    }
}

impl Engine {
    fn get_best_move(&mut self) -> String {
        let mut m = match self.tt.probe(self.position.hash()) {
            Some(entry) => entry.move16(),
            None => 0,
        };
        if m == 0 {
            // Pick the first legal move.
            let mut first_legal_move = Move::from_u32(0);
            let mut v = Vec::with_capacity(128);
            self.position.generate_moves(&mut v);
            while let Some(x) = v.pop() {
                if self.position.do_move(x) {
                    self.position.undo_move();
                    first_legal_move = x;
                    break;
                }
            }
            m = first_legal_move.move16();
        }
        if m != 0 {
            let move_type = ((m & 0b1100000000000000) >> 14) as MoveType;
            let orig_square = ((m & 0b0011111100000000) >> 8) as Square;
            let dest_square = ((m & 0b0000000011111100) >> 2) as Square;
            let promoted_piece = match m & 0b11 {
                0 => "q",
                1 => "r",
                2 => "b",
                3 => "n",
                _ => panic!("invalid promoted piece code"),
            };
            format!("{}{}{}",
                    notation(orig_square),
                    notation(dest_square),
                    if move_type == MOVE_PROMOTION {
                        promoted_piece
                    } else {
                        ""
                    })

        } else {
            "0000".to_string()
        }
    }
}

/// Implements `UciEngineFactory` trait.
pub struct EngineFactory;

impl UciEngineFactory<Engine> for EngineFactory {
    fn name(&self) -> String {
        format!("Alcibiades {}", VERSION)
    }

    fn author(&self) -> String {
        "Evgeni Pandurski".to_string()
    }

    fn options(&self) -> Vec<(OptionName, OptionDescription)> {
        vec![
            // TODO: Calculate a sane limit for the hash size.
            ("Hash".to_string(), OptionDescription::Spin { min: 1, max: 2048, default: 16 }),
            ("Ponder".to_string(), OptionDescription::Check { default: false }),
            ("MultiPV".to_string(), OptionDescription::Spin { min: 1, max: 32, default: 1 }),
        ]
    }

    fn create(&self, hash_size_mb: Option<usize>) -> Engine {
        Engine::new(hash_size_mb.unwrap_or(16))
    }
}
<commit_msg>started implementing DeepeningSearcher<commit_after>pub mod search;

use std::thread;
use std::sync::Arc;
use std::sync::mpsc::{channel, Sender, Receiver};
use basetypes::*;
use uci::{UciEngine, UciEngineFactory, EngineReply, OptionName, OptionDescription};
use position::Position;
use chess_move::*;
use tt::TranspositionTable;

// use rand;
// use rand::distributions::{Sample, Range};
// let mut rng = rand::thread_rng();
// let mut between = Range::new(0, 10);
// let x = between.sample(&mut rng);

const VERSION: &'static str = "0.1";

struct DeepeningSearcher {
    depth: u8,
    position: Option<Position>,
    positions: Sender<Option<Position>>,
    master: thread::JoinHandle<()>,
    slave: thread::JoinHandle<()>,
}

impl DeepeningSearcher {
    fn new(tt: Arc<TranspositionTable>) -> DeepeningSearcher {
        let (positions_tx, positions_rx) = channel();
        let (commands_tx, commands_rx) = channel();
        let (reports_tx, reports_rx) = channel();
        let (results_tx, results_rx) = channel();
        DeepeningSearcher {
            depth: 0,
            position: None,
            positions: positions_tx,
            master: thread::spawn(move || {
                while let Some(position) = positions_rx.recv().unwrap() {
                    for depth in 1.. {
                        commands_tx.send(search::Command::Search(search::Parameters {
                            id: 0,
                            position: position.clone(),
                            depth: depth,
                            lower_bound: -20000,
                            upper_bound: 20000,
                        }));
                        // reports_rx.recv().unwrap()
                    }

                }
            }),
            slave: thread::spawn(move || {
                search::run(&tt, commands_rx, reports_tx, results_tx);
            }),
        }
    }

    fn start(&mut self, p: &Position) {
        if self.depth == 0 {
            self.depth += 1;
            // self.commands
            //     .send(search::Command::Search(search::Parameters {
            //         id: 0,
            //         position: p.clone(),
            //         depth: self.depth,
            //         lower_bound: -20000,
            //         upper_bound: 20000,
            //     }))
            //     .unwrap();
        }
    }

    fn stop(&mut self) {
        if self.depth > 0 {
            // self.commands.send(search::Command::Stop).unwrap();
            self.depth = 0;
        }
    }
}

/// Implements `UciEngine` trait.
pub struct Engine {
    position: Position,
    pondering_is_allowed: bool,
    multi_pv: usize,
    is_thinking: bool,
    is_pondering: bool,
    replies: Vec<EngineReply>,
    infinite: bool,
    tt: Arc<TranspositionTable>,
    commands: Sender<search::Command>,
    reports: Receiver<search::Progress>,
    results: Receiver<search::Done>,
    searcher: thread::JoinHandle<()>,
}

impl Engine {
    /// Creates a new instance.
    ///
    /// `tt_size_mb` is the preferred size of the transposition
    /// table in Mbytes.
    pub fn new(tt_size_mb: usize) -> Engine {
        let (commands_tx, commands_rx) = channel();
        let (reports_tx, reports_rx) = channel();
        let (results_tx, results_rx) = channel();
        let mut tt = TranspositionTable::new();
        tt.resize(tt_size_mb);
        let tt = Arc::new(tt);
        Engine {
            position: Position::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w QKqk - 0 \
                                          1")
                          .ok()
                          .unwrap(),
            pondering_is_allowed: false,
            multi_pv: 1,
            is_thinking: false,
            is_pondering: false,
            replies: vec![],
            infinite: false,
            tt: tt.clone(),
            commands: commands_tx,
            reports: reports_rx,
            results: results_rx,
            searcher: thread::spawn(move || {
                search::run(&tt, commands_rx, reports_tx, results_tx);
            }),
        }
    }
}

impl UciEngine for Engine {
    fn set_option(&mut self, name: &str, value: &str) {
        match name {
            // We do not support re-sizing of the transposition table
            // once the engine had started, so we do nothing.
            "Hash" => (),

            // Tells the engine that it will be allowed to ponder.
            // This option is needed because the engine might change
            // its time management algorithm when pondering is
            // allowed.
            "Ponder" => {
                self.pondering_is_allowed = value == "true";
            }

            // Tells the engine to output multiple best lines.
            // the default value is `1`.)
            "MultiPV" => {
                self.multi_pv = value.parse::<usize>().ok().unwrap_or(1);
            }

            // An invalid option.
            _ => {
                self.replies.push(EngineReply::Info(vec![("string".to_string(),
                                                          format!("Invalid option \"{}\"", name))]));
            }
        }
    }

    fn new_game(&mut self) {
        // Clearing the transposition table would not change anything,
        // so we do nothing.
    }

    fn position(&mut self, fen: &str, moves: &mut Iterator<Item = &str>) {
        if !self.is_thinking {
            if let Ok(p) = Position::from_history(fen, moves) {
                self.position = p;
            }
        }
    }

    #[allow(unused_variables)]
    fn go(&mut self,
          searchmoves: Option<Vec<String>>,
          ponder: bool,
          wtime: Option<u64>,
          btime: Option<u64>,
          winc: Option<u64>,
          binc: Option<u64>,
          movestogo: Option<u64>,
          depth: Option<u64>,
          nodes: Option<u64>,
          mate: Option<u64>,
          movetime: Option<u64>,
          infinite: bool) {
        if !self.is_thinking {
            self.commands
                .send(search::Command::Search(search::Parameters {
                    id: 0,
                    position: self.position.clone(),
                    depth: 5,
                    lower_bound: -20000,
                    upper_bound: 20000,
                }))
                .unwrap();
            self.is_thinking = true;
            self.is_pondering = ponder;
            self.infinite = infinite;
        }
    }

    fn ponder_hit(&mut self) {
        if self.is_thinking && self.is_pondering {
            self.is_pondering = false;
        }
    }

    fn stop(&mut self) {
        if self.is_thinking {
            self.commands.send(search::Command::Stop).unwrap();
            let best_move = self.get_best_move();
            self.replies.push(EngineReply::BestMove {
                best_move: best_move,
                ponder_move: None,
            });
            self.is_thinking = false;
        }
    }

    fn is_thinking(&self) -> bool {
        self.is_thinking
    }

    fn get_reply(&mut self) -> Option<EngineReply> {
        // TODO: do interactive deepening instead.
        if !self.is_pondering {
            if let Ok(_) = self.results.try_recv() {
                self.stop();
            }
        }

        self.replies.pop()
    }
}

impl Engine {
    fn get_best_move(&mut self) -> String {
        let mut m = match self.tt.probe(self.position.hash()) {
            Some(entry) => entry.move16(),
            None => 0,
        };
        if m == 0 {
            // Pick the first legal move.
            let mut first_legal_move = Move::from_u32(0);
            let mut v = Vec::with_capacity(128);
            self.position.generate_moves(&mut v);
            while let Some(x) = v.pop() {
                if self.position.do_move(x) {
                    self.position.undo_move();
                    first_legal_move = x;
                    break;
                }
            }
            m = first_legal_move.move16();
        }
        if m != 0 {
            let move_type = ((m & 0b1100000000000000) >> 14) as MoveType;
            let orig_square = ((m & 0b0011111100000000) >> 8) as Square;
            let dest_square = ((m & 0b0000000011111100) >> 2) as Square;
            let promoted_piece = match m & 0b11 {
                0 => "q",
                1 => "r",
                2 => "b",
                3 => "n",
                _ => panic!("invalid promoted piece code"),
            };
            format!("{}{}{}",
                    notation(orig_square),
                    notation(dest_square),
                    if move_type == MOVE_PROMOTION {
                        promoted_piece
                    } else {
                        ""
                    })

        } else {
            "0000".to_string()
        }
    }
}

/// Implements `UciEngineFactory` trait.
pub struct EngineFactory;

impl UciEngineFactory<Engine> for EngineFactory {
    fn name(&self) -> String {
        format!("Alcibiades {}", VERSION)
    }

    fn author(&self) -> String {
        "Evgeni Pandurski".to_string()
    }

    fn options(&self) -> Vec<(OptionName, OptionDescription)> {
        vec![
            // TODO: Calculate a sane limit for the hash size.
            ("Hash".to_string(), OptionDescription::Spin { min: 1, max: 2048, default: 16 }),
            ("Ponder".to_string(), OptionDescription::Check { default: false }),
            ("MultiPV".to_string(), OptionDescription::Spin { min: 1, max: 32, default: 1 }),
        ]
    }

    fn create(&self, hash_size_mb: Option<usize>) -> Engine {
        Engine::new(hash_size_mb.unwrap_or(16))
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::env;
use git2;
use errors::*;

pub trait Config {
  fn get(&self, name: &str) -> Result<String>;
  fn get_all(&self, glob: &str) -> Result<HashMap<String, String>>;
  fn set(&mut self, name: &str, value: &str) -> Result<()>;
}

pub struct GitConfig {
  repo: git2::Repository,
  config: git2::Config,
}

impl GitConfig {
  pub fn new() -> Result<GitConfig> {
    let path =
      env::current_dir().chain_err(|| "error getting current directory")?;
    let repo = git2::Repository::discover(path)
      .chain_err(|| "error discovering git repo")?;
    let config = repo.config().chain_err(|| "error getting git config")?;

    Ok(GitConfig {
      repo: repo,
      config: config,
    })
  }

  pub fn auto_include(&mut self, filename: &str) {
    let include_path = format!("../{}", filename);
    let file_exists = self.repo.workdir().map(|path| {
      let mut path_buf = path.to_path_buf();
      path_buf.push(&filename);
      path_buf.exists()
    });

    // Make sure .git-together exists
    if !file_exists.unwrap_or(false) {
      return;
    }

    if self.already_included(&include_path).unwrap_or(true) {
      return;
    }

    let _ = self.config.set_multivar("include.path", "^$", &include_path);
  }

  fn already_included(&self, include_path: &str) -> Result<bool> {
    let local_config = self.config
      .open_level(git2::ConfigLevel::Local)
      .chain_err(|| "error opening local git config")?;
    let entries = local_config.entries(None)
      .chain_err(|| "error getting git config entries")?;
    Ok(entries.into_iter().any(|entry| {
      entry.map(|entry| entry.value() == Some(include_path)).unwrap_or(true)
    }))
  }
}

impl Config for GitConfig {
  fn get(&self, name: &str) -> Result<String> {
    self.config
      .get_string(&name)
      .chain_err(|| format!("error getting git config for '{}'", name))
  }

  fn get_all(&self, glob: &str) -> Result<HashMap<String, String>> {
    let mut result = HashMap::new();
    let entries = self.config
      .entries(Some(glob))
      .chain_err(|| "error getting git config entries")?;
    for entry in &entries {
      let entry = entry.chain_err(|| "error getting git config entry")?;
      if let (Some(name), Some(value)) = (entry.name(), entry.value()) {
        result.insert(name.into(), value.into());
      }
    }
    Ok(result)
  }

  fn set(&mut self, name: &str, value: &str) -> Result<()> {
    self.config
      .set_str(&name, value)
      .chain_err(|| format!("error setting git config '{}': '{}'", name, value))
  }
}
<commit_msg>remove needless borrow<commit_after>use std::collections::HashMap;
use std::env;
use git2;
use errors::*;

pub trait Config {
  fn get(&self, name: &str) -> Result<String>;
  fn get_all(&self, glob: &str) -> Result<HashMap<String, String>>;
  fn set(&mut self, name: &str, value: &str) -> Result<()>;
}

pub struct GitConfig {
  repo: git2::Repository,
  config: git2::Config,
}

impl GitConfig {
  pub fn new() -> Result<GitConfig> {
    let path =
      env::current_dir().chain_err(|| "error getting current directory")?;
    let repo = git2::Repository::discover(path)
      .chain_err(|| "error discovering git repo")?;
    let config = repo.config().chain_err(|| "error getting git config")?;

    Ok(GitConfig {
      repo: repo,
      config: config,
    })
  }

  pub fn auto_include(&mut self, filename: &str) {
    let include_path = format!("../{}", filename);
    let file_exists = self.repo.workdir().map(|path| {
      let mut path_buf = path.to_path_buf();
      path_buf.push(&filename);
      path_buf.exists()
    });

    // Make sure .git-together exists
    if !file_exists.unwrap_or(false) {
      return;
    }

    if self.already_included(&include_path).unwrap_or(true) {
      return;
    }

    let _ = self.config.set_multivar("include.path", "^$", &include_path);
  }

  fn already_included(&self, include_path: &str) -> Result<bool> {
    let local_config = self.config
      .open_level(git2::ConfigLevel::Local)
      .chain_err(|| "error opening local git config")?;
    let entries = local_config.entries(None)
      .chain_err(|| "error getting git config entries")?;
    Ok(entries.into_iter().any(|entry| {
      entry.map(|entry| entry.value() == Some(include_path)).unwrap_or(true)
    }))
  }
}

impl Config for GitConfig {
  fn get(&self, name: &str) -> Result<String> {
    self.config
      .get_string(name)
      .chain_err(|| format!("error getting git config for '{}'", name))
  }

  fn get_all(&self, glob: &str) -> Result<HashMap<String, String>> {
    let mut result = HashMap::new();
    let entries = self.config
      .entries(Some(glob))
      .chain_err(|| "error getting git config entries")?;
    for entry in &entries {
      let entry = entry.chain_err(|| "error getting git config entry")?;
      if let (Some(name), Some(value)) = (entry.name(), entry.value()) {
        result.insert(name.into(), value.into());
      }
    }
    Ok(result)
  }

  fn set(&mut self, name: &str, value: &str) -> Result<()> {
    self.config
      .set_str(name, value)
      .chain_err(|| format!("error setting git config '{}': '{}'", name, value))
  }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use regex::Regex;

use server::Server;
use server::Stream;

use http::Http;
use http::Request;
use http::Response;

use self::route::Route;

mod route;

pub struct Micro {
    routes: Vec<Route>,
}

impl Micro {
    pub fn new() -> Micro {
        Micro {
            routes: Vec::new(),
        }
    }

    pub fn add<H>(&mut self, method: &str, pattern: &str, handle: H) -> &mut Route
        where H: Fn(&Request) -> Response + Send + Sync + 'static
    {
        let route = Route::new(
            method.parse().unwrap(),
            pattern.into(),
            Box::new(handle),
        );

        self.routes.push(route);
        self.routes.last_mut().unwrap()
    }

    pub fn handle(&self, stream: Stream) {
        let mut http = Http::new(stream);
        let request = http.decode();

        let mut route_found = false;

        for route in &self.routes {
            if route.method != request.method() {
                continue;
            }

            let path = {
                let path = request.path();
                let path = path.find('?').map_or(path.as_ref(), |pos| &path[..pos]);
                if path != "/" {
                    path.trim_right_matches('/').to_owned()
                } else {
                    path.to_owned()
                }
            };

            let pattern = route.compilied_pattern.clone();

            let mut params: HashMap<String, String> = HashMap::new();
            if pattern.contains("^") {
                let re = Regex::new(&pattern).unwrap();
                let caps = re.captures(&path);

                if let Some(caps) = caps {
                    route_found = true;

                    let matches = route.paths.clone();

                    for (key, value) in matches.iter() {
                        params.insert(key.to_owned(), caps.get(*value).unwrap().as_str().to_owned());
                    }
                }
            } else {
                if pattern == path {
                    route_found = true;
                }
            }

            if route_found {
                let ref handle = route.handle;
                let response = handle(&request);
                http.encode(response);
                break;
            }
        }

        if !route_found {
            http.encode(Response::from_string("404"));
        }
    }

    pub fn run(self, addr: &str) {
        let mut server = Server::new();

        server.handle(Box::new(move |stream| {
            self.handle(stream);
        }));

        server.run(addr).unwrap();
    }
}
<commit_msg>add http methods<commit_after>use std::collections::HashMap;

use regex::Regex;

use server::Server;
use server::Stream;

use http::Http;
use http::Request;
use http::Response;

use self::route::Route;

mod route;

pub struct Micro {
    routes: Vec<Route>,
}

impl Micro {
    pub fn new() -> Micro {
        Micro {
            routes: Vec::new(),
        }
    }

    pub fn add<H>(&mut self, method: &str, pattern: &str, handle: H) -> &mut Route
        where H: Fn(&Request) -> Response + Send + Sync + 'static
    {
        let route = Route::new(
            method.parse().unwrap(),
            pattern.into(),
            Box::new(handle),
        );

        self.routes.push(route);
        self.routes.last_mut().unwrap()
    }

    pub fn get<H>(&mut self, pattern: &str, handle: H) -> &mut Route
        where H: Fn(&Request) -> Response + Send + Sync + 'static
    {
        self.add("GET", pattern, handle)
    }

    pub fn post<H>(&mut self, pattern: &str, handle: H) -> &mut Route
        where H: Fn(&Request) -> Response + Send + Sync + 'static
    {
        self.add("POST", pattern, handle)
    }

    pub fn put<H>(&mut self, pattern: &str, handle: H) -> &mut Route
        where H: Fn(&Request) -> Response + Send + Sync + 'static
    {
        self.add("PUT", pattern, handle)
    }

    pub fn delete<H>(&mut self, pattern: &str, handle: H) -> &mut Route
        where H: Fn(&Request) -> Response + Send + Sync + 'static
    {
        self.add("DELETE", pattern, handle)
    }

    pub fn option<H>(&mut self, pattern: &str, handle: H) -> &mut Route
        where H: Fn(&Request) -> Response + Send + Sync + 'static
    {
        self.add("OPTION", pattern, handle)
    }

    pub fn head<H>(&mut self, pattern: &str, handle: H) -> &mut Route
        where H: Fn(&Request) -> Response + Send + Sync + 'static
    {
        self.add("HEAD", pattern, handle)
    }

    pub fn handle(&self, stream: Stream) {
        let mut http = Http::new(stream);
        let request = http.decode();

        let mut route_found = false;

        for route in &self.routes {
            if route.method != request.method() {
                continue;
            }

            let path = {
                let path = request.path();
                let path = path.find('?').map_or(path.as_ref(), |pos| &path[..pos]);
                if path != "/" {
                    path.trim_right_matches('/').to_owned()
                } else {
                    path.to_owned()
                }
            };

            let pattern = route.compilied_pattern.clone();

            let mut params: HashMap<String, String> = HashMap::new();
            if pattern.contains("^") {
                let re = Regex::new(&pattern).unwrap();
                let caps = re.captures(&path);

                if let Some(caps) = caps {
                    route_found = true;

                    let matches = route.paths.clone();

                    for (key, value) in matches.iter() {
                        params.insert(key.to_owned(), caps.get(*value).unwrap().as_str().to_owned());
                    }
                }
            } else {
                if pattern == path {
                    route_found = true;
                }
            }

            if route_found {
                let ref handle = route.handle;
                let response = handle(&request);
                http.encode(response);
                break;
            }
        }

        if !route_found {
            http.encode(Response::from_string("404"));
        }
    }

    pub fn run(self, addr: &str) {
        let mut server = Server::new();

        server.handle(Box::new(move |stream| {
            self.handle(stream);
        }));

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