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

use crate::sampler::{NativeStack, Sampler};
use crossbeam_channel::{after, unbounded, Receiver, Sender};
use ipc_channel::ipc::{IpcReceiver, IpcSender};
use ipc_channel::router::ROUTER;
use msg::constellation_msg::MonitoredComponentId;
use msg::constellation_msg::{
    BackgroundHangMonitor, BackgroundHangMonitorClone, BackgroundHangMonitorRegister,
};
use msg::constellation_msg::{HangAlert, HangAnnotation, HangMonitorAlert, SamplerControlMsg};
use std::cell::Cell;
use std::collections::{HashMap, VecDeque};
use std::thread;
use std::time::{Duration, Instant};

#[derive(Clone)]
pub struct HangMonitorRegister {
    sender: Sender<(MonitoredComponentId, MonitoredComponentMsg)>,
}

impl HangMonitorRegister {
    /// Start a new hang monitor worker, and return a handle to register components for monitoring.
    pub fn init(
        constellation_chan: IpcSender<HangMonitorAlert>,
        control_port: IpcReceiver<SamplerControlMsg>,
    ) -> Box<BackgroundHangMonitorRegister> {
        let (sender, port) = unbounded();
        let _ = thread::Builder::new().spawn(move || {
            let mut monitor =
                BackgroundHangMonitorWorker::new(constellation_chan, control_port, port);
            while monitor.run() {
                // Monitoring until all senders have been dropped...
            }
        });
        Box::new(HangMonitorRegister { sender })
    }
}

impl BackgroundHangMonitorRegister for HangMonitorRegister {
    /// Register a component for monitoring.
    /// Returns a dedicated wrapper around a sender
    /// to be used for communication with the hang monitor worker.
    fn register_component(
        &self,
        component_id: MonitoredComponentId,
        transient_hang_timeout: Duration,
        permanent_hang_timeout: Duration,
    ) -> Box<BackgroundHangMonitor> {
        let bhm_chan = BackgroundHangMonitorChan::new(self.sender.clone(), component_id);

        #[cfg(target_os = "windows")]
        let sampler = crate::sampler_windows::WindowsSampler::new();
        #[cfg(target_os = "macos")]
        let sampler = crate::sampler_mac::MacOsSampler::new();
        #[cfg(all(
            target_os = "linux",
            not(any(target_arch = "arm", target_arch = "aarch64"))
        ))]
        let sampler = crate::sampler_linux::LinuxSampler::new();
        #[cfg(any(target_os = "android", target_arch = "arm", target_arch = "aarch64"))]
        let sampler = crate::sampler::DummySampler::new();

        bhm_chan.send(MonitoredComponentMsg::Register(
            sampler,
            thread::current().name().map(str::to_owned),
            transient_hang_timeout,
            permanent_hang_timeout,
        ));
        Box::new(bhm_chan)
    }
}

impl BackgroundHangMonitorClone for HangMonitorRegister {
    fn clone_box(&self) -> Box<BackgroundHangMonitorRegister> {
        Box::new(self.clone())
    }
}

/// Messages sent from monitored components to the monitor.
pub enum MonitoredComponentMsg {
    /// Register component for monitoring,
    Register(Box<Sampler>, Option<String>, Duration, Duration),
    /// Unregister component for monitoring.
    Unregister,
    /// Notify start of new activity for a given component,
    NotifyActivity(HangAnnotation),
    /// Notify start of waiting for a new task to come-in for processing.
    NotifyWait,
}

/// A wrapper around a sender to the monitor,
/// which will send the Id of the monitored component along with each message,
/// and keep track of whether the monitor is still listening on the other end.
pub struct BackgroundHangMonitorChan {
    sender: Sender<(MonitoredComponentId, MonitoredComponentMsg)>,
    component_id: MonitoredComponentId,
    disconnected: Cell<bool>,
}

impl BackgroundHangMonitorChan {
    pub fn new(
        sender: Sender<(MonitoredComponentId, MonitoredComponentMsg)>,
        component_id: MonitoredComponentId,
    ) -> Self {
        BackgroundHangMonitorChan {
            sender,
            component_id: component_id,
            disconnected: Default::default(),
        }
    }

    pub fn send(&self, msg: MonitoredComponentMsg) {
        if self.disconnected.get() {
            return;
        }
        if let Err(_) = self.sender.send((self.component_id.clone(), msg)) {
            warn!("BackgroundHangMonitor has gone away");
            self.disconnected.set(true);
        }
    }
}

impl BackgroundHangMonitor for BackgroundHangMonitorChan {
    fn notify_activity(&self, annotation: HangAnnotation) {
        let msg = MonitoredComponentMsg::NotifyActivity(annotation);
        self.send(msg);
    }
    fn notify_wait(&self) {
        let msg = MonitoredComponentMsg::NotifyWait;
        self.send(msg);
    }
    fn unregister(&self) {
        let msg = MonitoredComponentMsg::Unregister;
        self.send(msg);
    }
}

struct MonitoredComponent {
    sampler: Box<Sampler>,
    last_activity: Instant,
    last_annotation: Option<HangAnnotation>,
    transient_hang_timeout: Duration,
    permanent_hang_timeout: Duration,
    sent_transient_alert: bool,
    sent_permanent_alert: bool,
    is_waiting: bool,
}

struct Sample(MonitoredComponentId, Instant, NativeStack);

pub struct BackgroundHangMonitorWorker {
    component_names: HashMap<MonitoredComponentId, String>,
    monitored_components: HashMap<MonitoredComponentId, MonitoredComponent>,
    constellation_chan: IpcSender<HangMonitorAlert>,
    port: Receiver<(MonitoredComponentId, MonitoredComponentMsg)>,
    control_port: Receiver<SamplerControlMsg>,
    sampling_duration: Option<Duration>,
    sampling_max_duration: Option<Duration>,
    last_sample: Instant,
    creation: Instant,
    sampling_baseline: Instant,
    samples: VecDeque<Sample>,
}

impl BackgroundHangMonitorWorker {
    pub fn new(
        constellation_chan: IpcSender<HangMonitorAlert>,
        control_port: IpcReceiver<SamplerControlMsg>,
        port: Receiver<(MonitoredComponentId, MonitoredComponentMsg)>,
    ) -> Self {
        let control_port = ROUTER.route_ipc_receiver_to_new_crossbeam_receiver(control_port);
        Self {
            component_names: Default::default(),
            monitored_components: Default::default(),
            constellation_chan,
            port,
            control_port,
            sampling_duration: None,
            sampling_max_duration: None,
            last_sample: Instant::now(),
            sampling_baseline: Instant::now(),
            creation: Instant::now(),
            samples: Default::default(),
        }
    }

    fn finish_sampled_profile(&mut self) {
        let mut bytes = vec![];
        bytes.extend(
            format!(
                "{{ \"rate\": {}, \"start\": {}, \"data\": [\n",
                self.sampling_duration.unwrap().as_millis(),
                (self.sampling_baseline - self.creation).as_millis(),
            )
            .as_bytes(),
        );

        let mut first = true;
        let to_resolve = self.samples.len();
        for (i, Sample(id, instant, stack)) in self.samples.drain(..).enumerate() {
            println!("Resolving {}/{}", i + 1, to_resolve);
            let profile = stack.to_hangprofile();
            let name = match self.component_names.get(&id) {
                Some(ref s) => format!("\"{}\"", s),
                None => format!("null"),
            };
            let json = format!(
                "{}{{ \"name\": {}, \"namespace\": {}, \"index\": {}, \"type\": \"{:?}\", \
                 \"time\": {}, \"frames\": {} }}",
                if !first { ",\n" } else { "" },
                name,
                id.0.namespace_id.0,
                id.0.index.0.get(),
                id.1,
                (instant - self.sampling_baseline).as_millis(),
                serde_json::to_string(&profile.backtrace).unwrap(),
            );
            bytes.extend(json.as_bytes());
            first = false;
        }

        bytes.extend(b"\n] }");
        let _ = self
            .constellation_chan
            .send(HangMonitorAlert::Profile(bytes));
    }

    pub fn run(&mut self) -> bool {
        let timeout = if let Some(duration) = self.sampling_duration {
            duration
                .checked_sub(Instant::now() - self.last_sample)
                .unwrap_or_else(|| Duration::from_millis(0))
        } else {
            Duration::from_millis(100)
        };
        let received = select! {
            recv(self.port) -> event => {
                match event {
                    Ok(msg) => Some(msg),
                    // Our sender has been dropped, quit.
                    Err(_) => return false,
                }
            },
            recv(self.control_port) -> event => {
                match event {
                    Ok(SamplerControlMsg::Enable(rate, max_duration)) => {
                        println!("Enabling profiler.");
                        self.sampling_duration = Some(rate);
                        self.sampling_max_duration = Some(max_duration);
                        self.sampling_baseline = Instant::now();
                        None
                    }
                    Ok(SamplerControlMsg::Disable) => {
                        println!("Disabling profiler.");
                        self.finish_sampled_profile();
                        self.sampling_duration = None;
                        None
                    }
                    Err(_) => return false,
                }
            }
            recv(after(timeout)) -> _ => None,
        };
        if let Some(msg) = received {
            self.handle_msg(msg);
            while let Ok(another_msg) = self.port.try_recv() {
                // Handle any other incoming messages,
                // before performing a hang checkpoint.
                self.handle_msg(another_msg);
            }
        }

        if let Some(duration) = self.sampling_duration {
            let now = Instant::now();
            if now - self.last_sample > duration {
                self.sample();
                self.last_sample = now;
            }
        } else {
            self.perform_a_hang_monitor_checkpoint();
        }
        true
    }

    fn handle_msg(&mut self, msg: (MonitoredComponentId, MonitoredComponentMsg)) {
        match msg {
            (
                component_id,
                MonitoredComponentMsg::Register(
                    sampler,
                    name,
                    transient_hang_timeout,
                    permanent_hang_timeout,
                ),
            ) => {
                let component = MonitoredComponent {
                    sampler,
                    last_activity: Instant::now(),
                    last_annotation: None,
                    transient_hang_timeout,
                    permanent_hang_timeout,
                    sent_transient_alert: false,
                    sent_permanent_alert: false,
                    is_waiting: true,
                };
                if let Some(name) = name {
                    self.component_names.insert(component_id.clone(), name);
                }
                assert!(
                    self.monitored_components
                        .insert(component_id, component)
                        .is_none(),
                    "This component was already registered for monitoring."
                );
            },
            (component_id, MonitoredComponentMsg::Unregister) => {
                let _ = self
                    .monitored_components
                    .remove_entry(&component_id)
                    .expect("Received Unregister for an unknown component");
            },
            (component_id, MonitoredComponentMsg::NotifyActivity(annotation)) => {
                let component = self
                    .monitored_components
                    .get_mut(&component_id)
                    .expect("Received NotifyActivity for an unknown component");
                component.last_activity = Instant::now();
                component.last_annotation = Some(annotation);
                component.sent_transient_alert = false;
                component.sent_permanent_alert = false;
                component.is_waiting = false;
            },
            (component_id, MonitoredComponentMsg::NotifyWait) => {
                let component = self
                    .monitored_components
                    .get_mut(&component_id)
                    .expect("Received NotifyWait for an unknown component");
                component.last_activity = Instant::now();
                component.sent_transient_alert = false;
                component.sent_permanent_alert = false;
                component.is_waiting = true;
            },
        }
    }

    fn perform_a_hang_monitor_checkpoint(&mut self) {
        for (component_id, monitored) in self.monitored_components.iter_mut() {
            if monitored.is_waiting {
                continue;
            }
            let last_annotation = monitored.last_annotation.unwrap();
            if monitored.last_activity.elapsed() > monitored.permanent_hang_timeout {
                if monitored.sent_permanent_alert {
                    continue;
                }
                let profile = match monitored.sampler.suspend_and_sample_thread() {
                    Ok(native_stack) => Some(native_stack.to_hangprofile()),
                    Err(()) => None,
                };
                let _ = self
                    .constellation_chan
                    .send(HangMonitorAlert::Hang(HangAlert::Permanent(
                        component_id.clone(),
                        last_annotation,
                        profile,
                    )));
                monitored.sent_permanent_alert = true;
                continue;
            }
            if monitored.last_activity.elapsed() > monitored.transient_hang_timeout {
                if monitored.sent_transient_alert {
                    continue;
                }
                let _ = self
                    .constellation_chan
                    .send(HangMonitorAlert::Hang(HangAlert::Transient(
                        component_id.clone(),
                        last_annotation,
                    )));
                monitored.sent_transient_alert = true;
            }
        }
    }

    fn sample(&mut self) {
        for (component_id, monitored) in self.monitored_components.iter_mut() {
            let instant = Instant::now();
            if let Ok(stack) = monitored.sampler.suspend_and_sample_thread() {
                if self.sampling_baseline.elapsed() >
                    self.sampling_max_duration
                        .expect("Max duration has been set")
                {
                    // Buffer is full, start discarding older samples.
                    self.samples.pop_front();
                }
                self.samples
                    .push_back(Sample(component_id.clone(), instant, stack));
            }
        }
    }
}
<commit_msg>Hide windows sampler on arm64.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use crate::sampler::{NativeStack, Sampler};
use crossbeam_channel::{after, unbounded, Receiver, Sender};
use ipc_channel::ipc::{IpcReceiver, IpcSender};
use ipc_channel::router::ROUTER;
use msg::constellation_msg::MonitoredComponentId;
use msg::constellation_msg::{
    BackgroundHangMonitor, BackgroundHangMonitorClone, BackgroundHangMonitorRegister,
};
use msg::constellation_msg::{HangAlert, HangAnnotation, HangMonitorAlert, SamplerControlMsg};
use std::cell::Cell;
use std::collections::{HashMap, VecDeque};
use std::thread;
use std::time::{Duration, Instant};

#[derive(Clone)]
pub struct HangMonitorRegister {
    sender: Sender<(MonitoredComponentId, MonitoredComponentMsg)>,
}

impl HangMonitorRegister {
    /// Start a new hang monitor worker, and return a handle to register components for monitoring.
    pub fn init(
        constellation_chan: IpcSender<HangMonitorAlert>,
        control_port: IpcReceiver<SamplerControlMsg>,
    ) -> Box<BackgroundHangMonitorRegister> {
        let (sender, port) = unbounded();
        let _ = thread::Builder::new().spawn(move || {
            let mut monitor =
                BackgroundHangMonitorWorker::new(constellation_chan, control_port, port);
            while monitor.run() {
                // Monitoring until all senders have been dropped...
            }
        });
        Box::new(HangMonitorRegister { sender })
    }
}

impl BackgroundHangMonitorRegister for HangMonitorRegister {
    /// Register a component for monitoring.
    /// Returns a dedicated wrapper around a sender
    /// to be used for communication with the hang monitor worker.
    fn register_component(
        &self,
        component_id: MonitoredComponentId,
        transient_hang_timeout: Duration,
        permanent_hang_timeout: Duration,
    ) -> Box<BackgroundHangMonitor> {
        let bhm_chan = BackgroundHangMonitorChan::new(self.sender.clone(), component_id);

        #[cfg(all(
            target_os = "windows",
            any(target_arch = "x86_64", target_arch = "x86")
        ))]
        let sampler = crate::sampler_windows::WindowsSampler::new();
        #[cfg(target_os = "macos")]
        let sampler = crate::sampler_mac::MacOsSampler::new();
        #[cfg(all(
            target_os = "linux",
            not(any(target_arch = "arm", target_arch = "aarch64"))
        ))]
        let sampler = crate::sampler_linux::LinuxSampler::new();
        #[cfg(any(target_os = "android", target_arch = "arm", target_arch = "aarch64"))]
        let sampler = crate::sampler::DummySampler::new();

        bhm_chan.send(MonitoredComponentMsg::Register(
            sampler,
            thread::current().name().map(str::to_owned),
            transient_hang_timeout,
            permanent_hang_timeout,
        ));
        Box::new(bhm_chan)
    }
}

impl BackgroundHangMonitorClone for HangMonitorRegister {
    fn clone_box(&self) -> Box<BackgroundHangMonitorRegister> {
        Box::new(self.clone())
    }
}

/// Messages sent from monitored components to the monitor.
pub enum MonitoredComponentMsg {
    /// Register component for monitoring,
    Register(Box<Sampler>, Option<String>, Duration, Duration),
    /// Unregister component for monitoring.
    Unregister,
    /// Notify start of new activity for a given component,
    NotifyActivity(HangAnnotation),
    /// Notify start of waiting for a new task to come-in for processing.
    NotifyWait,
}

/// A wrapper around a sender to the monitor,
/// which will send the Id of the monitored component along with each message,
/// and keep track of whether the monitor is still listening on the other end.
pub struct BackgroundHangMonitorChan {
    sender: Sender<(MonitoredComponentId, MonitoredComponentMsg)>,
    component_id: MonitoredComponentId,
    disconnected: Cell<bool>,
}

impl BackgroundHangMonitorChan {
    pub fn new(
        sender: Sender<(MonitoredComponentId, MonitoredComponentMsg)>,
        component_id: MonitoredComponentId,
    ) -> Self {
        BackgroundHangMonitorChan {
            sender,
            component_id: component_id,
            disconnected: Default::default(),
        }
    }

    pub fn send(&self, msg: MonitoredComponentMsg) {
        if self.disconnected.get() {
            return;
        }
        if let Err(_) = self.sender.send((self.component_id.clone(), msg)) {
            warn!("BackgroundHangMonitor has gone away");
            self.disconnected.set(true);
        }
    }
}

impl BackgroundHangMonitor for BackgroundHangMonitorChan {
    fn notify_activity(&self, annotation: HangAnnotation) {
        let msg = MonitoredComponentMsg::NotifyActivity(annotation);
        self.send(msg);
    }
    fn notify_wait(&self) {
        let msg = MonitoredComponentMsg::NotifyWait;
        self.send(msg);
    }
    fn unregister(&self) {
        let msg = MonitoredComponentMsg::Unregister;
        self.send(msg);
    }
}

struct MonitoredComponent {
    sampler: Box<Sampler>,
    last_activity: Instant,
    last_annotation: Option<HangAnnotation>,
    transient_hang_timeout: Duration,
    permanent_hang_timeout: Duration,
    sent_transient_alert: bool,
    sent_permanent_alert: bool,
    is_waiting: bool,
}

struct Sample(MonitoredComponentId, Instant, NativeStack);

pub struct BackgroundHangMonitorWorker {
    component_names: HashMap<MonitoredComponentId, String>,
    monitored_components: HashMap<MonitoredComponentId, MonitoredComponent>,
    constellation_chan: IpcSender<HangMonitorAlert>,
    port: Receiver<(MonitoredComponentId, MonitoredComponentMsg)>,
    control_port: Receiver<SamplerControlMsg>,
    sampling_duration: Option<Duration>,
    sampling_max_duration: Option<Duration>,
    last_sample: Instant,
    creation: Instant,
    sampling_baseline: Instant,
    samples: VecDeque<Sample>,
}

impl BackgroundHangMonitorWorker {
    pub fn new(
        constellation_chan: IpcSender<HangMonitorAlert>,
        control_port: IpcReceiver<SamplerControlMsg>,
        port: Receiver<(MonitoredComponentId, MonitoredComponentMsg)>,
    ) -> Self {
        let control_port = ROUTER.route_ipc_receiver_to_new_crossbeam_receiver(control_port);
        Self {
            component_names: Default::default(),
            monitored_components: Default::default(),
            constellation_chan,
            port,
            control_port,
            sampling_duration: None,
            sampling_max_duration: None,
            last_sample: Instant::now(),
            sampling_baseline: Instant::now(),
            creation: Instant::now(),
            samples: Default::default(),
        }
    }

    fn finish_sampled_profile(&mut self) {
        let mut bytes = vec![];
        bytes.extend(
            format!(
                "{{ \"rate\": {}, \"start\": {}, \"data\": [\n",
                self.sampling_duration.unwrap().as_millis(),
                (self.sampling_baseline - self.creation).as_millis(),
            )
            .as_bytes(),
        );

        let mut first = true;
        let to_resolve = self.samples.len();
        for (i, Sample(id, instant, stack)) in self.samples.drain(..).enumerate() {
            println!("Resolving {}/{}", i + 1, to_resolve);
            let profile = stack.to_hangprofile();
            let name = match self.component_names.get(&id) {
                Some(ref s) => format!("\"{}\"", s),
                None => format!("null"),
            };
            let json = format!(
                "{}{{ \"name\": {}, \"namespace\": {}, \"index\": {}, \"type\": \"{:?}\", \
                 \"time\": {}, \"frames\": {} }}",
                if !first { ",\n" } else { "" },
                name,
                id.0.namespace_id.0,
                id.0.index.0.get(),
                id.1,
                (instant - self.sampling_baseline).as_millis(),
                serde_json::to_string(&profile.backtrace).unwrap(),
            );
            bytes.extend(json.as_bytes());
            first = false;
        }

        bytes.extend(b"\n] }");
        let _ = self
            .constellation_chan
            .send(HangMonitorAlert::Profile(bytes));
    }

    pub fn run(&mut self) -> bool {
        let timeout = if let Some(duration) = self.sampling_duration {
            duration
                .checked_sub(Instant::now() - self.last_sample)
                .unwrap_or_else(|| Duration::from_millis(0))
        } else {
            Duration::from_millis(100)
        };
        let received = select! {
            recv(self.port) -> event => {
                match event {
                    Ok(msg) => Some(msg),
                    // Our sender has been dropped, quit.
                    Err(_) => return false,
                }
            },
            recv(self.control_port) -> event => {
                match event {
                    Ok(SamplerControlMsg::Enable(rate, max_duration)) => {
                        println!("Enabling profiler.");
                        self.sampling_duration = Some(rate);
                        self.sampling_max_duration = Some(max_duration);
                        self.sampling_baseline = Instant::now();
                        None
                    }
                    Ok(SamplerControlMsg::Disable) => {
                        println!("Disabling profiler.");
                        self.finish_sampled_profile();
                        self.sampling_duration = None;
                        None
                    }
                    Err(_) => return false,
                }
            }
            recv(after(timeout)) -> _ => None,
        };
        if let Some(msg) = received {
            self.handle_msg(msg);
            while let Ok(another_msg) = self.port.try_recv() {
                // Handle any other incoming messages,
                // before performing a hang checkpoint.
                self.handle_msg(another_msg);
            }
        }

        if let Some(duration) = self.sampling_duration {
            let now = Instant::now();
            if now - self.last_sample > duration {
                self.sample();
                self.last_sample = now;
            }
        } else {
            self.perform_a_hang_monitor_checkpoint();
        }
        true
    }

    fn handle_msg(&mut self, msg: (MonitoredComponentId, MonitoredComponentMsg)) {
        match msg {
            (
                component_id,
                MonitoredComponentMsg::Register(
                    sampler,
                    name,
                    transient_hang_timeout,
                    permanent_hang_timeout,
                ),
            ) => {
                let component = MonitoredComponent {
                    sampler,
                    last_activity: Instant::now(),
                    last_annotation: None,
                    transient_hang_timeout,
                    permanent_hang_timeout,
                    sent_transient_alert: false,
                    sent_permanent_alert: false,
                    is_waiting: true,
                };
                if let Some(name) = name {
                    self.component_names.insert(component_id.clone(), name);
                }
                assert!(
                    self.monitored_components
                        .insert(component_id, component)
                        .is_none(),
                    "This component was already registered for monitoring."
                );
            },
            (component_id, MonitoredComponentMsg::Unregister) => {
                let _ = self
                    .monitored_components
                    .remove_entry(&component_id)
                    .expect("Received Unregister for an unknown component");
            },
            (component_id, MonitoredComponentMsg::NotifyActivity(annotation)) => {
                let component = self
                    .monitored_components
                    .get_mut(&component_id)
                    .expect("Received NotifyActivity for an unknown component");
                component.last_activity = Instant::now();
                component.last_annotation = Some(annotation);
                component.sent_transient_alert = false;
                component.sent_permanent_alert = false;
                component.is_waiting = false;
            },
            (component_id, MonitoredComponentMsg::NotifyWait) => {
                let component = self
                    .monitored_components
                    .get_mut(&component_id)
                    .expect("Received NotifyWait for an unknown component");
                component.last_activity = Instant::now();
                component.sent_transient_alert = false;
                component.sent_permanent_alert = false;
                component.is_waiting = true;
            },
        }
    }

    fn perform_a_hang_monitor_checkpoint(&mut self) {
        for (component_id, monitored) in self.monitored_components.iter_mut() {
            if monitored.is_waiting {
                continue;
            }
            let last_annotation = monitored.last_annotation.unwrap();
            if monitored.last_activity.elapsed() > monitored.permanent_hang_timeout {
                if monitored.sent_permanent_alert {
                    continue;
                }
                let profile = match monitored.sampler.suspend_and_sample_thread() {
                    Ok(native_stack) => Some(native_stack.to_hangprofile()),
                    Err(()) => None,
                };
                let _ = self
                    .constellation_chan
                    .send(HangMonitorAlert::Hang(HangAlert::Permanent(
                        component_id.clone(),
                        last_annotation,
                        profile,
                    )));
                monitored.sent_permanent_alert = true;
                continue;
            }
            if monitored.last_activity.elapsed() > monitored.transient_hang_timeout {
                if monitored.sent_transient_alert {
                    continue;
                }
                let _ = self
                    .constellation_chan
                    .send(HangMonitorAlert::Hang(HangAlert::Transient(
                        component_id.clone(),
                        last_annotation,
                    )));
                monitored.sent_transient_alert = true;
            }
        }
    }

    fn sample(&mut self) {
        for (component_id, monitored) in self.monitored_components.iter_mut() {
            let instant = Instant::now();
            if let Ok(stack) = monitored.sampler.suspend_and_sample_thread() {
                if self.sampling_baseline.elapsed() >
                    self.sampling_max_duration
                        .expect("Max duration has been set")
                {
                    // Buffer is full, start discarding older samples.
                    self.samples.pop_front();
                }
                self.samples
                    .push_back(Sample(component_id.clone(), instant, stack));
            }
        }
    }
}
<|endoftext|>


<commit_before>//! [Church booleans](https://en.wikipedia.org/wiki/Church_encoding#Church_Booleans)

use term::*;
use term::Term::*;

/// A Church-encoded boolean `true`.
///
/// TRUE := λab.a = λ λ 2
pub fn tru() -> Term { abs(abs(Var(2))) }

/// A Church-encoded boolean `false`.
///
/// FALSE := λab.b = λ λ 1
pub fn fls() -> Term { abs(abs(Var(1))) }

/// Applied to two Church-encoded booleans it returns their Church-encoded conjunction.
///
/// AND := λpq.p q p = λ λ 2 1 2
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::booleans::{and, tru, fls};
/// use lambda_calculus::reduction::beta_full;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta_full(app!(and(), tru(), tru()), &Normal), tru());
/// assert_eq!(beta_full(app!(and(), tru(), fls()), &Normal), fls());
/// assert_eq!(beta_full(app!(and(), fls(), tru()), &Normal), fls());
/// assert_eq!(beta_full(app!(and(), fls(), fls()), &Normal), fls());
/// # }
/// ```
pub fn and() -> Term {
    abs(abs(
        app!(Var(2), Var(1), Var(2))
    ))
}

/// Applied to two Church-encoded booleans it returns their Church-encoded disjunction.
///
/// OR := λpq.p p q = λ λ 2 2 1
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::booleans::{or, tru, fls};
/// use lambda_calculus::reduction::beta_full;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta_full(app!(or(), tru(), tru()), &Normal), tru());
/// assert_eq!(beta_full(app!(or(), tru(), fls()), &Normal), tru());
/// assert_eq!(beta_full(app!(or(), fls(), tru()), &Normal), tru());
/// assert_eq!(beta_full(app!(or(), fls(), fls()), &Normal), fls());
/// # }
/// ```
pub fn or() -> Term {
    abs(abs(
        app!(Var(2), Var(2), Var(1))
    ))
}

/// Applied to a Church-encoded boolean it returns its Church-encoded negation.
///
/// NOT := λp.p FALSE TRUE = λ 1 FALSE TRUE
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::booleans::{not, tru, fls};
/// use lambda_calculus::reduction::beta_full;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta_full(app!(not(), tru()), &Normal), fls());
/// assert_eq!(beta_full(app!(not(), fls()), &Normal), tru());
/// # }
/// ```
pub fn not() -> Term {
    abs(
        app!(Var(1), fls(), tru())
    )
}

/// Applied to a Church-encoded boolean it returns its Church-encoded exclusive disjunction.
///
/// XOR := λab.a (NOT b) b = λ λ 2 (NOT 1) 1
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::booleans::{xor, tru, fls};
/// use lambda_calculus::reduction::beta_full;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta_full(app!(xor(), tru(), tru()), &Normal), fls());
/// assert_eq!(beta_full(app!(xor(), tru(), fls()), &Normal), tru());
/// assert_eq!(beta_full(app!(xor(), fls(), tru()), &Normal), tru());
/// assert_eq!(beta_full(app!(xor(), fls(), fls()), &Normal), fls());
/// # }
/// ```
pub fn xor() -> Term {
    abs(abs(
        app!(Var(2), app(not(), Var(1)), Var(1))
    ))
}

/// Applied to a Church encoded predicate and two terms it returns the first one if the predicate
/// is true or the second one if the predicate is false.
///
/// IF_ELSE := λpab.p a b = λ λ λ 3 2 1
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::booleans::{if_else, tru, fls};
/// use lambda_calculus::arithmetic::{zero, one};
/// use lambda_calculus::reduction::beta_full;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta_full(app!(if_else(), tru(), one(), zero()), &Normal), one());
/// assert_eq!(beta_full(app!(if_else(), fls(), one(), zero()), &Normal), zero());
/// # }
/// ```
pub fn if_else() -> Term {
    abs(abs(abs(
        app!(Var(3), Var(2), Var(1))
    )))
}

impl From<bool> for Term {
    fn from(b: bool) -> Self {
        if b { tru() } else { fls() }
    }
}
<commit_msg>migrate booleans to the new beta<commit_after>//! [Church booleans](https://en.wikipedia.org/wiki/Church_encoding#Church_Booleans)

use term::*;
use term::Term::*;

/// A Church-encoded boolean `true`.
///
/// TRUE := λab.a = λ λ 2
pub fn tru() -> Term { abs(abs(Var(2))) }

/// A Church-encoded boolean `false`.
///
/// FALSE := λab.b = λ λ 1
pub fn fls() -> Term { abs(abs(Var(1))) }

/// Applied to two Church-encoded booleans it returns their Church-encoded conjunction.
///
/// AND := λpq.p q p = λ λ 2 1 2
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::booleans::{and, tru, fls};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta(app!(and(), tru(), tru()), &Normal, None), tru());
/// assert_eq!(beta(app!(and(), tru(), fls()), &Normal, None), fls());
/// assert_eq!(beta(app!(and(), fls(), tru()), &Normal, None), fls());
/// assert_eq!(beta(app!(and(), fls(), fls()), &Normal, None), fls());
/// # }
/// ```
pub fn and() -> Term {
    abs(abs(
        app!(Var(2), Var(1), Var(2))
    ))
}

/// Applied to two Church-encoded booleans it returns their Church-encoded disjunction.
///
/// OR := λpq.p p q = λ λ 2 2 1
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::booleans::{or, tru, fls};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta(app!(or(), tru(), tru()), &Normal, None), tru());
/// assert_eq!(beta(app!(or(), tru(), fls()), &Normal, None), tru());
/// assert_eq!(beta(app!(or(), fls(), tru()), &Normal, None), tru());
/// assert_eq!(beta(app!(or(), fls(), fls()), &Normal, None), fls());
/// # }
/// ```
pub fn or() -> Term {
    abs(abs(
        app!(Var(2), Var(2), Var(1))
    ))
}

/// Applied to a Church-encoded boolean it returns its Church-encoded negation.
///
/// NOT := λp.p FALSE TRUE = λ 1 FALSE TRUE
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::booleans::{not, tru, fls};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta(app!(not(), tru()), &Normal, None), fls());
/// assert_eq!(beta(app!(not(), fls()), &Normal, None), tru());
/// # }
/// ```
pub fn not() -> Term {
    abs(
        app!(Var(1), fls(), tru())
    )
}

/// Applied to a Church-encoded boolean it returns its Church-encoded exclusive disjunction.
///
/// XOR := λab.a (NOT b) b = λ λ 2 (NOT 1) 1
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::booleans::{xor, tru, fls};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta(app!(xor(), tru(), tru()), &Normal, None), fls());
/// assert_eq!(beta(app!(xor(), tru(), fls()), &Normal, None), tru());
/// assert_eq!(beta(app!(xor(), fls(), tru()), &Normal, None), tru());
/// assert_eq!(beta(app!(xor(), fls(), fls()), &Normal, None), fls());
/// # }
/// ```
pub fn xor() -> Term {
    abs(abs(
        app!(Var(2), app(not(), Var(1)), Var(1))
    ))
}

/// Applied to a Church encoded predicate and two terms it returns the first one if the predicate
/// is true or the second one if the predicate is false.
///
/// IF_ELSE := λpab.p a b = λ λ λ 3 2 1
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::booleans::{if_else, tru, fls};
/// use lambda_calculus::arithmetic::{zero, one};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta(app!(if_else(), tru(), one(), zero()), &Normal, None), one());
/// assert_eq!(beta(app!(if_else(), fls(), one(), zero()), &Normal, None), zero());
/// # }
/// ```
pub fn if_else() -> Term {
    abs(abs(abs(
        app!(Var(3), Var(2), Var(1))
    )))
}

impl From<bool> for Term {
    fn from(b: bool) -> Self {
        if b { tru() } else { fls() }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use aggregate::AggregateCall;
use answer::Answer;
use expr::Expr;
use query::Query;
use row::Row;

struct Executor {
    query: Query,
    aggregate_calls: Vec<AggregateCall>,
    non_aggregates: Vec<Expr>,
}

impl Executor {
    fn new(query: Query) -> Self {
        let mut aggregates = Vec::new();
        let mut non_aggregates = Vec::new();

        for expr in query.select.iter() {
            if let Some(call) = expr.get_aggregate_call() {
                aggregates.push(call);
            } else {
                non_aggregates.push(expr.clone());
            }
        }

        Executor {
            query: query,
            aggregate_calls: aggregates,
            non_aggregates: non_aggregates,
        }
    }

    fn execute(&self, source: Box<Iterator<Item=Row>>) -> Answer {
        if self.aggregate_calls.is_empty() {
            self.execute_non_aggregate(source)
        } else {
            self.execute_aggregate(source)
        }
    }

    fn execute_non_aggregate(&self, source: Box<Iterator<Item=Row>>) -> Answer {
        let mut rows = Vec::new();
        for input_row in source {
            let mut row = Vec::new();
            for field in self.non_aggregates.iter() {
                row.push(field.eval(&input_row));
            }
            rows.push(row);
        }

        Answer {
            columns: self.get_columns(),
            rows: rows,
        }
    }

    fn execute_aggregate(&self, source: Box<Iterator<Item=Row>>) -> Answer {
        let mut aggregates = HashMap::new();
        for call in self.aggregate_calls.iter() {
            aggregates.insert(call.clone(), call.function.aggregate());
        }

        for row in source {
            for (call, aggregate) in aggregates.iter_mut() {
                aggregate.apply(call.argument.eval(&row));
            }
        }

        let mut aggregate_row = Row::new();
        for (call, aggregate) in aggregates {
            aggregate_row.fields.insert(Expr::AggregateCall(call), aggregate.final_value());
        }

        let mut output_row = Vec::new();
        for field in self.query.select.iter() {
            output_row.push(field.eval(&aggregate_row));
        }

        Answer {
            columns: self.get_columns(),
            rows: vec![output_row],
        }
    }

    fn get_columns(&self) -> Vec<String> {
        let mut columns = Vec::new();
        for field in self.query.select.iter() {
            columns.push(format!("{}", field));
        }
        columns
    }
}

pub fn execute(query: Query, source: Box<Iterator<Item=Row>>) -> Answer {
    Executor::new(query).execute(source)
}

#[cfg(test)]
mod tests {
    use super::*;
    use aggregate::{AggregateCall, AggregateFunction};
    use data::Data;
    use expr::Expr;
    use row::make_rows;

    #[test]
    fn aggregate_query() {
        let source = make_rows(vec!["a"], vec![
            vec![Data::Int(1)],
            vec![Data::Int(2)],
            vec![Data::Int(3)],
            vec![Data::Int(4)],
            vec![Data::Int(5)],
        ]);

        let call = AggregateCall{
            function: AggregateFunction::Sum,
            argument: Box::new(Expr::Column(String::from("a"))),
        };

        let query = Query {
            select: vec![Expr::AggregateCall(call)],
            from: String::new(),
        };

        let actual = execute(query, Box::new(source.into_iter()));
        let expected = Answer {
            columns: vec![String::from("sum(a)")],
            rows: vec![vec![Data::Int(15)]],
        };

        assert_eq!(expected, actual);
    }

    #[test]
    fn non_aggregate_query() {
        let source = make_rows(vec!["a"], vec![
            vec![Data::Int(1)],
            vec![Data::Int(2)],
            vec![Data::Int(3)],
            vec![Data::Int(4)],
            vec![Data::Int(5)],
        ]);

        let query = Query {
            select: vec![Expr::Column(String::from("a"))],
            from: String::new(),
        };

        let actual = execute(query, Box::new(source.clone().into_iter()));
        let expected = Answer {
            columns: vec![String::from("a")],
            rows: vec![
                vec![Data::Int(1)],
                vec![Data::Int(2)],
                vec![Data::Int(3)],
                vec![Data::Int(4)],
                vec![Data::Int(5)],
            ],
        };

        assert_eq!(expected, actual);
    }
}
<commit_msg>Remove unnecessary field<commit_after>use std::collections::HashMap;
use aggregate::AggregateCall;
use answer::Answer;
use expr::Expr;
use query::Query;
use row::Row;

struct Executor {
    query: Query,
    aggregate_calls: Vec<AggregateCall>,
}

impl Executor {
    fn new(query: Query) -> Self {
        let mut aggregates = Vec::new();

        for expr in query.select.iter() {
            if let Some(call) = expr.get_aggregate_call() {
                aggregates.push(call);
            }
        }

        Executor {
            query: query,
            aggregate_calls: aggregates,
        }
    }

    fn execute(&self, source: Box<Iterator<Item=Row>>) -> Answer {
        if self.aggregate_calls.is_empty() {
            self.execute_non_aggregate(source)
        } else {
            self.execute_aggregate(source)
        }
    }

    fn execute_non_aggregate(&self, source: Box<Iterator<Item=Row>>) -> Answer {
        let mut rows = Vec::new();
        for input_row in source {
            let mut row = Vec::new();
            for field in self.query.select.iter() {
                row.push(field.eval(&input_row));
            }
            rows.push(row);
        }

        Answer {
            columns: self.get_columns(),
            rows: rows,
        }
    }

    fn execute_aggregate(&self, source: Box<Iterator<Item=Row>>) -> Answer {
        let mut aggregates = HashMap::new();
        for call in self.aggregate_calls.iter() {
            aggregates.insert(call.clone(), call.function.aggregate());
        }

        for row in source {
            for (call, aggregate) in aggregates.iter_mut() {
                aggregate.apply(call.argument.eval(&row));
            }
        }

        let mut aggregate_row = Row::new();
        for (call, aggregate) in aggregates {
            aggregate_row.fields.insert(Expr::AggregateCall(call), aggregate.final_value());
        }

        let mut output_row = Vec::new();
        for field in self.query.select.iter() {
            output_row.push(field.eval(&aggregate_row));
        }

        Answer {
            columns: self.get_columns(),
            rows: vec![output_row],
        }
    }

    fn get_columns(&self) -> Vec<String> {
        let mut columns = Vec::new();
        for field in self.query.select.iter() {
            columns.push(format!("{}", field));
        }
        columns
    }
}

pub fn execute(query: Query, source: Box<Iterator<Item=Row>>) -> Answer {
    Executor::new(query).execute(source)
}

#[cfg(test)]
mod tests {
    use super::*;
    use aggregate::{AggregateCall, AggregateFunction};
    use data::Data;
    use expr::Expr;
    use row::make_rows;

    #[test]
    fn aggregate_query() {
        let source = make_rows(vec!["a"], vec![
            vec![Data::Int(1)],
            vec![Data::Int(2)],
            vec![Data::Int(3)],
            vec![Data::Int(4)],
            vec![Data::Int(5)],
        ]);

        let call = AggregateCall{
            function: AggregateFunction::Sum,
            argument: Box::new(Expr::Column(String::from("a"))),
        };

        let query = Query {
            select: vec![Expr::AggregateCall(call)],
            from: String::new(),
        };

        let actual = execute(query, Box::new(source.into_iter()));
        let expected = Answer {
            columns: vec![String::from("sum(a)")],
            rows: vec![vec![Data::Int(15)]],
        };

        assert_eq!(expected, actual);
    }

    #[test]
    fn non_aggregate_query() {
        let source = make_rows(vec!["a"], vec![
            vec![Data::Int(1)],
            vec![Data::Int(2)],
            vec![Data::Int(3)],
            vec![Data::Int(4)],
            vec![Data::Int(5)],
        ]);

        let query = Query {
            select: vec![Expr::Column(String::from("a"))],
            from: String::new(),
        };

        let actual = execute(query, Box::new(source.clone().into_iter()));
        let expected = Answer {
            columns: vec![String::from("a")],
            rows: vec![
                vec![Data::Int(1)],
                vec![Data::Int(2)],
                vec![Data::Int(3)],
                vec![Data::Int(4)],
                vec![Data::Int(5)],
            ],
        };

        assert_eq!(expected, actual);
    }
}
<|endoftext|>


<commit_before>use ::screen;
use ::screen::Screen;

use piston_window;

pub struct Game {
    window: piston_window::PistonWindow,
    screens: Vec<Box<screen::Screen>>,
}

impl Game {
    pub fn new() -> Game {
        let window: piston_window::PistonWindow = piston_window::WindowSettings::new("rrthozopsi", [600, 600]).exit_on_esc(true).build().unwrap();
        let screens: Vec<Box<screen::Screen>> = vec![Box::new(screen::MainMenuScreen::new())];
        Game {
            window: window,
            screens: screens,
        }
    }

    pub fn run(&mut self) {
        use piston_window::Event;

	// ???
	// TODO: Use drop to unborrow?
        //let mut screen = self.screens.last_mut().unwrap();

        // TODO: Remove clone?
        for window in &mut self.window {
            match window.event {
                Some(Event::Update(args)) => { self.screens.last_mut().unwrap().on_update(&args); }
                Some(Event::Render(args)) => { self.screens.last_mut().unwrap().on_draw(&args, &window); }
                Some(Event::Input(ref input)) => {
            	    for action in self.screens.last_mut().unwrap().on_input(&input, &window) {
            		match action {
            		    screen::InputResult::PushScreen(_) => {}
            		    screen::InputResult::PopScreen => {
            			self.screens.pop();
            		    }
            		}
            	    }
            	    //let result = screen.on_input(&input, &window);
            	}
                _ => {}
            }
        }
    }
}
<commit_msg>PushScreen handling<commit_after>use ::screen;
use ::screen::Screen;

use piston_window;

pub struct Game {
    window: piston_window::PistonWindow,
    screens: Vec<Box<screen::Screen>>,
}

impl Game {
    pub fn new() -> Game {
        let window: piston_window::PistonWindow = piston_window::WindowSettings::new("rrthozopsi", [600, 600]).exit_on_esc(true).build().unwrap();
        let screens: Vec<Box<screen::Screen>> = vec![Box::new(screen::MainMenuScreen::new())];
        Game {
            window: window,
            screens: screens,
        }
    }

    pub fn run(&mut self) {
        use piston_window::Event;

	// ???
	// TODO: Use drop to unborrow?
        //let mut screen = self.screens.last_mut().unwrap();

        // TODO: Remove clone?
        for window in &mut self.window {
            match window.event {
                Some(Event::Update(args)) => { self.screens.last_mut().unwrap().on_update(&args); }
                Some(Event::Render(args)) => { self.screens.last_mut().unwrap().on_draw(&args, &window); }
                Some(Event::Input(ref input)) => {
            	    for action in self.screens.last_mut().unwrap().on_input(&input, &window) {
            		match action {
            		    screen::InputResult::PushScreen(new_screen) => {
            			self.screens.push(new_screen);
            		    }
            		    screen::InputResult::PopScreen => {
            			self.screens.pop();
            		    }
            		}
            	    }
            	    //let result = screen.on_input(&input, &window);
            	}
                _ => {}
            }
        }
    }
}
<|endoftext|>


<commit_before>
use ndarray::*;
use std::ops::*;
use rand::*;

use super::layout::*;
use super::types::*;
use super::error::*;

pub fn conjugate(a: &ArrayBase<Si, Ix2>) -> ArrayBase<So, Ix2>
    where A: Conjugate,
          Si: Data<Elem = A>,
          So: DataOwned<Elem = A> + DataMut
{
    let mut a = replicate(&a.t());
    for val in a.iter_mut() {
        *val = Conjugate::conj(*val);
    }
    a
}

/// Random square matrix
pub fn random_square(n: usize) -> ArrayBase<S, Ix2>
    where A: RandNormal,
          S: DataOwned<Elem = A>
{
    let mut rng = thread_rng();
    let v: Vec = (0..n * n).map(|_| A::randn(&mut rng)).collect();
    ArrayBase::from_shape_vec((n, n), v).unwrap()
}

/// Random Hermite matrix
pub fn random_hermite(n: usize) -> ArrayBase<S, Ix2>
    where A: RandNormal + Conjugate + Add<Output = A>,
          S: DataOwned<Elem = A> + DataMut
{
    let mut a = random_square(n);
    for i in 0..n {
        a[(i, i)] = a[(i, i)] + Conjugate::conj(a[(i, i)]);
        for j in (i + 1)..n {
            a[(i, j)] = Conjugate::conj(a[(j, i)])
        }
    }
    a
}

/// Random Hermite Positive-definite matrix
pub fn random_hpd(n: usize) -> ArrayBase<S, Ix2>
    where A: RandNormal + Conjugate + LinalgScalar,
          S: DataOwned<Elem = A> + DataMut
{
    let a: Array2 = random_square(n);
    let ah: Array2 = conjugate(&a);
    replicate(&ah.dot(&a))
}

/// construct matrix from diag
pub fn from_diag(d: &[A]) -> Array2
    where A: LinalgScalar
{
    let n = d.len();
    let mut e = Array::zeros((n, n));
    for i in 0..n {
        e[(i, i)] = d[i];
    }
    e
}

/// stack vectors into matrix horizontally
pub fn hstack(xs: &[ArrayBase<S, Ix1>]) -> Result<Array>
    where A: LinalgScalar,
          S: Data<Elem = A>
{
    let views: Vec<_> = xs.iter()
        .map(|x| {
            let n = x.len();
            x.view().into_shape((n, 1)).unwrap()
        })
        .collect();
    stack(Axis(1), &views).map_err(|e| e.into())
}

/// stack vectors into matrix vertically
pub fn vstack(xs: &[ArrayBase<S, Ix1>]) -> Result<Array>
    where A: LinalgScalar,
          S: Data<Elem = A>
{
    let views: Vec<_> = xs.iter()
        .map(|x| {
            let n = x.len();
            x.view().into_shape((1, n)).unwrap()
        })
        .collect();
    stack(Axis(0), &views).map_err(|e| e.into())
}
<commit_msg>Add generate::random(n, m)<commit_after>
use ndarray::*;
use std::ops::*;
use rand::*;

use super::layout::*;
use super::types::*;
use super::error::*;

pub fn conjugate(a: &ArrayBase<Si, Ix2>) -> ArrayBase<So, Ix2>
    where A: Conjugate,
          Si: Data<Elem = A>,
          So: DataOwned<Elem = A> + DataMut
{
    let mut a = replicate(&a.t());
    for val in a.iter_mut() {
        *val = Conjugate::conj(*val);
    }
    a
}

/// Random matrix
pub fn random(n: usize, m: usize) -> ArrayBase<S, Ix2>
    where A: RandNormal,
          S: DataOwned<Elem = A>
{
    let mut rng = thread_rng();
    let v: Vec = (0..n * m).map(|_| A::randn(&mut rng)).collect();
    ArrayBase::from_shape_vec((n, m), v).unwrap()
}

/// Random square matrix
pub fn random_square(n: usize) -> ArrayBase<S, Ix2>
    where A: RandNormal,
          S: DataOwned<Elem = A>
{
    random(n, n)
}

/// Random Hermite matrix
pub fn random_hermite(n: usize) -> ArrayBase<S, Ix2>
    where A: RandNormal + Conjugate + Add<Output = A>,
          S: DataOwned<Elem = A> + DataMut
{
    let mut a = random_square(n);
    for i in 0..n {
        a[(i, i)] = a[(i, i)] + Conjugate::conj(a[(i, i)]);
        for j in (i + 1)..n {
            a[(i, j)] = Conjugate::conj(a[(j, i)])
        }
    }
    a
}

/// Random Hermite Positive-definite matrix
pub fn random_hpd(n: usize) -> ArrayBase<S, Ix2>
    where A: RandNormal + Conjugate + LinalgScalar,
          S: DataOwned<Elem = A> + DataMut
{
    let a: Array2 = random_square(n);
    let ah: Array2 = conjugate(&a);
    replicate(&ah.dot(&a))
}

/// construct matrix from diag
pub fn from_diag(d: &[A]) -> Array2
    where A: LinalgScalar
{
    let n = d.len();
    let mut e = Array::zeros((n, n));
    for i in 0..n {
        e[(i, i)] = d[i];
    }
    e
}

/// stack vectors into matrix horizontally
pub fn hstack(xs: &[ArrayBase<S, Ix1>]) -> Result<Array>
    where A: LinalgScalar,
          S: Data<Elem = A>
{
    let views: Vec<_> = xs.iter()
        .map(|x| {
            let n = x.len();
            x.view().into_shape((n, 1)).unwrap()
        })
        .collect();
    stack(Axis(1), &views).map_err(|e| e.into())
}

/// stack vectors into matrix vertically
pub fn vstack(xs: &[ArrayBase<S, Ix1>]) -> Result<Array>
    where A: LinalgScalar,
          S: Data<Elem = A>
{
    let views: Vec<_> = xs.iter()
        .map(|x| {
            let n = x.len();
            x.view().into_shape((1, n)).unwrap()
        })
        .collect();
    stack(Axis(0), &views).map_err(|e| e.into())
}
<|endoftext|>


<commit_before>extern crate cursive;

use cursive::Cursive;
use cursive::view::{IdView,TextView,Dialog,Selector,KeyEventView};

fn show_popup(siv: &mut Cursive) {

    siv.add_layer(Dialog::new(TextView::new("Tak!"))
                  .button("Change", |s| {
                      // Look for a view tagged "text". We _know_ it's there, so unwrap it.
                      let view = s.find::<TextView>(&Selector::Id("text")).unwrap();
                      let content: String = view.get_content().chars().rev().collect();
                      view.set_content(&content);
                  })
                  .dismiss_button("Ok"));

}

fn main() {
    let mut siv = Cursive::new();

    let content = "Press Q to quit the application.\n\nPress P to bring back the popup.";

    siv.add_global_callback('q' as i32, |s| s.quit());

    // Let's wrap the view to give it a recognizable ID, so we can look for it.
    // We add the P callback on the textview only (and not globally),
    // so that we can't call it when the popup is already visible.
    siv.add_layer(KeyEventView::new(IdView::new("text", TextView::new(content)))
                  .register('p' as i32, |s| show_popup(s)));

    show_popup(&mut siv);

    siv.run();
}
<commit_msg>Update mutation example<commit_after>extern crate cursive;

use cursive::Cursive;
use cursive::view::{IdView,TextView,Dialog,Selector,KeyEventView};

fn show_popup(siv: &mut Cursive) {

    siv.add_layer(Dialog::new(TextView::new("Tak!"))
                  .button("Change", |s| {
                      // Look for a view tagged "text". We _know_ it's there, so unwrap it.
                      let view = s.find::<TextView>(&Selector::Id("text")).unwrap();
                      let content: String = view.get_content().chars().rev().collect();
                      view.set_content(&content);
                  })
                  .dismiss_button("Ok"));

}

fn main() {
    let mut siv = Cursive::new();

    let content = "Press Q to quit the application.\n\nPress P to open the popup.";

    siv.add_global_callback('q' as i32, |s| s.quit());

    // Let's wrap the view to give it a recognizable ID, so we can look for it.
    // We add the P callback on the textview only (and not globally),
    // so that we can't call it when the popup is already visible.
    siv.add_layer(KeyEventView::new(IdView::new("text", TextView::new(content)))
                  .register('p' as i32, |s| show_popup(s)));

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


<commit_before>// Copyright (C) 2015 Élisabeth HENRY.
//
// This file is part of Caribon.
//
// Caribon is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Caribon is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Caribon.  If not, see <http://www.gnu.org/licenses/>.

/// `Word` type: some inner representation used by `Parser`.
///
/// You probably should not use this type directly.
#[derive(Debug,Clone)]
pub enum Word {
    /// A String which is not part of the text (typically whitespace, HTML formatting, ...)
    Untracked(String),
    /// A word that is ignored, either because it is in `parser.ignored` or because it is
    /// a proper noun and `ignore_proper` has been set to `true`.
    Ignored(String),
    /// Tracked string, containing the string, the stemmed variant of the
    /// string, some value corresponding to the degree of repetitions and
    /// an option to a highlighting colour
    Tracked(String, String, f32, Option<&'static str>),
}

impl Word {
    /// Sets the stemmed value of a word.
    pub fn set_stemmed(&mut self, s:String) {
        match self {
            &mut Word::Tracked(_, ref mut stemmed, _, _) => {
                *stemmed = s;
            },
            _ => {}
        }
    }

    /// Sets the repetition value of a word.
    pub fn set_count(&mut self, x: f32)  {
        match self {
            &mut Word::Tracked(_, _, ref mut v, _) => {
                *v = x;
            },
            _ => {}
        }
    }
}

#[derive(Debug,Clone)]
/// The internal representation of the document.
///
/// Technically the name AST is not really well chosen, since it is not a tree, but mainly a vector of
/// `Word`s plus some additonal informations for HTML parsing, but the idea is that it is the internal
/// representation of the documentation.
pub struct Ast {
    /// Vector of `Word`s. The main data of the structure.
    pub words: Vec<Word>,
    /// Position of <head> tag, if any
    pub begin_head: Option<usize>,
    /// position of <body> tag, if any
    pub begin_body: Option<usize>,
    /// position of </body> tag, if any
    pub end_body: Option<usize>,
}

impl Ast {
    /// Creates a new, empty AST
    pub fn new() -> Ast {
        Ast {
            words: vec!(),
            begin_head: None,
            begin_body: None,
            end_body: None
        }
    }

    /// Sets begin_head to current last position of words
    ///
    /// This should be called *before* inserting the corresponding element.
    pub fn mark_begin_head(&mut self) {
        if self.begin_head.is_some() {
            return;
        }

        let i = self.words.len();
        self.begin_head = Some(i);
    }

    /// Sets begin_body to current last position of words
    ///
    /// This should be called *before* inserting the corresponding element.
    pub fn mark_begin_body(&mut self)  {
        if self.begin_body.is_some() {
            return;
        }

        let i = self.words.len();
        self.begin_body = Some(i);
    }

    /// Sets end_body to current last position of words
    ///
    /// This should be called *before* inserting the corresponding element.
    pub fn mark_end_body(&mut self) {
        let i = self.words.len();
        self.end_body = Some(i);
    }

    /// Get only the words contained between <body> and </body>
    ///
    /// If body_begin and body_end are both set (and the first one is before the second),
    /// returns a slice that contains only words in this part; else, returns all words.
    pub fn get_body_mut(&mut self) -> &mut [Word] {
        if let Some(begin) = self.begin_body {
            if let Some(end) = self.end_body {
                if begin < end {
                    return &mut self.words[begin + 1..end];
                }
            }
        }
        return &mut self.words;
    }

    pub fn get_body(&self) -> &[Word] {
        if let Some(begin) = self.begin_body {
            if let Some(end) = self.end_body {
                if begin < end {
                    return &self.words[begin + 1..end];
                }
            }
        }
        return &self.words;
    }
}
<commit_msg>updated comment of ast::get_body(_mut)<commit_after>// Copyright (C) 2015 Élisabeth HENRY.
//
// This file is part of Caribon.
//
// Caribon is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Caribon is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Caribon.  If not, see <http://www.gnu.org/licenses/>.

/// `Word` type: some inner representation used by `Parser`.
///
/// You probably should not use this type directly.
#[derive(Debug,Clone)]
pub enum Word {
    /// A String which is not part of the text (typically whitespace, HTML formatting, ...)
    Untracked(String),
    /// A word that is ignored, either because it is in `parser.ignored` or because it is
    /// a proper noun and `ignore_proper` has been set to `true`.
    Ignored(String),
    /// Tracked string, containing the string, the stemmed variant of the
    /// string, some value corresponding to the degree of repetitions and
    /// an option to a highlighting colour
    Tracked(String, String, f32, Option<&'static str>),
}

impl Word {
    /// Sets the stemmed value of a word.
    pub fn set_stemmed(&mut self, s:String) {
        match self {
            &mut Word::Tracked(_, ref mut stemmed, _, _) => {
                *stemmed = s;
            },
            _ => {}
        }
    }

    /// Sets the repetition value of a word.
    pub fn set_count(&mut self, x: f32)  {
        match self {
            &mut Word::Tracked(_, _, ref mut v, _) => {
                *v = x;
            },
            _ => {}
        }
    }
}

#[derive(Debug,Clone)]
/// The internal representation of the document.
///
/// Technically the name AST is not really well chosen, since it is not a tree, but mainly a vector of
/// `Word`s plus some additonal informations for HTML parsing, but the idea is that it is the internal
/// representation of the documentation.
pub struct Ast {
    /// Vector of `Word`s. The main data of the structure.
    pub words: Vec<Word>,
    /// Position of <head> tag, if any
    pub begin_head: Option<usize>,
    /// position of <body> tag, if any
    pub begin_body: Option<usize>,
    /// position of </body> tag, if any
    pub end_body: Option<usize>,
}

impl Ast {
    /// Creates a new, empty AST
    pub fn new() -> Ast {
        Ast {
            words: vec!(),
            begin_head: None,
            begin_body: None,
            end_body: None
        }
    }

    /// Sets begin_head to current last position of words
    ///
    /// This should be called *before* inserting the corresponding element.
    pub fn mark_begin_head(&mut self) {
        if self.begin_head.is_some() {
            return;
        }

        let i = self.words.len();
        self.begin_head = Some(i);
    }

    /// Sets begin_body to current last position of words
    ///
    /// This should be called *before* inserting the corresponding element.
    pub fn mark_begin_body(&mut self)  {
        if self.begin_body.is_some() {
            return;
        }

        let i = self.words.len();
        self.begin_body = Some(i);
    }

    /// Sets end_body to current last position of words
    ///
    /// This should be called *before* inserting the corresponding element.
    pub fn mark_end_body(&mut self) {
        let i = self.words.len();
        self.end_body = Some(i);
    }

    /// Get only the words contained between <body> and </body>
    ///
    /// If body_begin and body_end are both set (and the first one is before the second),
    /// returns a slice that contains only words in this part; else, returns all words.
    pub fn get_body(&self) -> &[Word] {
        if let Some(begin) = self.begin_body {
            if let Some(end) = self.end_body {
                if begin < end {
                    return &self.words[begin + 1..end];
                }
            }
        }
        return &self.words;
    }

    /// Get only the words contained between <body> and </body>, mutable version
    ///
    /// Same as get_body, but takes and return a mutable reference.
    pub fn get_body_mut(&mut self) -> &mut [Word] {
        if let Some(begin) = self.begin_body {
            if let Some(end) = self.end_body {
                if begin < end {
                    return &mut self.words[begin + 1..end];
                }
            }
        }
        return &mut self.words;
    }
}
<|endoftext|>


<commit_before>use std::collections::{HashSet, HashMap};
use std::io::{BufReader, BufRead};
use std::str::FromStr;
use std::fs::File;
use std::cmp;
use rand::Rng;
use tar::Archive;
use spiral::Spiral;
use dfa::{Dfa, DfaState};
use player::Player;
use cell::Cell;
use field::{Pos, Field};

const PATTERNS_STR: &'static str = "patterns";

#[derive(Clone, Debug)]
struct Move {
  x: u32,
  y: u32,
  p: f64 // probability
}

struct Pattern {
  p: f64, // priority
  width: u32,
  height: u32,
  moves: Vec<Move>
}

pub struct Patterns {
  min_size: u32,
  dfa: Dfa,
  patterns: Vec<Pattern>
}

impl Patterns {
  pub fn empty() -> Patterns {
    Patterns {
      min_size: u32::max_value(),
      dfa: Dfa::empty(),
      patterns: Vec::with_capacity(0)
    }
  }

  fn read_header<T: BufRead>(input: &mut T, s: &mut String) -> (u32, u32, u32, f64) {
    s.clear();
    input.read_line(s).ok();
    s.pop();
    let mut split = s.split(' ').fuse();
    let width = u32::from_str(split.next().expect("Invalid pattern format: expected width.")).expect("Invalid pattern format: width must be u32.");
    let height = u32::from_str(split.next().expect("Invalid pattern format: expected height.")).expect("Invalid pattern format: height must be u32.");
    let moves_count = u32::from_str(split.next().expect("Invalid pattern format: expected moves count.")).expect("Invalid pattern format: moves count must be u32.");
    let priority = f64::from_str(split.next().expect("Invalid pattern format: expected priority.")).expect("Invalid pattern format: priority must be f64.");
    (width, height, moves_count, priority)
  }

  fn read_pattern<T: BufRead>(input: &mut T, s: &mut String, width: u32, height: u32) {
    s.clear();
    for _ in 0 .. height {
      let last_len = s.len();
      input.read_line(s).ok();
      s.pop();
      assert_eq!((s.len() - last_len) as u32, width)
    }
  }

  fn read_moves<T: BufRead>(input: &mut T, s: &mut String, moves_count: u32) -> Vec<Move> {
    let mut moves = Vec::with_capacity(moves_count as usize);
    let mut priorities_sum = 0f64;
    for _ in 0 .. moves_count {
      s.clear();
      input.read_line(s).ok();
      s.pop();
      let mut split = s.split(' ').fuse();
      let x = u32::from_str(split.next().expect("Invalid pattern format: expected x coordinate.")).expect("Invalid pattern format: x coordinate must be u32.");
      let y = u32::from_str(split.next().expect("Invalid pattern format: expected x coordinate.")).expect("Invalid pattern format: x coordinate must be u32.");
      let p = f64::from_str(split.next().expect("Invalid pattern format: expected probability.")).expect("Invalid pattern format: probability must be f64.");
      priorities_sum += p;
      moves.push(Move {
        x: x,
        y: y,
        p: p
      });
    }
    for m in &mut moves {
      m.p /= priorities_sum;
    }
    moves
  }

  fn covering_spiral_length(side_of_square: u32) -> u32 {
    let x = side_of_square / 2 + 1;
    let y = (1 - side_of_square % 2) * side_of_square * 2;
    (8 * x - 13) * x + 6 - y
  }

  fn rotate(width: u32, height: u32, x: i32, y: i32, rotation: u32) -> (i32, i32) {
    match rotation {
      0 => (x, y),
      1 => (width as i32 - x - 1, y),
      2 => (x, height as i32 - y - 1),
      3 => (width as i32 - x - 1, height as i32 - y - 1),
      4 => (y, x),
      5 => (height as i32 - y - 1, x),
      6 => (y, width as i32 - x - 1),
      7 => (height as i32 - y - 1, width as i32 - x - 1),
      r => panic!("Invalid rotation number: {}", r)
    }
  }

  fn build_dfa(name: &str, width: u32, height: u32, pattern: usize, rotation: u32, s: &str) -> Dfa {
    let center_x = (width - 1) / 2;
    let center_y = (height - 1) / 2;
    let spiral_length = Patterns::covering_spiral_length(cmp::max(width, height)) as usize;
    let mut states = Vec::with_capacity(spiral_length + 2);
    let fs = spiral_length; // "Found" state.
    let nfs = spiral_length + 1; // "Not found" state.
    for (i, (shift_x, shift_y)) in Spiral::new().into_iter().take(spiral_length).enumerate() {
      let nxt = i + 1;
      let (x, y) = Patterns::rotate(width, height, center_x as i32 + shift_x, center_y as i32 + shift_y, rotation);
      let state = if x >= 0 && x < width as i32 && y >= 0 && y < height as i32 {
        let pos = y as u32 * width + x as u32;
        match s.char_at(pos as usize) {
          '.' => DfaState::new(nxt, nfs, nfs, nfs, false, HashSet::with_capacity(0)),
          '?' => DfaState::new(nxt, nxt, nxt, nfs, false, HashSet::with_capacity(0)),
          '*' => DfaState::new(nxt, nxt, nxt, nxt, false, HashSet::with_capacity(0)),
          'R' => DfaState::new(nfs, nxt, nfs, nfs, false, HashSet::with_capacity(0)),
          'B' => DfaState::new(nfs, nfs, nxt, nfs, false, HashSet::with_capacity(0)),
          'r' => DfaState::new(nxt, nxt, nfs, nfs, false, HashSet::with_capacity(0)),
          'b' => DfaState::new(nxt, nfs, nxt, nfs, false, HashSet::with_capacity(0)),
          '#' => DfaState::new(nfs, nfs, nfs, nxt, false, HashSet::with_capacity(0)),
          c   => panic!("Invalid character in the pattern '{}': {}", name, c)
        }
      } else {
        DfaState::new(nxt, nxt, nxt, nxt, false, HashSet::with_capacity(0))
      };
      states.push(state);
    }
    let mut patterns = HashSet::with_capacity(1);
    patterns.insert(pattern);
    states.push(DfaState::new(fs, fs, fs, fs, true, patterns));
    states.push(DfaState::new(nfs, nfs, nfs, nfs, true, HashSet::with_capacity(0)));
    Dfa::new(states)
  }

  pub fn load(file: File) -> Patterns {
    let archive = Archive::new(file);
    let mut s = String::new();
    let mut pattern_s = String::new();
    let mut patterns = Vec::new();
    let iter = archive.files().expect("Reading of tar archive is failed.").into_iter().map(|file| file.expect("Reading of file in tar archive is failed."));
    let mut dfa = Dfa::empty();
    let mut min_size = u32::max_value();
    for file in iter {
      let name = file.header().path().ok()
        .and_then(|path| path.to_str().map(|s| s.to_owned()))
        .unwrap_or_else(|| "<unknown>".to_owned());
      let mut input = BufReader::new(file);
      let (width, height, moves_count, priority) = Patterns::read_header(&mut input, &mut s);
      if width < min_size {
        min_size = width;
      }
      if height < min_size {
        min_size = height;
      }
      Patterns::read_pattern(&mut input, &mut pattern_s, width, height);
      let moves = Patterns::read_moves(&mut input, &mut s, moves_count);
      for i in 0 .. 8 {
        let cur_dfa = Patterns::build_dfa(name.as_str(), width, height, patterns.len(), i, &pattern_s);
        dfa = dfa.product(&cur_dfa);
        patterns.push(Pattern {
          p: priority,
          width: if i < 4 { width } else { height },
          height: if i < 4 { height } else { width },
          moves: moves.iter().map(|m| {
            let (x, y) = Patterns::rotate(width, height, m.x as i32, m.y as i32, i);
            Move {
              x: x as u32,
              y: y as u32,
              p: m.p
            }
          }).collect()
        });
      }
    }
    Patterns {
      min_size: min_size,
      dfa: dfa,
      patterns: patterns
    }
  }

  pub fn find(&self, field: &Field, player: Player, first_match: bool) -> Vec<(Pos, f64)> {
    if self.dfa.is_empty() {
      return Vec::with_capacity(0);
    }
    let mut priorities_sum = 0f64;
    let mut moves_count = 0usize;
    let mut matched = Vec::new();
    let left_border = (self.min_size - 1) / 2;
    let right_border = self.min_size / 2;
    let inv_color = player == Player::Black;
    for y in left_border .. field.height() - right_border {
      for x in left_border .. field.width() - right_border {
        let patterns = self.dfa.run(&mut Spiral::new().into_iter().map(|(shift_x, shift_y)| {
          let cur_x = x as i32 + shift_x;
          let cur_y = y as i32 + shift_y;
          if cur_x >= 0 && cur_x < field.width() as i32 && cur_y >= 0 && cur_y < field.height() as i32 {
            let pos = field.to_pos(cur_x as u32, cur_y as u32);
            field.cell(pos)
          } else {
            Cell::new(true)
          }
        }), inv_color, first_match);
        for &pattern_number in patterns {
          let pattern = &self.patterns[pattern_number];
          priorities_sum += pattern.p;
          moves_count += pattern.moves.len();
          matched.push((pattern_number, x, y));
        }
      }
    }
    let mut result = Vec::with_capacity(moves_count);
    for (pattern_number, center_x, center_y) in matched {
      let pattern = &self.patterns[pattern_number];
      for &Move { x, y, p: probability } in &pattern.moves {
        let move_x = center_x - (pattern.width - 1) / 2 + x;
        let move_y = center_y - (pattern.height - 1) / 2 + y;
        result.push((field.to_pos(move_x, move_y), probability * pattern.p / priorities_sum));
      }
    }
    result
  }

  pub fn find_sorted(&self, field: &Field, player: Player, first_match: bool) -> Vec<(Pos, f64)> {
    let moves = self.find(field, player, first_match);
    let mut map = HashMap::with_capacity(moves.len());
    for (pos, p) in moves {
      let sum_p = map.get(&pos).cloned().unwrap_or(0f64) + p;
      map.insert(pos, sum_p);
    }
    let mut result = map.into_iter().collect::<Vec<(Pos, f64)>>();
    result.sort_by(|&(_, a), &(_, b)| b.partial_cmp(&a).expect("Cann't compare f64 types."));
    result
  }

  pub fn find_foreground(&self, field: &Field, player: Player, first_match: bool) -> Option<Pos> {
    self.find_sorted(field, player, first_match).first().map(|&(pos, _)| pos)
  }

  pub fn find_rand<T: Rng>(&self, field: &Field, player: Player, first_match: bool, rng: &mut T) -> Option<Pos> {
    let moves = self.find_sorted(field, player, first_match);
    if moves.is_empty() {
      return None;
    }
    let rand = rng.gen();
    let mut sum = 0f64;
    let mut idx = 0;
    while sum < rand && idx < moves.len() {
      sum += moves[idx].1;
      idx += 1;
    }
    Some(moves[idx - 1].0)
  }
}
<commit_msg>Bugfixes.<commit_after>use std::collections::{HashSet, HashMap};
use std::io::{BufReader, BufRead};
use std::str::FromStr;
use std::fs::File;
use std::cmp;
use rand::Rng;
use tar::Archive;
use spiral::Spiral;
use dfa::{Dfa, DfaState};
use player::Player;
use cell::Cell;
use field::{Pos, Field};

const PATTERNS_STR: &'static str = "patterns";

#[derive(Clone, Debug)]
struct Move {
  x: u32,
  y: u32,
  p: f64 // probability
}

struct Pattern {
  p: f64, // priority
  width: u32,
  height: u32,
  moves: Vec<Move>
}

pub struct Patterns {
  min_size: u32,
  dfa: Dfa,
  patterns: Vec<Pattern>
}

impl Patterns {
  pub fn empty() -> Patterns {
    Patterns {
      min_size: u32::max_value(),
      dfa: Dfa::empty(),
      patterns: Vec::with_capacity(0)
    }
  }

  fn read_header<T: BufRead>(input: &mut T, s: &mut String) -> (u32, u32, u32, f64) {
    s.clear();
    input.read_line(s).ok();
    s.pop();
    let mut split = s.split(' ').fuse();
    let width = u32::from_str(split.next().expect("Invalid pattern format: expected width.")).expect("Invalid pattern format: width must be u32.");
    let height = u32::from_str(split.next().expect("Invalid pattern format: expected height.")).expect("Invalid pattern format: height must be u32.");
    let moves_count = u32::from_str(split.next().expect("Invalid pattern format: expected moves count.")).expect("Invalid pattern format: moves count must be u32.");
    let priority = f64::from_str(split.next().expect("Invalid pattern format: expected priority.")).expect("Invalid pattern format: priority must be f64.");
    (width, height, moves_count, priority)
  }

  fn read_pattern<T: BufRead>(input: &mut T, s: &mut String, width: u32, height: u32) {
    s.clear();
    for _ in 0 .. height {
      let last_len = s.len();
      input.read_line(s).ok();
      s.pop();
      assert_eq!((s.len() - last_len) as u32, width)
    }
  }

  fn read_moves<T: BufRead>(input: &mut T, s: &mut String, moves_count: u32) -> Vec<Move> {
    let mut moves = Vec::with_capacity(moves_count as usize);
    let mut priorities_sum = 0f64;
    for _ in 0 .. moves_count {
      s.clear();
      input.read_line(s).ok();
      s.pop();
      let mut split = s.split(' ').fuse();
      let x = u32::from_str(split.next().expect("Invalid pattern format: expected x coordinate.")).expect("Invalid pattern format: x coordinate must be u32.");
      let y = u32::from_str(split.next().expect("Invalid pattern format: expected x coordinate.")).expect("Invalid pattern format: x coordinate must be u32.");
      let p = f64::from_str(split.next().expect("Invalid pattern format: expected probability.")).expect("Invalid pattern format: probability must be f64.");
      priorities_sum += p;
      moves.push(Move {
        x: x,
        y: y,
        p: p
      });
    }
    for m in &mut moves {
      m.p /= priorities_sum;
    }
    moves
  }

  fn covering_spiral_length(side_of_square: u32) -> u32 {
    let x = side_of_square / 2 + 1;
    let y = (1 - side_of_square % 2) * side_of_square * 2;
    (8 * x - 13) * x + 6 - y
  }

  fn rotate(width: u32, height: u32, x: i32, y: i32, rotation: u32) -> (i32, i32) {
    match rotation {
      0 => (x, y),
      1 => (width as i32 - x - 1, y),
      2 => (x, height as i32 - y - 1),
      3 => (width as i32 - x - 1, height as i32 - y - 1),
      4 => (y, x),
      5 => (height as i32 - y - 1, x),
      6 => (y, width as i32 - x - 1),
      7 => (height as i32 - y - 1, width as i32 - x - 1),
      r => panic!("Invalid rotation number: {}", r)
    }
  }

  fn rotate_back(width: u32, height: u32, x: i32, y: i32, rotation: u32) -> (i32, i32) {
    let back_rotation = match rotation {
      5 => 6,
      6 => 5,
      r => r
    };
    Patterns::rotate(width, height, x, y, back_rotation)
  }

  fn rotate_sizes(width: u32, height: u32, rotation: u32) -> (u32, u32) {
    if rotation < 4 {
      (width, height)
    } else {
      (height, width)
    }
  }

  fn build_dfa(name: &str, width: u32, height: u32, pattern: usize, rotation: u32, s: &str) -> Dfa {
    let (rotated_width, rotated_height) = Patterns::rotate_sizes(width, height, rotation);
    let center_x = (rotated_width - 1) / 2;
    let center_y = (rotated_height - 1) / 2;
    let spiral_length = Patterns::covering_spiral_length(cmp::max(width, height)) as usize;
    let mut states = Vec::with_capacity(spiral_length + 2);
    let fs = spiral_length; // "Found" state.
    let nfs = spiral_length + 1; // "Not found" state.
    for (i, (shift_x, shift_y)) in Spiral::new().into_iter().take(spiral_length).enumerate() {
      let nxt = i + 1;
      let (x, y) = Patterns::rotate_back(rotated_width, rotated_height, center_x as i32 + shift_x, center_y as i32 + shift_y, rotation);
      let state = if x >= 0 && x < width as i32 && y >= 0 && y < height as i32 {
        let pos = y as u32 * width + x as u32;
        match s.char_at(pos as usize) {
          '.' => DfaState::new(nxt, nfs, nfs, nfs, false, HashSet::with_capacity(0)),
          '?' => DfaState::new(nxt, nxt, nxt, nfs, false, HashSet::with_capacity(0)),
          '*' => DfaState::new(nxt, nxt, nxt, nxt, false, HashSet::with_capacity(0)),
          'R' => DfaState::new(nfs, nxt, nfs, nfs, false, HashSet::with_capacity(0)),
          'B' => DfaState::new(nfs, nfs, nxt, nfs, false, HashSet::with_capacity(0)),
          'r' => DfaState::new(nxt, nxt, nfs, nfs, false, HashSet::with_capacity(0)),
          'b' => DfaState::new(nxt, nfs, nxt, nfs, false, HashSet::with_capacity(0)),
          '#' => DfaState::new(nfs, nfs, nfs, nxt, false, HashSet::with_capacity(0)),
          c   => panic!("Invalid character in the pattern '{}': {}", name, c)
        }
      } else {
        DfaState::new(nxt, nxt, nxt, nxt, false, HashSet::with_capacity(0))
      };
      states.push(state);
    }
    let mut patterns = HashSet::with_capacity(1);
    patterns.insert(pattern);
    states.push(DfaState::new(fs, fs, fs, fs, true, patterns));
    states.push(DfaState::new(nfs, nfs, nfs, nfs, true, HashSet::with_capacity(0)));
    Dfa::new(states)
  }

  pub fn load(file: File) -> Patterns {
    let archive = Archive::new(file);
    let mut s = String::new();
    let mut pattern_s = String::new();
    let mut patterns = Vec::new();
    let iter = archive.files().expect("Reading of tar archive is failed.").into_iter().map(|file| file.expect("Reading of file in tar archive is failed."));
    let mut dfa = Dfa::empty();
    let mut min_size = u32::max_value();
    for file in iter {
      let name = file.header().path().ok()
        .and_then(|path| path.to_str().map(|s| s.to_owned()))
        .unwrap_or_else(|| "<unknown>".to_owned());
      info!(target: PATTERNS_STR, "Loading pattern '{}'", name);
      let mut input = BufReader::new(file);
      let (width, height, moves_count, priority) = Patterns::read_header(&mut input, &mut s);
      if width < min_size {
        min_size = width;
      }
      if height < min_size {
        min_size = height;
      }
      Patterns::read_pattern(&mut input, &mut pattern_s, width, height);
      let moves = Patterns::read_moves(&mut input, &mut s, moves_count);
      for rotation in 0 .. 8 {
        let cur_dfa = Patterns::build_dfa(name.as_str(), width, height, patterns.len(), rotation, &pattern_s);
        dfa = dfa.product(&cur_dfa);
        let (rotated_width, rotated_height) = Patterns::rotate_sizes(width, height, rotation);
        patterns.push(Pattern {
          p: priority,
          width: rotated_width,
          height: rotated_height,
          moves: moves.iter().map(|m| {
            let (x, y) = Patterns::rotate(width, height, m.x as i32, m.y as i32, rotation);
            Move {
              x: x as u32,
              y: y as u32,
              p: m.p
            }
          }).collect()
        });
      }
    }
    Patterns {
      min_size: min_size,
      dfa: dfa,
      patterns: patterns
    }
  }

  pub fn find(&self, field: &Field, player: Player, first_match: bool) -> Vec<(Pos, f64)> {
    if self.dfa.is_empty() {
      return Vec::with_capacity(0);
    }
    let mut priorities_sum = 0f64;
    let mut moves_count = 0usize;
    let mut matched = Vec::new();
    let left_border = (self.min_size - 1) / 2;
    let right_border = self.min_size / 2;
    let inv_color = player == Player::Black;
    for y in left_border .. field.height() - right_border {
      for x in left_border .. field.width() - right_border {
        let patterns = self.dfa.run(&mut Spiral::new().into_iter().map(|(shift_x, shift_y)| {
          let cur_x = x as i32 + shift_x;
          let cur_y = y as i32 + shift_y;
          if cur_x >= 0 && cur_x < field.width() as i32 && cur_y >= 0 && cur_y < field.height() as i32 {
            let pos = field.to_pos(cur_x as u32, cur_y as u32);
            field.cell(pos)
          } else {
            Cell::new(true)
          }
        }), inv_color, first_match);
        for &pattern_number in patterns {
          let pattern = &self.patterns[pattern_number];
          info!(target: PATTERNS_STR, "Found pattern {} ({} with rotation {}) at ({}, {}).", pattern_number, pattern_number / 8, pattern_number % 8, x - (pattern.width - 1) / 2, y -(pattern.height - 1) / 2);
          priorities_sum += pattern.p;
          moves_count += pattern.moves.len();
          matched.push((pattern_number, x, y));
        }
      }
    }
    let mut result = Vec::with_capacity(moves_count);
    for (pattern_number, center_x, center_y) in matched {
      let pattern = &self.patterns[pattern_number];
      for &Move { x, y, p: probability } in &pattern.moves {
        let move_x = center_x - (pattern.width - 1) / 2 + x;
        let move_y = center_y - (pattern.height - 1) / 2 + y;
        result.push((field.to_pos(move_x, move_y), probability * pattern.p / priorities_sum));
      }
    }
    info!(target: PATTERNS_STR, "Found moves: {:?}.", result.iter().map(|&(pos, p)| (field.to_x(pos), field.to_y(pos), p)).collect::<Vec<(u32, u32, f64)>>());
    result
  }

  pub fn find_sorted(&self, field: &Field, player: Player, first_match: bool) -> Vec<(Pos, f64)> {
    let moves = self.find(field, player, first_match);
    let mut map = HashMap::with_capacity(moves.len());
    for (pos, p) in moves {
      let sum_p = map.get(&pos).cloned().unwrap_or(0f64) + p;
      map.insert(pos, sum_p);
    }
    let mut result = map.into_iter().collect::<Vec<(Pos, f64)>>();
    result.sort_by(|&(_, a), &(_, b)| b.partial_cmp(&a).expect("Cann't compare f64 types."));
    info!(target: PATTERNS_STR, "Found sorted moves: {:?}.", result.iter().map(|&(pos, p)| (field.to_x(pos), field.to_y(pos), p)).collect::<Vec<(u32, u32, f64)>>());
    result
  }

  pub fn find_foreground(&self, field: &Field, player: Player, first_match: bool) -> Option<Pos> {
    self.find_sorted(field, player, first_match).first().map(|&(pos, _)| pos)
  }

  pub fn find_rand<T: Rng>(&self, field: &Field, player: Player, first_match: bool, rng: &mut T) -> Option<Pos> {
    let moves = self.find_sorted(field, player, first_match);
    if moves.is_empty() {
      return None;
    }
    let rand = rng.gen();
    let mut sum = 0f64;
    let mut idx = 0;
    while sum < rand && idx < moves.len() {
      sum += moves[idx].1;
      idx += 1;
    }
    Some(moves[idx - 1].0)
  }
}
<|endoftext|>


<commit_before>use std::fmt;

pub struct RawCodeItem {
    pub name: String,
    pub attributes: Vec<(String, String)>,
    pub children: Vec<RawCodeItem>
}

impl RawCodeItem {
    pub fn new(item_name: &str, item_attribs: Vec<(String, String)>) -> RawCodeItem {
        RawCodeItem {
            name: String::from(item_name),
            attributes: item_attribs,
            children: Vec::<RawCodeItem>::new()
        }
    }
}

pub struct RawCode {
    pub elements: Vec<RawCodeItem>
}

impl RawCode {
    pub fn new() -> RawCode {
        RawCode {
            elements: Vec::<RawCodeItem>::new()
        }
    }

    // convert raw data to cpp code
    pub fn to_cpp(&self) -> u8 {
        0
    }

    // convert raw data to Rust code
    pub fn to_rust(&self) -> u8 {
        0
    }

    // used by Display trait to print the tree of elements
    fn print_element(&self, e: &RawCodeItem, f: &mut fmt::Formatter, is_last: bool, num_spaces: u8, depth: u8) {
        if depth > 0 {
            let _ = write!(f, "|  ");

            if num_spaces > 0 {
                for _ in 0..depth-1-num_spaces {
                    let _ = write!(f, "|  ");
                }
                for _ in 0..num_spaces {
                    let _ = write!(f, "   ");
                }
            }
            else {
                for _ in 0..depth-1 {
                    let _ = write!(f, "|  ");
                }
            }
        }

        let _ = write!(f, "|--{}", e.name);
        if e.attributes.len() > 0 {
            let _ = write!(f, " [");
            for a in 0..e.attributes.len() {
                if a > 0 && a < e.attributes.len() {
                    let _ = write!(f, ", ");
                }
                let _ = write!(f, "{}:\"{}\"", e.attributes[a].0, e.attributes[a].1);
            }
            let _ = write!(f, "]");
        }
        let _ = write!(f, "\n");

        if e.children.len() > 0 {
            for c in 0..e.children.len() {
                let ne = if is_last && depth > 0 { num_spaces+1 } else { 0 };
                let _ = self.print_element(&e.children[c], f, (e.children.len() - c) == 1, ne, depth+1);
            }

            if !is_last {
                for _ in 0..depth {
                    let _ = write!(f, "|  ");
                }

                let _ = write!(f, "|\n");
            }
        }
        else if depth == 0 {
            let _ = write!(f, "|\n");
        }
    }
}

impl fmt::Display for RawCode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let _ = write!(f, "\n");
        for e in 0..self.elements.len() {
            let _ = self.print_element(&self.elements[e], f, (self.elements.len() - e) == 1, 0, 0);
        }
        write!(f, "\n")
    }
}
<commit_msg>improved tree draw<commit_after>use std::fmt;

pub struct RawCodeItem {
    pub name: String,
    pub attributes: Vec<(String, String)>,
    pub children: Vec<RawCodeItem>
}

impl RawCodeItem {
    pub fn new(item_name: &str, item_attribs: Vec<(String, String)>) -> RawCodeItem {
        RawCodeItem {
            name: String::from(item_name),
            attributes: item_attribs,
            children: Vec::<RawCodeItem>::new()
        }
    }
}

pub struct RawCode {
    pub elements: Vec<RawCodeItem>
}

impl RawCode {
    pub fn new() -> RawCode {
        RawCode {
            elements: Vec::<RawCodeItem>::new()
        }
    }

    // convert raw data to cpp code
    pub fn to_cpp(&self) -> u8 {
        0
    }

    // convert raw data to Rust code
    pub fn to_rust(&self) -> u8 {
        0
    }

    // used by Display trait to print the tree of elements
    fn print_element(&self, e: &RawCodeItem, f: &mut fmt::Formatter, depth: u8, empty_spaces: &mut Vec<u8>) {
        // indentation
        for i in 0..depth {
            let mut separator = "|";
            for j in empty_spaces.iter() {
                if i == *j {
                    separator = " ";
                    break;
                }
            }
            let _ = write!(f, "{}  ", separator);
        }

        let _ = write!(f, "|--{}", e.name);
        // print attributes
        if e.attributes.len() > 0 {
            let _ = write!(f, " [");
            for a in 0..e.attributes.len() {
                if a > 0 && a < e.attributes.len() {
                    let _ = write!(f, ", ");
                }
                let _ = write!(f, "{}:\"{}\"", e.attributes[a].0, e.attributes[a].1);
            }
            let _ = write!(f, "]");
        }
        let _ = write!(f, "\n");

        // child processing
        if e.children.len() > 0 {
            for c in 0..e.children.len() {
                if (e.children.len() - c) == 1 {
                    empty_spaces.push(depth+1);
                }
                self.print_element(&e.children[c], f, depth+1, empty_spaces);
            }

            if depth == 1 {
                empty_spaces.clear();
            }
        }
    }
}

impl fmt::Display for RawCode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let _ = write!(f, "\n");
        for e in 0..self.elements.len() {
            let mut empty_spaces = Vec::<u8>::new();
            let _ = self.print_element(&self.elements[e], f, 0, &mut empty_spaces);
        }
        write!(f, "\n")
    }
}
<|endoftext|>