<commit_before>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Mining plugin manager, using the cuckoo-miner crate to provide
//! a mining worker implementation
//!

use std::io::Read;
use std::net::SocketAddr;
use std::str;
use std::sync::{mpsc, Arc};
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;
use std::thread;
use time::{self, now_utc};

use hyper;

use p2p;
use util::LOGGER;

const DANDELION_RELAY_TIME: i64 = 600;
const BAN_WINDOW: i64 = 10800;
const PEER_MAX_COUNT: u32 = 25;
const PEER_PREFERRED_COUNT: u32 = 8;
const SEEDS_URL: &'static str = "http://grin-tech.org/seeds.txt";

pub fn connect_and_monitor(
	p2p_server: Arc<p2p::Server>,
	capabilities: p2p::Capabilities,
	seed_list: Box<Fn() -> Vec<SocketAddr> + Send>,
	stop: Arc<AtomicBool>,
) {
	let _ = thread::Builder::new()
		.name("seed".to_string())
		.spawn(move || {
			let peers = p2p_server.peers.clone();

			// open a channel with a listener that connects every peer address sent below
			// max peer count
			let (tx, rx) = mpsc::channel();

			// check seeds first
			connect_to_seeds(peers.clone(), tx.clone(), seed_list);

			let mut prev = time::now_utc() - time::Duration::seconds(60);
			loop {
				let current_time = time::now_utc();

				if current_time - prev > time::Duration::seconds(20) {
					// try to connect to any address sent to the channel
					listen_for_addrs(peers.clone(), p2p_server.clone(), capabilities, &rx);

					// monitor additional peers if we need to add more
					monitor_peers(peers.clone(), capabilities, tx.clone());

					update_dandelion_relay(peers.clone());

					prev = current_time;
				}

				thread::sleep(Duration::from_secs(1));

				if stop.load(Ordering::Relaxed) {
					break;
				}
			}
		});
}

fn monitor_peers(
	peers: Arc<p2p::Peers>,
	capabilities: p2p::Capabilities,
	tx: mpsc::Sender<SocketAddr>,
) {
	// regularly check if we need to acquire more peers  and if so, gets
	// them from db
	let total_count = peers.all_peers().len();
	let mut healthy_count = 0;
	let mut banned_count = 0;
	let mut defunct_count = 0;
	for x in peers.all_peers() {
		match x.flags {
			p2p::State::Banned => {
				let interval = now_utc().to_timespec().sec - x.last_banned;
				// Unban peer
				if interval >= BAN_WINDOW {
					peers.unban_peer(&x.addr);
					debug!(
						LOGGER,
						"monitor_peers: unbanned {} after {} seconds", x.addr, interval
					);
				} else {
					banned_count += 1;
				}
			}
			p2p::State::Healthy => healthy_count += 1,
			p2p::State::Defunct => defunct_count += 1,
		}
	}

	debug!(
		LOGGER,
		"monitor_peers: {} connected ({} most_work). \
		 all {} = {} healthy + {} banned + {} defunct",
		peers.connected_peers().len(),
		peers.most_work_peers().len(),
		total_count,
		healthy_count,
		banned_count,
		defunct_count,
	);

	// maintenance step first, clean up p2p server peers
	peers.clean_peers(PEER_MAX_COUNT as usize);

	// not enough peers, getting more from db
	if peers.peer_count() >= PEER_PREFERRED_COUNT {
		return;
	}

	// loop over connected peers
	// ask them for their list of peers
	for p in peers.connected_peers() {
		if let Ok(p) = p.try_read() {
			debug!(LOGGER, "monitor_peers: ask {} for more peers", p.info.addr);
			let _ = p.send_peer_request(capabilities);
		} else {
			warn!(LOGGER, "monitor_peers: failed to get read lock on peer");
		}
	}

	// find some peers from our db
	// and queue them up for a connection attempt
	let peers = peers.find_peers(p2p::State::Healthy, p2p::Capabilities::UNKNOWN, 100);
	for p in peers {
		debug!(LOGGER, "monitor_peers: queue to soon try {}", p.addr);
		tx.send(p.addr).unwrap();
	}
}

fn update_dandelion_relay(peers: Arc<p2p::Peers>) {
	// Dandelion Relay Updater
	let dandelion_relay = peers.get_dandelion_relay();
	if dandelion_relay.is_empty() {
		debug!(LOGGER, "monitor_peers: no dandelion relay updating");
		peers.update_dandelion_relay();
	} else {
		for last_added in dandelion_relay.keys() {
			let dandelion_interval = now_utc().to_timespec().sec - last_added;
			if dandelion_interval >= DANDELION_RELAY_TIME {
				debug!(LOGGER, "monitor_peers: updating expired dandelion relay");
				peers.update_dandelion_relay();
			}
		}
	}
}

// Check if we have any pre-existing peer in db. If so, start with those,
// otherwise use the seeds provided.
fn connect_to_seeds(
	peers: Arc<p2p::Peers>,
	tx: mpsc::Sender<SocketAddr>,
	seed_list: Box<Fn() -> Vec<SocketAddr>>,
) {
	// check if we have some peers in db
	let peers = peers.find_peers(p2p::State::Healthy, p2p::Capabilities::FULL_HIST, 100);

	// if so, get their addresses, otherwise use our seeds
	let peer_addrs = if peers.len() > 3 {
		peers.iter().map(|p| p.addr).collect::<Vec<_>>()
	} else {
		seed_list()
	};

	if peer_addrs.len() == 0 {
		warn!(LOGGER, "No seeds were retrieved.");
	}

	// connect to this first set of addresses
	for addr in peer_addrs {
		tx.send(addr).unwrap();
	}
}

/// Regularly poll a channel receiver for new addresses and initiate a
/// connection if the max peer count isn't exceeded. A request for more
/// peers is also automatically sent after connection.
fn listen_for_addrs(
	peers: Arc<p2p::Peers>,
	p2p: Arc<p2p::Server>,
	capab: p2p::Capabilities,
	rx: &mpsc::Receiver<SocketAddr>,
) {
	let pc = peers.peer_count();
	for addr in rx.try_iter() {
		if pc < PEER_MAX_COUNT {
			let connect_peer = p2p.connect(&addr);
			match connect_peer {
				Ok(p) => {
					trace!(LOGGER, "connect_and_req: ok. attempting send_peer_request");
					if let Ok(p) = p.try_read() {
						let _ = p.send_peer_request(capab);
					}
				}
				Err(e) => {
					debug!(LOGGER, "connect_and_req: {} is Defunct; {:?}", addr, e);
					let _ = peers.update_state(addr, p2p::State::Defunct);
				}
			}
		}
	}
}

/// Extract the list of seeds from a pre-defined text file available through
/// http. Easy method until we have a set of DNS names we can rely on.
pub fn web_seeds() -> Box<Fn() -> Vec<SocketAddr> + Send> {
	Box::new(|| {
		let client = hyper::Client::new();
		debug!(LOGGER, "Retrieving seed nodes from {}", &SEEDS_URL);

		// http get, filtering out non 200 results
		let mut res = client
			.get(SEEDS_URL)
			.send()
			.expect("Failed to resolve seeds.");
		if res.status != hyper::Ok {
			panic!("Failed to resolve seeds, got status {}.", res.status);
		}
		let mut buf = vec![];
		res.read_to_end(&mut buf)
			.expect("Could not read seed list.");

		let text = str::from_utf8(&buf[..]).expect("Corrupted seed list.");
		let addrs = text.split_whitespace()
			.map(|s| s.parse().unwrap())
			.collect::<Vec<_>>();
		debug!(LOGGER, "Retrieved seed addresses: {:?}", addrs);
		addrs
	})
}

/// Convenience function when the seed list is immediately known. Mostly used
/// for tests.
pub fn predefined_seeds(addrs_str: Vec<String>) -> Box<Fn() -> Vec<SocketAddr> + Send> {
	Box::new(move || {
		addrs_str
			.iter()
			.map(|s| s.parse().unwrap())
			.collect::<Vec<_>>()
	})
}
<commit_msg>Make peer connect attempts asynchronous (#879)<commit_after>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Mining plugin manager, using the cuckoo-miner crate to provide
//! a mining worker implementation
//!

use std::io::Read;
use std::net::SocketAddr;
use std::str;
use std::sync::{mpsc, Arc};
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;
use std::thread;
use time::{self, now_utc};

use hyper;

use p2p;
use util::LOGGER;

const DANDELION_RELAY_TIME: i64 = 600;
const BAN_WINDOW: i64 = 10800;
const PEER_MAX_COUNT: u32 = 25;
const PEER_PREFERRED_COUNT: u32 = 8;
const SEEDS_URL: &'static str = "http://grin-tech.org/seeds.txt";

pub fn connect_and_monitor(
	p2p_server: Arc<p2p::Server>,
	capabilities: p2p::Capabilities,
	seed_list: Box<Fn() -> Vec<SocketAddr> + Send>,
	stop: Arc<AtomicBool>,
) {
	let _ = thread::Builder::new()
		.name("seed".to_string())
		.spawn(move || {
			let peers = p2p_server.peers.clone();

			// open a channel with a listener that connects every peer address sent below
			// max peer count
			let (tx, rx) = mpsc::channel();

			// check seeds first
			connect_to_seeds(peers.clone(), tx.clone(), seed_list);

			let mut prev = time::now_utc() - time::Duration::seconds(60);
			loop {
				let current_time = time::now_utc();

				if current_time - prev > time::Duration::seconds(20) {
					// try to connect to any address sent to the channel
					listen_for_addrs(peers.clone(), p2p_server.clone(), capabilities, &rx);

					// monitor additional peers if we need to add more
					monitor_peers(peers.clone(), capabilities, tx.clone());

					update_dandelion_relay(peers.clone());

					prev = current_time;
				}

				thread::sleep(Duration::from_secs(1));

				if stop.load(Ordering::Relaxed) {
					break;
				}
			}
		});
}

fn monitor_peers(
	peers: Arc<p2p::Peers>,
	capabilities: p2p::Capabilities,
	tx: mpsc::Sender<SocketAddr>,
) {
	// regularly check if we need to acquire more peers  and if so, gets
	// them from db
	let total_count = peers.all_peers().len();
	let mut healthy_count = 0;
	let mut banned_count = 0;
	let mut defunct_count = 0;
	for x in peers.all_peers() {
		match x.flags {
			p2p::State::Banned => {
				let interval = now_utc().to_timespec().sec - x.last_banned;
				// Unban peer
				if interval >= BAN_WINDOW {
					peers.unban_peer(&x.addr);
					debug!(
						LOGGER,
						"monitor_peers: unbanned {} after {} seconds", x.addr, interval
					);
				} else {
					banned_count += 1;
				}
			}
			p2p::State::Healthy => healthy_count += 1,
			p2p::State::Defunct => defunct_count += 1,
		}
	}

	debug!(
		LOGGER,
		"monitor_peers: {} connected ({} most_work). \
		 all {} = {} healthy + {} banned + {} defunct",
		peers.connected_peers().len(),
		peers.most_work_peers().len(),
		total_count,
		healthy_count,
		banned_count,
		defunct_count,
	);

	// maintenance step first, clean up p2p server peers
	peers.clean_peers(PEER_MAX_COUNT as usize);

	// not enough peers, getting more from db
	if peers.peer_count() >= PEER_PREFERRED_COUNT {
		return;
	}

	// loop over connected peers
	// ask them for their list of peers
	for p in peers.connected_peers() {
		if let Ok(p) = p.try_read() {
			debug!(LOGGER, "monitor_peers: ask {} for more peers", p.info.addr);
			let _ = p.send_peer_request(capabilities);
		} else {
			warn!(LOGGER, "monitor_peers: failed to get read lock on peer");
		}
	}

	// find some peers from our db
	// and queue them up for a connection attempt
	let peers = peers.find_peers(p2p::State::Healthy, p2p::Capabilities::UNKNOWN, 100);
	for p in peers {
		debug!(LOGGER, "monitor_peers: queue to soon try {}", p.addr);
		tx.send(p.addr).unwrap();
	}
}

fn update_dandelion_relay(peers: Arc<p2p::Peers>) {
	// Dandelion Relay Updater
	let dandelion_relay = peers.get_dandelion_relay();
	if dandelion_relay.is_empty() {
		debug!(LOGGER, "monitor_peers: no dandelion relay updating");
		peers.update_dandelion_relay();
	} else {
		for last_added in dandelion_relay.keys() {
			let dandelion_interval = now_utc().to_timespec().sec - last_added;
			if dandelion_interval >= DANDELION_RELAY_TIME {
				debug!(LOGGER, "monitor_peers: updating expired dandelion relay");
				peers.update_dandelion_relay();
			}
		}
	}
}

// Check if we have any pre-existing peer in db. If so, start with those,
// otherwise use the seeds provided.
fn connect_to_seeds(
	peers: Arc<p2p::Peers>,
	tx: mpsc::Sender<SocketAddr>,
	seed_list: Box<Fn() -> Vec<SocketAddr>>,
) {
	// check if we have some peers in db
	let peers = peers.find_peers(p2p::State::Healthy, p2p::Capabilities::FULL_HIST, 100);

	// if so, get their addresses, otherwise use our seeds
	let peer_addrs = if peers.len() > 3 {
		peers.iter().map(|p| p.addr).collect::<Vec<_>>()
	} else {
		seed_list()
	};

	if peer_addrs.len() == 0 {
		warn!(LOGGER, "No seeds were retrieved.");
	}

	// connect to this first set of addresses
	for addr in peer_addrs {
		tx.send(addr).unwrap();
	}
}

/// Regularly poll a channel receiver for new addresses and initiate a
/// connection if the max peer count isn't exceeded. A request for more
/// peers is also automatically sent after connection.
fn listen_for_addrs(
	peers: Arc<p2p::Peers>,
	p2p: Arc<p2p::Server>,
	capab: p2p::Capabilities,
	rx: &mpsc::Receiver<SocketAddr>,
) {
	let pc = peers.peer_count();
	for addr in rx.try_iter() {
		if pc < PEER_MAX_COUNT {
			let peers_c = peers.clone();
			let p2p_c = p2p.clone();
			let _ = thread::Builder::new()
				.name("peer_connect".to_string())
				.spawn(move || {
					let connect_peer = p2p_c.connect(&addr);
					match connect_peer {
						Ok(p) => {
							trace!(LOGGER, "connect_and_req: ok. attempting send_peer_request");
							if let Ok(p) = p.try_read() {
								let _ = p.send_peer_request(capab);
							}
						}
						Err(e) => {
							debug!(LOGGER, "connect_and_req: {} is Defunct; {:?}", addr, e);
							let _ = peers_c.update_state(addr, p2p::State::Defunct);
						}
					}
				});
		}
	}
}

/// Extract the list of seeds from a pre-defined text file available through
/// http. Easy method until we have a set of DNS names we can rely on.
pub fn web_seeds() -> Box<Fn() -> Vec<SocketAddr> + Send> {
	Box::new(|| {
		let client = hyper::Client::new();
		debug!(LOGGER, "Retrieving seed nodes from {}", &SEEDS_URL);

		// http get, filtering out non 200 results
		let mut res = client
			.get(SEEDS_URL)
			.send()
			.expect("Failed to resolve seeds.");
		if res.status != hyper::Ok {
			panic!("Failed to resolve seeds, got status {}.", res.status);
		}
		let mut buf = vec![];
		res.read_to_end(&mut buf)
			.expect("Could not read seed list.");

		let text = str::from_utf8(&buf[..]).expect("Corrupted seed list.");
		let addrs = text.split_whitespace()
			.map(|s| s.parse().unwrap())
			.collect::<Vec<_>>();
		debug!(LOGGER, "Retrieved seed addresses: {:?}", addrs);
		addrs
	})
}

/// Convenience function when the seed list is immediately known. Mostly used
/// for tests.
pub fn predefined_seeds(addrs_str: Vec<String>) -> Box<Fn() -> Vec<SocketAddr> + Send> {
	Box::new(move || {
		addrs_str
			.iter()
			.map(|s| s.parse().unwrap())
			.collect::<Vec<_>>()
	})
}
<|endoftext|>


<commit_before>use cgmath::prelude::*;
use cgmath::Point3;

use renderer::{Intersect, Ray};

#[derive(Clone)]
pub struct AABB {
    pub min: Point3<f32>,
    pub max: Point3<f32>,
}

pub fn min_point(p1: &Point3<f32>, p2: &Point3<f32>) -> Point3<f32> {
    let mut p_min = Point3::origin();
    for i in 0..2 {
        p_min[i] = p1[i].min(p2[i]);
    }
    p_min
}

pub fn max_point(p1: &Point3<f32>, p2: &Point3<f32>) -> Point3<f32> {
    let mut p_max = Point3::origin();
    for i in 0..2 {
        p_max[i] = p1[i].max(p2[i]);
    }
    p_max
}

impl AABB {
    /// Update the bounding box with new position
    pub fn add_point(&mut self, new_pos: &Point3<f32>) {
        self.min = min_point(&self.min, new_pos);
        self.max = max_point(&self.max, new_pos);
    }

    /// Update the bounding box to enclose other aswell
    pub fn add_aabb(&mut self, other: &AABB) {
        self.min = min_point(&self.min, &other.min);
        self.max = max_point(&self.max, &other.max);
    }

    /// Get the center of the scene as defined by the bounding box
    pub fn center(&self) -> Point3<f32> {
        Point3::midpoint(self.min, self.max)
    }

    pub fn longest_edge(&self) -> f32 {
        let mut longest = 0.0f32;
        for i in 0..2 {
            longest = longest.max(self.max[i] - self.min[i]);
        }
        longest
    }

    pub fn longest_edge_i(&self) -> usize {
        let mut longest = 0.0f32;
        let mut index = 0;
        for i in 0..2 {
            let length = self.max[i] - self.min[i];
            if length > longest {
                longest = length;
                index = i;
            }
        }
        index
    }
}

impl<'a> Intersect<'a, f32> for AABB {
    fn intersect(&self, ray: &Ray) -> Option<f32> {
        let t1 = (self.min - ray.orig).mul_element_wise(ray.reciprocal_dir);
        let t2 = (self.max - ray.orig).mul_element_wise(ray.reciprocal_dir);
        let mut start = ::std::f32::MIN;
        let mut end = ::std::f32::MAX;
        for i in 0..2 {
            if ray.dir[i] == 0.0 && (ray.orig[i] < self.min[i] || ray.orig[i] > self.max[i]) {
                // Can't hit
                return None;
            } else if ray.dir[i] < 0.0 {
                start = start.max(t2[i]);
                end = end.min(t1[i]);
            } else {
                start = start.max(t1[i]);
                end = end.min(t2[i]);
            }
        }
        if start <= end && end > 0.0 && start < ray.length {
            Some(start)
        } else {
            None
        }
    }
}
<commit_msg>Iterate all three dimensions in AABB<commit_after>use cgmath::prelude::*;
use cgmath::Point3;

use renderer::{Intersect, Ray};

#[derive(Clone)]
pub struct AABB {
    pub min: Point3<f32>,
    pub max: Point3<f32>,
}

pub fn min_point(p1: &Point3<f32>, p2: &Point3<f32>) -> Point3<f32> {
    let mut p_min = Point3::max_value();
    for i in 0..3 {
        p_min[i] = p1[i].min(p2[i]);
    }
    p_min
}

pub fn max_point(p1: &Point3<f32>, p2: &Point3<f32>) -> Point3<f32> {
    let mut p_max = Point3::min_value();
    for i in 0..3 {
        p_max[i] = p1[i].max(p2[i]);
    }
    p_max
}

impl AABB {
    /// Update the bounding box with new position
    pub fn add_point(&mut self, new_pos: &Point3<f32>) {
        self.min = min_point(&self.min, new_pos);
        self.max = max_point(&self.max, new_pos);
    }

    /// Update the bounding box to enclose other aswell
    pub fn add_aabb(&mut self, other: &AABB) {
        self.min = min_point(&self.min, &other.min);
        self.max = max_point(&self.max, &other.max);
    }

    /// Get the center of the scene as defined by the bounding box
    pub fn center(&self) -> Point3<f32> {
        Point3::midpoint(self.min, self.max)
    }

    pub fn longest_edge(&self) -> f32 {
        let mut longest = 0.0f32;
        for i in 0..3 {
            longest = longest.max(self.max[i] - self.min[i]);
        }
        longest
    }

    pub fn longest_edge_i(&self) -> usize {
        let mut longest = 0.0f32;
        let mut index = 0;
        for i in 0..3 {
            let length = self.max[i] - self.min[i];
            if length > longest {
                longest = length;
                index = i;
            }
        }
        index
    }
}

impl<'a> Intersect<'a, f32> for AABB {
    fn intersect(&self, ray: &Ray) -> Option<f32> {
        let t1 = (self.min - ray.orig).mul_element_wise(ray.reciprocal_dir);
        let t2 = (self.max - ray.orig).mul_element_wise(ray.reciprocal_dir);
        let mut start = ::std::f32::MIN;
        let mut end = ::std::f32::MAX;
        for i in 0..3 {
            if ray.dir[i] == 0.0 && (ray.orig[i] < self.min[i] || ray.orig[i] > self.max[i]) {
                // Can't hit
                return None;
            } else if ray.dir[i] < 0.0 {
                start = start.max(t2[i]);
                end = end.min(t1[i]);
            } else {
                start = start.max(t1[i]);
                end = end.min(t2[i]);
            }
        }
        if start <= end && end > 0.0 && start < ray.length {
            Some(start)
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>/// Breadth First Search
pub mod bfs {

    use hex2d::Coordinate;
    use hex2d;

    use std::hash;
    use std::collections::VecDeque;
    use std::collections::HashMap;
    use std::collections::hash_map::Entry::{Occupied,Vacant};

    struct Visited<I = i32>
        where I : hex2d::Integer
        {
            prev : Coordinate<I>,
            dist : u32,
        }

    /// Breadth First Search
    ///
    /// Use BFS to find closest (in walk steps) Coordinates that satisfy `is_dest` and can be
    /// reached with a walk through coordinates for which `can_pass` returns true.
    pub struct Traverser<FCanPass, FIsDest, I = i32> where
        I : hex2d::Integer,
        I : hash::Hash,
        FCanPass : Fn(Coordinate<I>) -> bool,
        FIsDest : Fn(Coordinate<I>) -> bool
    {
        visited : HashMap<Coordinate<I>, Visited<I>>,
        to_traverse : VecDeque<Coordinate<I>>,
        can_pass : FCanPass,
        is_dest : FIsDest,
        start : Coordinate<I>,
    }

    impl<FCanPass, FIsDest, I> Traverser<FCanPass, FIsDest, I> where
        I : hex2d::Integer,
        I : hash::Hash,
        FCanPass : Fn(Coordinate<I>) -> bool,
        FIsDest : Fn(Coordinate<I>) -> bool
    {

        /// Create a Traverser instance with initial conditions
        pub fn new(can_pass : FCanPass, is_dest : FIsDest, start: Coordinate<I>) -> Traverser<FCanPass, FIsDest, I> {
            let mut to_traverse = VecDeque::new();
            to_traverse.push_back(start);

            let mut visited = HashMap::new();
            visited.insert(start, Visited{prev: start, dist: 0});

            Traverser {
                visited: visited,
                to_traverse: to_traverse,
                can_pass: can_pass,
                is_dest: is_dest,
                start: start,
            }
        }

        /// Find next closest coordinate.
        ///
        /// Can be called multiple times, each time returning next coordinate
        pub fn find(&mut self) -> Option<Coordinate<I>> {

            loop {
                let pos = match self.to_traverse.pop_front() {
                    None => return None,
                    Some(coord) => coord,
                };

                // Traverse before returning, so `find` can be call subsequently
                // for more than just first answer
                if (self.can_pass)(pos) {

                    let &Visited{dist, ..} = self.visited.get(&pos).expect("BFS: Should have been visited already");

                    let dist = dist + 1;

                    for &npos in pos.neighbors().iter() {
                        match self.visited.entry(npos) {
                            Occupied(_) => { /* already visited */ }
                            Vacant(entry) => {
                                entry.insert(Visited{prev: pos, dist: dist});
                                self.to_traverse.push_back(npos);
                            }
                        }
                    }
                }

                if (self.is_dest)(pos) {
                    return Some(pos);
                }
            }
        }

        /// Return neighbor Coordinate to `pos` that is one step closer to
        /// `start` from initial conditions.
        ///
        /// Useful for finding whole path to a Coordinate returned by `find`.
        ///
        /// Returns `None` for Coordinates that were not yet visited.
        /// Returns `start` for `start` (from initial conditions)
        pub fn backtrace(&self, pos : Coordinate<I>) -> Option<Coordinate<I>> {
            self.visited.get(&pos).map(|entry| entry.prev)
        }

        /// Perform a recursive `backtrace` walk to find a neighbor of `start` that leads to the
        /// Coordinate returned by `find()`.
        ///
        /// Returns `None` for Coordinates that were not yet visited.
        /// Returns `start` for `start` (from initial conditions)
        pub fn backtrace_last(&self, mut pos : Coordinate<I>) -> Option<Coordinate<I>> {
            loop {
                pos = match self.visited.get(&pos) {
                    None => return None,
                    Some(entry) => {
                        if entry.prev == self.start {
                            return Some(pos);
                        } else {
                            entry.prev
                        }
                    }
                }
            }
        }
    }
}

/// Very tricky, but (hopefully) good enough, recursive LoS algorithm
pub mod los {
    use hex2d;
    use hex2d::Angle::{Left,Right};

    use hex2d::Direction;
    use hex2d::Coordinate;

    fn los_rec<FOpaqueness, FVisible, I=i32>(
        opaqueness : &FOpaqueness,
        visible : &mut FVisible,
        light: I,
        pos : Coordinate<I>,
        start_dir : Direction,
        main_dir : Direction,
        dir : Option<Direction>,
        pdir : Option<Direction>,
    ) where
        I : hex2d::Integer,
        FOpaqueness : Fn(Coordinate<I>) -> I,
        FVisible : FnMut(Coordinate<I>, I)
        {

            let mut light = light;
            let opaq = opaqueness(pos);

            if opaq >= light {
                return;
            } else {
                light = light - opaq;
            }

            visible(pos, light);

            /*
            // Handle long corridors a bit better
            if main_dir + Left == start_dir || main_dir == start_dir {
                visible(pos + (main_dir + Left), light);
            }
            if main_dir + Right == start_dir || main_dir == start_dir {
                visible(pos + (main_dir + Right), light);
            }*/

            let neighbors = match (dir, pdir) {
                (Some(dir), Some(pdir)) => {
                    if dir == pdir {
                        vec!(dir)
                    } else {
                        vec!(dir, pdir)
                    }
                },
                (Some(dir), None) => {
                    if main_dir == dir {
                        vec!(dir, dir + Left, dir + Right)
                    } else {
                        vec!(dir, main_dir)
                    }
                },
                _ => {
                    vec!(main_dir, main_dir + Left, main_dir + Right)
                }
            };

            for &d in neighbors.iter() {
                let npos = pos + d;
                match dir {
                    Some(_) => los_rec::<FOpaqueness, FVisible, I>(opaqueness, visible, light, npos, start_dir, d, Some(d), dir),
                    None => los_rec::<FOpaqueness, FVisible, I>(opaqueness, visible, light, npos, start_dir, main_dir, Some(d), dir),
                }
            }
        }

    /// Starting from `pos` in direction `dir`, call `visible` for each visible Coordinate.
    ///
    /// Use `light` as starting range of the LoS. For each visible Coordinate, the value returned
    /// by `opaqueness` will be subtracted from `light` to check if the LoS should finish due to
    /// "lack of visibility". `opaqueness` should typically return 1 for fully transparent
    /// Coordinates, and anything bigger than initial `light` for fully opaque Coordinates.
    pub fn los<FOpaqueness, FVisible, I=i32>(
        opaqueness : &FOpaqueness,
        visible : &mut FVisible,
        light: I,
        pos : Coordinate<I>,
        dirs : &[Direction],
    ) where
        I : hex2d::Integer,
        FOpaqueness : Fn(Coordinate<I>) -> I,
        FVisible : FnMut(Coordinate<I>, I)
        {
            for dir in dirs.iter() {
                los_rec::<FOpaqueness, FVisible, I>(opaqueness, visible, light, pos, *dir, *dir, None, None);
            }
        }
}

/// Combination of tricky Los with straight line checking
pub mod los2 {
    use hex2d;
    use hex2d::Angle::{Left, Right, Forward};
    use hex2d::Direction;
    use hex2d::Coordinate;
    use num::{FromPrimitive};
    use std::collections::HashSet;
    use std::hash;
    use std::ops::{Add};

    fn los_rec<FOpaqueness, FVisible, I=i32>(
        opaqueness : &FOpaqueness,
        visible : &mut FVisible,
        light: I,
        start : Coordinate<I>,
        pos : Coordinate<I>,
        dir : Direction,
        visited : &mut HashSet<Coordinate<I>>,
    ) where
        I : hex2d::Integer,
        I : hash::Hash+Eq,
        for <'a> &'a I: Add<&'a I, Output = I>,
        FOpaqueness : Fn(Coordinate<I>) -> I,
        FVisible : FnMut(Coordinate<I>, I)
        {
            if visited.contains(&pos) {
                return;
            } else {
                visited.insert(pos);
            }

            let mut opaq_sum : I = FromPrimitive::from_i8(0).unwrap();
            let mut last = start;

            for &c in start.line_to(pos).iter() {
                let opaq = opaqueness(c);
                opaq_sum = opaq_sum + opaq;
                last = c;

                if opaq_sum >= light {
                    break;
                }
            };

            if last == pos {
                visible(pos, light - light);
            } else {
                return;
            }

            let neighbors = vec!(Forward, Left, Right);

            for &a in neighbors.iter() {
                let npos = pos + (dir + a);
                los_rec::<FOpaqueness, FVisible, I>(
                    opaqueness, visible, light, start, npos, dir, visited
                    );
            }
        }

    /// Starting from `pos` in direction `dir`, call `visible` for each visible Coordinate.
    ///
    /// Use `light` as starting range of the LoS. For each visible Coordinate, the value returned
    /// by `opaqueness` will be subtracted from `light` to check if the LoS should finish due to
    /// "lack of visibility". `opaqueness` should typically return 1 for fully transparent
    /// Coordinates, and anything bigger than initial `light` for fully opaque Coordinates.
    pub fn los<FOpaqueness, FVisible, I=i32>(
        opaqueness : &FOpaqueness,
        visible : &mut FVisible,
        light: I,
        pos : Coordinate<I>,
        dirs : &[Direction],
    ) where
        I : hex2d::Integer,
        I : hash::Hash,
        for <'a> &'a I: Add<&'a I, Output = I>,
        FOpaqueness : Fn(Coordinate<I>) -> I,
        FVisible : FnMut(Coordinate<I>, I)
        {
            for dir in dirs.iter() {
                let mut visited = HashSet::new();
                los_rec::<FOpaqueness, FVisible, I>(
                    opaqueness, visible, light, pos, pos, *dir, &mut visited
                    );
            }
        }
}
<commit_msg>Make the los2 symetric.<commit_after>/// Breadth First Search
pub mod bfs {

    use hex2d::Coordinate;
    use hex2d;

    use std::hash;
    use std::collections::VecDeque;
    use std::collections::HashMap;
    use std::collections::hash_map::Entry::{Occupied,Vacant};

    struct Visited<I = i32>
        where I : hex2d::Integer
        {
            prev : Coordinate<I>,
            dist : u32,
        }

    /// Breadth First Search
    ///
    /// Use BFS to find closest (in walk steps) Coordinates that satisfy `is_dest` and can be
    /// reached with a walk through coordinates for which `can_pass` returns true.
    pub struct Traverser<FCanPass, FIsDest, I = i32> where
        I : hex2d::Integer,
        I : hash::Hash,
        FCanPass : Fn(Coordinate<I>) -> bool,
        FIsDest : Fn(Coordinate<I>) -> bool
    {
        visited : HashMap<Coordinate<I>, Visited<I>>,
        to_traverse : VecDeque<Coordinate<I>>,
        can_pass : FCanPass,
        is_dest : FIsDest,
        start : Coordinate<I>,
    }

    impl<FCanPass, FIsDest, I> Traverser<FCanPass, FIsDest, I> where
        I : hex2d::Integer,
        I : hash::Hash,
        FCanPass : Fn(Coordinate<I>) -> bool,
        FIsDest : Fn(Coordinate<I>) -> bool
    {

        /// Create a Traverser instance with initial conditions
        pub fn new(can_pass : FCanPass, is_dest : FIsDest, start: Coordinate<I>) -> Traverser<FCanPass, FIsDest, I> {
            let mut to_traverse = VecDeque::new();
            to_traverse.push_back(start);

            let mut visited = HashMap::new();
            visited.insert(start, Visited{prev: start, dist: 0});

            Traverser {
                visited: visited,
                to_traverse: to_traverse,
                can_pass: can_pass,
                is_dest: is_dest,
                start: start,
            }
        }

        /// Find next closest coordinate.
        ///
        /// Can be called multiple times, each time returning next coordinate
        pub fn find(&mut self) -> Option<Coordinate<I>> {

            loop {
                let pos = match self.to_traverse.pop_front() {
                    None => return None,
                    Some(coord) => coord,
                };

                // Traverse before returning, so `find` can be call subsequently
                // for more than just first answer
                if (self.can_pass)(pos) {

                    let &Visited{dist, ..} = self.visited.get(&pos).expect("BFS: Should have been visited already");

                    let dist = dist + 1;

                    for &npos in pos.neighbors().iter() {
                        match self.visited.entry(npos) {
                            Occupied(_) => { /* already visited */ }
                            Vacant(entry) => {
                                entry.insert(Visited{prev: pos, dist: dist});
                                self.to_traverse.push_back(npos);
                            }
                        }
                    }
                }

                if (self.is_dest)(pos) {
                    return Some(pos);
                }
            }
        }

        /// Return neighbor Coordinate to `pos` that is one step closer to
        /// `start` from initial conditions.
        ///
        /// Useful for finding whole path to a Coordinate returned by `find`.
        ///
        /// Returns `None` for Coordinates that were not yet visited.
        /// Returns `start` for `start` (from initial conditions)
        pub fn backtrace(&self, pos : Coordinate<I>) -> Option<Coordinate<I>> {
            self.visited.get(&pos).map(|entry| entry.prev)
        }

        /// Perform a recursive `backtrace` walk to find a neighbor of `start` that leads to the
        /// Coordinate returned by `find()`.
        ///
        /// Returns `None` for Coordinates that were not yet visited.
        /// Returns `start` for `start` (from initial conditions)
        pub fn backtrace_last(&self, mut pos : Coordinate<I>) -> Option<Coordinate<I>> {
            loop {
                pos = match self.visited.get(&pos) {
                    None => return None,
                    Some(entry) => {
                        if entry.prev == self.start {
                            return Some(pos);
                        } else {
                            entry.prev
                        }
                    }
                }
            }
        }
    }
}

/// Very tricky, but (hopefully) good enough, recursive LoS algorithm
pub mod los {
    use hex2d;
    use hex2d::Angle::{Left,Right};

    use hex2d::Direction;
    use hex2d::Coordinate;

    fn los_rec<FOpaqueness, FVisible, I=i32>(
        opaqueness : &FOpaqueness,
        visible : &mut FVisible,
        light: I,
        pos : Coordinate<I>,
        start_dir : Direction,
        main_dir : Direction,
        dir : Option<Direction>,
        pdir : Option<Direction>,
    ) where
        I : hex2d::Integer,
        FOpaqueness : Fn(Coordinate<I>) -> I,
        FVisible : FnMut(Coordinate<I>, I)
        {

            let mut light = light;
            let opaq = opaqueness(pos);

            if opaq >= light {
                return;
            } else {
                light = light - opaq;
            }

            visible(pos, light);

            let neighbors = match (dir, pdir) {
                (Some(dir), Some(pdir)) => {
                    if dir == pdir {
                        vec!(dir)
                    } else {
                        vec!(dir, pdir)
                    }
                },
                (Some(dir), None) => {
                    if main_dir == dir {
                        vec!(dir, dir + Left, dir + Right)
                    } else {
                        vec!(dir, main_dir)
                    }
                },
                _ => {
                    vec!(main_dir, main_dir + Left, main_dir + Right)
                }
            };

            for &d in neighbors.iter() {
                let npos = pos + d;
                match dir {
                    Some(_) => los_rec::<FOpaqueness, FVisible, I>(opaqueness, visible, light, npos, start_dir, d, Some(d), dir),
                    None => los_rec::<FOpaqueness, FVisible, I>(opaqueness, visible, light, npos, start_dir, main_dir, Some(d), dir),
                }
            }
        }

    /// Starting from `pos` in direction `dir`, call `visible` for each visible Coordinate.
    ///
    /// Use `light` as starting range of the LoS. For each visible Coordinate, the value returned
    /// by `opaqueness` will be subtracted from `light` to check if the LoS should finish due to
    /// "lack of visibility". `opaqueness` should typically return 1 for fully transparent
    /// Coordinates, and anything bigger than initial `light` for fully opaque Coordinates.
    pub fn los<FOpaqueness, FVisible, I=i32>(
        opaqueness : &FOpaqueness,
        visible : &mut FVisible,
        light: I,
        pos : Coordinate<I>,
        dirs : &[Direction],
    ) where
        I : hex2d::Integer,
        FOpaqueness : Fn(Coordinate<I>) -> I,
        FVisible : FnMut(Coordinate<I>, I)
        {
            for dir in dirs.iter() {
                los_rec::<FOpaqueness, FVisible, I>(opaqueness, visible, light, pos, *dir, *dir, None, None);
            }
        }
}

/// Combination of tricky Los with straight line checking
pub mod los2 {
    use hex2d;
    use hex2d::Angle::{Left, Right, Forward};
    use hex2d::Direction;
    use hex2d::Coordinate;
    use num::{FromPrimitive};
    use std::collections::HashSet;
    use std::hash;
    use std::ops::{Add};

    fn los_rec<FOpaqueness, FVisible, I=i32>(
        opaqueness : &FOpaqueness,
        visible : &mut FVisible,
        light: I,
        start : Coordinate<I>,
        pos : Coordinate<I>,
        dir : Direction,
        visited : &mut HashSet<Coordinate<I>>,
    ) where
        I : hex2d::Integer,
        I : hash::Hash+Eq,
        for <'a> &'a I: Add<&'a I, Output = I>,
        FOpaqueness : Fn(Coordinate<I>) -> I,
        FVisible : FnMut(Coordinate<I>, I)
        {
            if visited.contains(&pos) {
                return;
            } else {
                visited.insert(pos);
            }

            let mut opaq_sum1 : I = FromPrimitive::from_i8(0).unwrap();
            let mut last1 = start;

            let mut opaq_sum2 : I = FromPrimitive::from_i8(0).unwrap();
            let mut last2 = start;

            for &(c1, c2) in start.line_to_with_edge_detection(pos).iter() {
                if opaq_sum1 < light {
                    let opaq1 = opaqueness(c1);
                    opaq_sum1 = opaq_sum1 + opaq1;
                    last1 = c1;
                }

                if opaq_sum2 < light {
                    let opaq2 = opaqueness(c2);
                    opaq_sum2 = opaq_sum2 + opaq2;
                    last2 = c2;
                }
            };

            if last1 == pos || last2 == pos {
                visible(pos, light - light);
            } else {
                return;
            }

            let neighbors = vec!(Forward, Left, Right);

            for &a in neighbors.iter() {
                let npos = pos + (dir + a);
                los_rec::<FOpaqueness, FVisible, I>(
                    opaqueness, visible, light, start, npos, dir, visited
                    );
            }
        }

    /// Starting from `pos` in direction `dir`, call `visible` for each visible Coordinate.
    ///
    /// Use `light` as starting range of the LoS. For each visible Coordinate, the value returned
    /// by `opaqueness` will be subtracted from `light` to check if the LoS should finish due to
    /// "lack of visibility". `opaqueness` should typically return 1 for fully transparent
    /// Coordinates, and anything bigger than initial `light` for fully opaque Coordinates.
    pub fn los<FOpaqueness, FVisible, I=i32>(
        opaqueness : &FOpaqueness,
        visible : &mut FVisible,
        light: I,
        pos : Coordinate<I>,
        dirs : &[Direction],
    ) where
        I : hex2d::Integer,
        I : hash::Hash,
        for <'a> &'a I: Add<&'a I, Output = I>,
        FOpaqueness : Fn(Coordinate<I>) -> I,
        FVisible : FnMut(Coordinate<I>, I)
        {
            for dir in dirs.iter() {
                let mut visited = HashSet::new();
                los_rec::<FOpaqueness, FVisible, I>(
                    opaqueness, visible, light, pos, pos, *dir, &mut visited
                    );
            }
        }
}
<|endoftext|>


<commit_before>//! Graph algorithms.
//!
//! It is a goal to gradually migrate the algorithms to be based on graph traits
//! so that they are generally applicable. For now, most of these use only the
//! **Graph** type.

use std::collections::BinaryHeap;
use std::borrow::{Borrow};
use std::cmp::min;

use super::{
    Graph,
    Undirected,
    EdgeDirection,
    EdgeType,
    Outgoing,
    Incoming,
    Dfs,
};
use scored::MinScored;
use super::visit::{
    Visitable,
    VisitMap,
    IntoNeighborsDirected,
    IntoNodeIdentifiers,
    IntoExternals,
    NodeIndexable,
    NodeCompactIndexable,
    IntoEdgeReferences,
    EdgeRef,
};
use super::unionfind::UnionFind;
use super::graph::{
    IndexType,
    NodeIndex,
};

pub use super::isomorphism::{
    is_isomorphic,
    is_isomorphic_matching,
};
pub use super::dijkstra::dijkstra;

/// [Generic] Return the number of connected components of the graph.
///
/// For a directed graph, this is the *weakly* connected components.
pub fn connected_components<G>(g: G) -> usize
    where G: NodeCompactIndexable + IntoEdgeReferences,
{
    let mut vertex_sets = UnionFind::new(g.node_bound());
    for edge in g.edge_references() {
        let (a, b) = (edge.source(), edge.target());

        // union the two vertices of the edge
        vertex_sets.union(G::to_index(a), G::to_index(b));
    }
    let mut labels = vertex_sets.into_labeling();
    labels.sort();
    labels.dedup();
    labels.len()
}

/// [Generic] Return `true` if the input graph contains a cycle.
///
/// Always treats the input graph as if undirected.
pub fn is_cyclic_undirected<G>(g: G) -> bool
    where G: NodeIndexable + IntoEdgeReferences
{
    let mut edge_sets = UnionFind::new(g.node_bound());
    for edge in g.edge_references() {
        let (a, b) = (edge.source(), edge.target());

        // union the two vertices of the edge
        //  -- if they were already the same, then we have a cycle
        if !edge_sets.union(G::to_index(a), G::to_index(b)) {
            return true
        }
    }
    false
}

/*
/// **Deprecated: Renamed to `is_cyclic_undirected`.**
pub fn is_cyclic<N, E, Ty, Ix>(g: &Graph<N, E, Ty, Ix>) -> bool
    where Ty: EdgeType,
          Ix: IndexType,
{
    is_cyclic_undirected(g)
}
*/

/// [Generic] Perform a topological sort of a directed graph `g`.
///
/// Visit each node in order (if it is part of a topological order).
///
/// You can pass `g` as either **&Graph** or **&mut Graph**, and it
/// will be passed on to the visitor closure.
#[inline]
fn toposort_generic<G, F>(g: G, mut visit: F)
    where G: IntoNeighborsDirected + IntoExternals + Visitable,
          F: FnMut(G, G::NodeId),
{
    let mut ordered = g.borrow().visit_map();
    let mut tovisit = Vec::new();

    // find all initial nodes
    tovisit.extend(g.externals(Incoming));

    // Take an unvisited element and find which of its neighbors are next
    while let Some(nix) = tovisit.pop() {
        if ordered.is_visited(&nix) {
            continue;
        }
        visit(g, nix.clone());
        ordered.visit(nix.clone());
        for neigh in g.neighbors_directed(nix, Outgoing) {
            // Look at each neighbor, and those that only have incoming edges
            // from the already ordered list, they are the next to visit.
            if g.neighbors_directed(neigh.clone(), Incoming)
                .all(|b| ordered.is_visited(&b)) {
                tovisit.push(neigh);
            }
        }
    }
}

/// [Generic] Return `true` if the input directed graph contains a cycle.
///
/// Using the topological sort algorithm.
pub fn is_cyclic_directed<G>(g: G) -> bool
    where G: IntoNodeIdentifiers + IntoNeighborsDirected + IntoExternals + Visitable,
{
    let mut n_ordered = 0;
    toposort_generic(g, |_, _| n_ordered += 1);
    n_ordered != g.node_count()
}

/// [Generic] Perform a topological sort of a directed graph.
///
/// Return a vector of nodes in topological order: each node is ordered
/// before its successors.
///
/// If the returned vec contains less than all the nodes of the graph, then
/// the graph was cyclic.
pub fn toposort<G>(g: G) -> Vec<G::NodeId>
    where G: IntoNodeIdentifiers + IntoNeighborsDirected + IntoExternals + Visitable,
{
    let mut order = Vec::with_capacity(g.node_count());
    toposort_generic(g, |_, ix| order.push(ix));
    order
}

/// [Generic] Compute the *strongly connected components* using Kosaraju's algorithm.
///
/// Return a vector where each element is an scc.
///
/// For an undirected graph, the sccs are simply the connected components.
pub fn scc<G>(g: G) -> Vec<Vec<G::NodeId>>
    where G: IntoNeighborsDirected + Visitable + IntoNodeIdentifiers,
{
    let mut dfs = Dfs::empty(&g);

    // First phase, reverse dfs pass, compute finishing times.
    // http://stackoverflow.com/a/26780899/161659
    let mut finished = g.visit_map();
    let mut finish_order = Vec::new();
    for i in g.node_identifiers() {
        if dfs.discovered.is_visited(&i) {
            continue
        }

        dfs.stack.push(i);
        while let Some(&nx) = dfs.stack.last() {
            if dfs.discovered.visit(nx) {
                // First time visiting `nx`: Push neighbors, don't pop `nx`
                for succ in g.neighbors_directed(nx, EdgeDirection::Incoming) {
                    if !dfs.discovered.is_visited(&succ) {
                        dfs.stack.push(succ);
                    }
                }
            } else {
                dfs.stack.pop();
                if finished.visit(nx) {
                    // Second time: All reachable nodes must have been finished
                    finish_order.push(nx);
                }
            }
        }
    }

    g.reset_map(&mut dfs.discovered);
    let mut sccs = Vec::new();

    // Second phase
    // Process in decreasing finishing time order
    for i in finish_order.into_iter().rev() {
        if dfs.discovered.is_visited(&i) {
            continue;
        }
        // Move to the leader node.
        dfs.move_to(i);
        //let leader = nindex;
        let mut scc = Vec::new();
        while let Some(nx) = dfs.next(g) {
            scc.push(nx);
        }
        sccs.push(scc);
    }
    sccs
}

/// [Generic] Compute the *strongly connected components* using Tarjan's algorithm.
///
/// Return a vector where each element is an scc.
///
/// For an undirected graph, the sccs are simply the connected components.
pub fn tarjan_scc<N, E, Ty, Ix>(g: &Graph<N, E, Ty, Ix>) -> Vec<Vec<NodeIndex<Ix>>>
    where Ty: EdgeType,
          Ix: IndexType
{
    #[derive(Copy, Clone)]
    #[derive(Debug)]
    struct NodeData {
        index: Option<usize>,
        lowlink: usize,
        on_stack: bool,
    }

    #[derive(Debug)]
    struct Data<'a, Ix: 'a> {
        index: usize,
        nodes: Vec<NodeData>,
        stack: Vec<NodeIndex<Ix>>,
        sccs: &'a mut Vec<Vec<NodeIndex<Ix>>>,
    }

    fn scc_visit<N, E, Ty, Ix>(v: NodeIndex<Ix>, g: &Graph<N, E, Ty, Ix>, data: &mut Data<Ix>)
        where Ty: EdgeType,
              Ix: IndexType
    {
        macro_rules! node {
            ($node:expr) => (data.nodes[$node.index()])
        }

        if node![v].index.is_some() {
            // already visited
            return;
        }

        let v_index = data.index;
        node![v].index = Some(v_index);
        node![v].lowlink = v_index;
        node![v].on_stack = true;
        data.stack.push(v);
        data.index += 1;

        for w in g.neighbors(v) {
            match node![w].index {
                None => {
                    scc_visit(w, g, data);
                    node![v].lowlink = min(node![v].lowlink, node![w].lowlink);
                }
                Some(w_index) => {
                    if node![w].on_stack {
                        // Successor w is in stack S and hence in the current SCC
                        let v_lowlink = &mut node![v].lowlink;
                        *v_lowlink = min(*v_lowlink, w_index);
                    }
                }
            }
        }

        // If v is a root node, pop the stack and generate an SCC
        if let Some(v_index) = node![v].index {
            if node![v].lowlink == v_index {
                let mut cur_scc = Vec::new();
                loop {
                    let w = data.stack.pop().unwrap();
                    node![w].on_stack = false;
                    cur_scc.push(w);
                    if w == v { break; }
                }
                data.sccs.push(cur_scc);
            }
        }
    }

    let mut sccs = Vec::new();
    {
        let map = g.node_indices().map(|_| {
            NodeData { index: None, lowlink: !0, on_stack: false }
        }).collect();

        let mut data = Data {
            index: 0,
            nodes: map,
            stack: Vec::new(),
            sccs: &mut sccs,
        };
        for n in g.node_indices() {
            scc_visit(n, g, &mut data);
        }
    }
    sccs
}

/// [Graph] Condense every strongly connected component into a single node and return the result.
///
/// If `make_acyclic` is true, self-loops and multi edges are ignored, guaranteeing that
/// the output is acyclic.
pub fn condensation<N, E, Ty, Ix>(g: Graph<N, E, Ty, Ix>, make_acyclic: bool) -> Graph<Vec<N>, E, Ty, Ix>
    where Ty: EdgeType,
          Ix: IndexType,
{
    let sccs = scc(&g);
    let mut condensed: Graph<Vec<N>, E, Ty, Ix> = Graph::with_capacity(sccs.len(), g.edge_count());

    // Build a map from old indices to new ones.
    let mut node_map = vec![NodeIndex::end(); g.node_count()];
    for comp in sccs {
        let new_nix = condensed.add_node(Vec::new());
        for nix in comp {
            node_map[nix.index()] = new_nix;
        }
    }

    // Consume nodes and edges of the old graph and insert them into the new one.
    let (nodes, edges) = g.into_nodes_edges();
    for (nix, node) in nodes.into_iter().enumerate() {
        condensed[node_map[nix]].push(node.weight);
    }
    for edge in edges {
        let source = node_map[edge.source().index()];
        let target = node_map[edge.target().index()];
        if make_acyclic {
            if source != target {
                condensed.update_edge(source, target, edge.weight);
            }
        } else {
            condensed.add_edge(source, target, edge.weight);
        }
    }
    condensed
}

/// [Graph] Compute a *minimum spanning tree* of a graph.
///
/// Treat the input graph as undirected.
///
/// Using Kruskal's algorithm with runtime **O(|E| log |E|)**. We actually
/// return a minimum spanning forest, i.e. a minimum spanning tree for each connected
/// component of the graph.
///
/// The resulting graph has all the vertices of the input graph (with identical node indices),
/// and **|V| - c** edges, where **c** is the number of connected components in `g`.
pub fn min_spanning_tree<N, E, Ty, Ix>(g: &Graph<N, E, Ty, Ix>)
    -> Graph<N, E, Undirected, Ix>
    where N: Clone,
          E: Clone + PartialOrd,
          Ty: EdgeType,
          Ix: IndexType,
{
    if g.node_count() == 0 {
        return Graph::with_capacity(0, 0)
    }

    // Create a mst skeleton by copying all nodes
    let mut mst = Graph::with_capacity(g.node_count(), g.node_count() - 1);
    for node in g.raw_nodes() {
        mst.add_node(node.weight.clone());
    }

    // Initially each vertex is its own disjoint subgraph, track the connectedness
    // of the pre-MST with a union & find datastructure.
    let mut subgraphs = UnionFind::new(g.node_count());

    let mut sort_edges = BinaryHeap::with_capacity(g.edge_count());
    for edge in g.edge_references() {
        sort_edges.push(MinScored(edge.weight().clone(), (edge.source(), edge.target())));
    }

    // Kruskal's algorithm.
    // Algorithm is this:
    //
    // 1. Create a pre-MST with all the vertices and no edges.
    // 2. Repeat:
    //
    //  a. Remove the shortest edge from the original graph.
    //  b. If the edge connects two disjoint trees in the pre-MST,
    //     add the edge.
    while let Some(MinScored(score, (a, b))) = sort_edges.pop() {
        // check if the edge would connect two disjoint parts
        if subgraphs.union(a.index(), b.index()) {
            mst.add_edge(a, b, score);
        }
    }

    debug_assert!(mst.node_count() == g.node_count());
    debug_assert!(mst.edge_count() < g.node_count());
    mst
}
<commit_msg>Better generalization of `tarjan_scc`<commit_after>//! Graph algorithms.
//!
//! It is a goal to gradually migrate the algorithms to be based on graph traits
//! so that they are generally applicable. For now, most of these use only the
//! **Graph** type.

use std::collections::BinaryHeap;
use std::borrow::{Borrow};
use std::cmp::min;

use super::{
    Graph,
    Undirected,
    EdgeDirection,
    EdgeType,
    Outgoing,
    Incoming,
    Dfs,
};
use scored::MinScored;
use super::visit::{
    Visitable,
    VisitMap,
    IntoNeighbors,
    IntoNeighborsDirected,
    IntoNodeIdentifiers,
    IntoExternals,
    NodeIndexable,
    NodeCompactIndexable,
    IntoEdgeReferences,
    EdgeRef,
};
use super::unionfind::UnionFind;
use super::graph::{
    IndexType,
    NodeIndex,
};

pub use super::isomorphism::{
    is_isomorphic,
    is_isomorphic_matching,
};
pub use super::dijkstra::dijkstra;

/// [Generic] Return the number of connected components of the graph.
///
/// For a directed graph, this is the *weakly* connected components.
pub fn connected_components<G>(g: G) -> usize
    where G: NodeCompactIndexable + IntoEdgeReferences,
{
    let mut vertex_sets = UnionFind::new(g.node_bound());
    for edge in g.edge_references() {
        let (a, b) = (edge.source(), edge.target());

        // union the two vertices of the edge
        vertex_sets.union(G::to_index(a), G::to_index(b));
    }
    let mut labels = vertex_sets.into_labeling();
    labels.sort();
    labels.dedup();
    labels.len()
}

/// [Generic] Return `true` if the input graph contains a cycle.
///
/// Always treats the input graph as if undirected.
pub fn is_cyclic_undirected<G>(g: G) -> bool
    where G: NodeIndexable + IntoEdgeReferences
{
    let mut edge_sets = UnionFind::new(g.node_bound());
    for edge in g.edge_references() {
        let (a, b) = (edge.source(), edge.target());

        // union the two vertices of the edge
        //  -- if they were already the same, then we have a cycle
        if !edge_sets.union(G::to_index(a), G::to_index(b)) {
            return true
        }
    }
    false
}

/*
/// **Deprecated: Renamed to `is_cyclic_undirected`.**
pub fn is_cyclic<N, E, Ty, Ix>(g: &Graph<N, E, Ty, Ix>) -> bool
    where Ty: EdgeType,
          Ix: IndexType,
{
    is_cyclic_undirected(g)
}
*/

/// [Generic] Perform a topological sort of a directed graph `g`.
///
/// Visit each node in order (if it is part of a topological order).
///
/// You can pass `g` as either **&Graph** or **&mut Graph**, and it
/// will be passed on to the visitor closure.
#[inline]
fn toposort_generic<G, F>(g: G, mut visit: F)
    where G: IntoNeighborsDirected + IntoExternals + Visitable,
          F: FnMut(G, G::NodeId),
{
    let mut ordered = g.borrow().visit_map();
    let mut tovisit = Vec::new();

    // find all initial nodes
    tovisit.extend(g.externals(Incoming));

    // Take an unvisited element and find which of its neighbors are next
    while let Some(nix) = tovisit.pop() {
        if ordered.is_visited(&nix) {
            continue;
        }
        visit(g, nix.clone());
        ordered.visit(nix.clone());
        for neigh in g.neighbors_directed(nix, Outgoing) {
            // Look at each neighbor, and those that only have incoming edges
            // from the already ordered list, they are the next to visit.
            if g.neighbors_directed(neigh.clone(), Incoming)
                .all(|b| ordered.is_visited(&b)) {
                tovisit.push(neigh);
            }
        }
    }
}

/// [Generic] Return `true` if the input directed graph contains a cycle.
///
/// Using the topological sort algorithm.
pub fn is_cyclic_directed<G>(g: G) -> bool
    where G: IntoNodeIdentifiers + IntoNeighborsDirected + IntoExternals + Visitable,
{
    let mut n_ordered = 0;
    toposort_generic(g, |_, _| n_ordered += 1);
    n_ordered != g.node_count()
}

/// [Generic] Perform a topological sort of a directed graph.
///
/// Return a vector of nodes in topological order: each node is ordered
/// before its successors.
///
/// If the returned vec contains less than all the nodes of the graph, then
/// the graph was cyclic.
pub fn toposort<G>(g: G) -> Vec<G::NodeId>
    where G: IntoNodeIdentifiers + IntoNeighborsDirected + IntoExternals + Visitable,
{
    let mut order = Vec::with_capacity(g.node_count());
    toposort_generic(g, |_, ix| order.push(ix));
    order
}

/// [Generic] Compute the *strongly connected components* using Kosaraju's algorithm.
///
/// Return a vector where each element is an scc.
///
/// For an undirected graph, the sccs are simply the connected components.
pub fn scc<G>(g: G) -> Vec<Vec<G::NodeId>>
    where G: IntoNeighborsDirected + Visitable + IntoNodeIdentifiers,
{
    let mut dfs = Dfs::empty(&g);

    // First phase, reverse dfs pass, compute finishing times.
    // http://stackoverflow.com/a/26780899/161659
    let mut finished = g.visit_map();
    let mut finish_order = Vec::new();
    for i in g.node_identifiers() {
        if dfs.discovered.is_visited(&i) {
            continue
        }

        dfs.stack.push(i);
        while let Some(&nx) = dfs.stack.last() {
            if dfs.discovered.visit(nx) {
                // First time visiting `nx`: Push neighbors, don't pop `nx`
                for succ in g.neighbors_directed(nx, EdgeDirection::Incoming) {
                    if !dfs.discovered.is_visited(&succ) {
                        dfs.stack.push(succ);
                    }
                }
            } else {
                dfs.stack.pop();
                if finished.visit(nx) {
                    // Second time: All reachable nodes must have been finished
                    finish_order.push(nx);
                }
            }
        }
    }

    g.reset_map(&mut dfs.discovered);
    let mut sccs = Vec::new();

    // Second phase
    // Process in decreasing finishing time order
    for i in finish_order.into_iter().rev() {
        if dfs.discovered.is_visited(&i) {
            continue;
        }
        // Move to the leader node.
        dfs.move_to(i);
        //let leader = nindex;
        let mut scc = Vec::new();
        while let Some(nx) = dfs.next(g) {
            scc.push(nx);
        }
        sccs.push(scc);
    }
    sccs
}

/// [Generic] Compute the *strongly connected components* using Tarjan's algorithm.
///
/// Return a vector where each element is an scc.
///
/// For an undirected graph, the sccs are simply the connected components.
pub fn tarjan_scc<G>(g: G) -> Vec<Vec<G::NodeId>>
    where G: IntoNodeIdentifiers + IntoNeighbors + NodeIndexable
{
    #[derive(Copy, Clone)]
    #[derive(Debug)]
    struct NodeData {
        index: Option<usize>,
        lowlink: usize,
        on_stack: bool,
    }

    #[derive(Debug)]
    struct Data<'a, G>
        where G: NodeIndexable,
          G::NodeId: 'a
    {
        index: usize,
        nodes: Vec<NodeData>,
        stack: Vec<G::NodeId>,
        sccs: &'a mut Vec<Vec<G::NodeId>>,
    }

    fn scc_visit<G>(v: G::NodeId, g: G, data: &mut Data<G>)
        where G: IntoNeighbors + NodeIndexable
    {
        macro_rules! node {
            ($node:expr) => (data.nodes[G::to_index($node)])
        }

        if node![v].index.is_some() {
            // already visited
            return;
        }

        let v_index = data.index;
        node![v].index = Some(v_index);
        node![v].lowlink = v_index;
        node![v].on_stack = true;
        data.stack.push(v);
        data.index += 1;

        for w in g.neighbors(v) {
            match node![w].index {
                None => {
                    scc_visit(w, g, data);
                    node![v].lowlink = min(node![v].lowlink, node![w].lowlink);
                }
                Some(w_index) => {
                    if node![w].on_stack {
                        // Successor w is in stack S and hence in the current SCC
                        let v_lowlink = &mut node![v].lowlink;
                        *v_lowlink = min(*v_lowlink, w_index);
                    }
                }
            }
        }

        // If v is a root node, pop the stack and generate an SCC
        if let Some(v_index) = node![v].index {
            if node![v].lowlink == v_index {
                let mut cur_scc = Vec::new();
                loop {
                    let w = data.stack.pop().unwrap();
                    node![w].on_stack = false;
                    cur_scc.push(w);
                    if G::to_index(w) == G::to_index(v) { break; }
                }
                data.sccs.push(cur_scc);
            }
        }
    }

    let mut sccs = Vec::new();
    {
        let map = g.node_identifiers().map(|_| {
            NodeData { index: None, lowlink: !0, on_stack: false }
        }).collect();

        let mut data = Data {
            index: 0,
            nodes: map,
            stack: Vec::new(),
            sccs: &mut sccs,
        };

        for n in g.node_identifiers() {
            scc_visit(n, g, &mut data);
        }
    }
    sccs
}

/// [Graph] Condense every strongly connected component into a single node and return the result.
///
/// If `make_acyclic` is true, self-loops and multi edges are ignored, guaranteeing that
/// the output is acyclic.
pub fn condensation<N, E, Ty, Ix>(g: Graph<N, E, Ty, Ix>, make_acyclic: bool) -> Graph<Vec<N>, E, Ty, Ix>
    where Ty: EdgeType,
          Ix: IndexType,
{
    let sccs = scc(&g);
    let mut condensed: Graph<Vec<N>, E, Ty, Ix> = Graph::with_capacity(sccs.len(), g.edge_count());

    // Build a map from old indices to new ones.
    let mut node_map = vec![NodeIndex::end(); g.node_count()];
    for comp in sccs {
        let new_nix = condensed.add_node(Vec::new());
        for nix in comp {
            node_map[nix.index()] = new_nix;
        }
    }

    // Consume nodes and edges of the old graph and insert them into the new one.
    let (nodes, edges) = g.into_nodes_edges();
    for (nix, node) in nodes.into_iter().enumerate() {
        condensed[node_map[nix]].push(node.weight);
    }
    for edge in edges {
        let source = node_map[edge.source().index()];
        let target = node_map[edge.target().index()];
        if make_acyclic {
            if source != target {
                condensed.update_edge(source, target, edge.weight);
            }
        } else {
            condensed.add_edge(source, target, edge.weight);
        }
    }
    condensed
}

/// [Graph] Compute a *minimum spanning tree* of a graph.
///
/// Treat the input graph as undirected.
///
/// Using Kruskal's algorithm with runtime **O(|E| log |E|)**. We actually
/// return a minimum spanning forest, i.e. a minimum spanning tree for each connected
/// component of the graph.
///
/// The resulting graph has all the vertices of the input graph (with identical node indices),
/// and **|V| - c** edges, where **c** is the number of connected components in `g`.
pub fn min_spanning_tree<N, E, Ty, Ix>(g: &Graph<N, E, Ty, Ix>)
    -> Graph<N, E, Undirected, Ix>
    where N: Clone,
          E: Clone + PartialOrd,
          Ty: EdgeType,
          Ix: IndexType,
{
    if g.node_count() == 0 {
        return Graph::with_capacity(0, 0)
    }

    // Create a mst skeleton by copying all nodes
    let mut mst = Graph::with_capacity(g.node_count(), g.node_count() - 1);
    for node in g.raw_nodes() {
        mst.add_node(node.weight.clone());
    }

    // Initially each vertex is its own disjoint subgraph, track the connectedness
    // of the pre-MST with a union & find datastructure.
    let mut subgraphs = UnionFind::new(g.node_count());

    let mut sort_edges = BinaryHeap::with_capacity(g.edge_count());
    for edge in g.edge_references() {
        sort_edges.push(MinScored(edge.weight().clone(), (edge.source(), edge.target())));
    }

    // Kruskal's algorithm.
    // Algorithm is this:
    //
    // 1. Create a pre-MST with all the vertices and no edges.
    // 2. Repeat:
    //
    //  a. Remove the shortest edge from the original graph.
    //  b. If the edge connects two disjoint trees in the pre-MST,
    //     add the edge.
    while let Some(MinScored(score, (a, b))) = sort_edges.pop() {
        // check if the edge would connect two disjoint parts
        if subgraphs.union(a.index(), b.index()) {
            mst.add_edge(a, b, score);
        }
    }

    debug_assert!(mst.node_count() == g.node_count());
    debug_assert!(mst.edge_count() < g.node_count());
    mst
}
<|endoftext|>


<commit_before>use std::any::Any;
use std::error::Error;
use std::fmt;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};

use {Future, Poll, Async};
use slot::{Slot, Token};
use stream::Stream;
use task;

/// Creates an in-memory channel implementation of the `Stream` trait.
///
/// This method creates a concrete implementation of the `Stream` trait which
/// can be used to send values across threads in a streaming fashion. This
/// channel is unique in that it implements back pressure to ensure that the
/// sender never outpaces the receiver. The `Sender::send` method will only
/// allow sending one message and the next message can only be sent once the
/// first was consumed.
///
/// The `Receiver` returned implements the `Stream` trait and has access to any
/// number of the associated combinators for transforming the result.
pub fn channel<T, E>() -> (Sender<T, E>, Receiver<T, E>) {
    let inner = Arc::new(Inner {
        slot: Slot::new(None),
        receiver_gone: AtomicBool::new(false),
    });
    let sender = Sender {
        inner: inner.clone(),
    };
    let receiver = Receiver {
        inner: inner,
        on_full_token: None,
    };
    (sender, receiver)
}

/// The transmission end of a channel which is used to send values.
///
/// This is created by the `channel` method in the `stream` module.
pub struct Sender<T, E> {
    inner: Arc<Inner<T, E>>,
}

/// A future returned by the `Sender::send` method which will resolve to the
/// sender once it's available to send another message.
#[must_use = "futures do nothing unless polled"]
pub struct FutureSender<T, E> {
    sender: Option<Sender<T, E>>,
    data: Option<Result<T, E>>,
    on_empty_token: Option<Token>,
}

/// The receiving end of a channel which implements the `Stream` trait.
///
/// This is a concrete implementation of a stream which can be used to represent
/// a stream of values being computed elsewhere. This is created by the
/// `channel` method in the `stream` module.
#[must_use = "streams do nothing unless polled"]
pub struct Receiver<T, E> {
    inner: Arc<Inner<T, E>>,
    on_full_token: Option<Token>,
}

struct Inner<T, E> {
    slot: Slot<Message<Result<T, E>>>,
    receiver_gone: AtomicBool,
}

enum Message<T> {
    Data(T),
    Done,
}

pub struct SendError<T, E>(Result<T, E>);

impl<T, E> fmt::Debug for SendError<T, E> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_tuple("SendError")
            .field(&"...")
            .finish()
    }
}

impl<T, E> fmt::Display for SendError<T, E> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "send failed because receiver is gone")
    }
}

impl<T, E> Error for SendError<T, E>
    where T: Any, E: Any
{
    fn description(&self) -> &str {
        "send failed because receiver is gone"
    }
}

impl<T, E> Stream for Receiver<T, E> {
    type Item = T;
    type Error = E;

    fn poll(&mut self) -> Poll<Option<T>, E> {
        if let Some(token) = self.on_full_token.take() {
            self.inner.slot.cancel(token);
        }

        match self.inner.slot.try_consume() {
            Ok(Message::Data(Ok(e))) => Ok(Async::Ready(Some(e))),
            Ok(Message::Data(Err(e))) => Err(e),
            Ok(Message::Done) => Ok(Async::Ready(None)),
            Err(..) => {
                let task = task::park();
                self.on_full_token = Some(self.inner.slot.on_full(move |_| {
                    task.unpark();
                }));
                Ok(Async::NotReady)
            }
        }
    }
}

impl<T, E> Drop for Receiver<T, E> {
    fn drop(&mut self) {
        self.inner.receiver_gone.store(true, Ordering::SeqCst);
        if let Some(token) = self.on_full_token.take() {
            self.inner.slot.cancel(token);
        }
        self.inner.slot.on_full(|slot| {
            drop(slot.try_consume());
        });
    }
}

impl<T, E> Sender<T, E> {
    /// Sends a new value along this channel to the receiver.
    ///
    /// This method consumes the sender and returns a future which will resolve
    /// to the sender again when the value sent has been consumed.
    pub fn send(self, t: Result<T, E>) -> FutureSender<T, E> {
        FutureSender {
            sender: Some(self),
            data: Some(t),
            on_empty_token: None,
        }
    }
}

impl<T, E> Drop for Sender<T, E> {
    fn drop(&mut self) {
        self.inner.slot.on_empty(None, |slot, _none| {
            slot.try_produce(Message::Done).ok().unwrap();
        });
    }
}

impl<T, E> Future for FutureSender<T, E> {
    type Item = Sender<T, E>;
    type Error = SendError<T, E>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let data = self.data.take().expect("cannot poll FutureSender twice");
        let sender = self.sender.take().expect("cannot poll FutureSender twice");
        if let Some(token) = self.on_empty_token.take() {
            sender.inner.slot.cancel(token);
        }
        if sender.inner.receiver_gone.load(Ordering::SeqCst) {
            return Err(SendError(data))
        }
        match sender.inner.slot.try_produce(Message::Data(data)) {
            Ok(()) => Ok(Async::Ready(sender)),
            Err(e) => {
                let task = task::park();
                let token = sender.inner.slot.on_empty(None, move |_slot, _item| {
                    task.unpark();
                });
                self.on_empty_token = Some(token);
                self.data = Some(match e.into_inner() {
                    Message::Data(data) => data,
                    Message::Done => panic!(),
                });
                self.sender = Some(sender);
                Ok(Async::NotReady)
            }
        }
    }
}
<commit_msg>Add documentation<commit_after>use std::any::Any;
use std::error::Error;
use std::fmt;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};

use {Future, Poll, Async};
use slot::{Slot, Token};
use stream::Stream;
use task;

/// Creates an in-memory channel implementation of the `Stream` trait.
///
/// This method creates a concrete implementation of the `Stream` trait which
/// can be used to send values across threads in a streaming fashion. This
/// channel is unique in that it implements back pressure to ensure that the
/// sender never outpaces the receiver. The `Sender::send` method will only
/// allow sending one message and the next message can only be sent once the
/// first was consumed.
///
/// The `Receiver` returned implements the `Stream` trait and has access to any
/// number of the associated combinators for transforming the result.
pub fn channel<T, E>() -> (Sender<T, E>, Receiver<T, E>) {
    let inner = Arc::new(Inner {
        slot: Slot::new(None),
        receiver_gone: AtomicBool::new(false),
    });
    let sender = Sender {
        inner: inner.clone(),
    };
    let receiver = Receiver {
        inner: inner,
        on_full_token: None,
    };
    (sender, receiver)
}

/// The transmission end of a channel which is used to send values.
///
/// This is created by the `channel` method in the `stream` module.
pub struct Sender<T, E> {
    inner: Arc<Inner<T, E>>,
}

/// A future returned by the `Sender::send` method which will resolve to the
/// sender once it's available to send another message.
#[must_use = "futures do nothing unless polled"]
pub struct FutureSender<T, E> {
    sender: Option<Sender<T, E>>,
    data: Option<Result<T, E>>,
    on_empty_token: Option<Token>,
}

/// The receiving end of a channel which implements the `Stream` trait.
///
/// This is a concrete implementation of a stream which can be used to represent
/// a stream of values being computed elsewhere. This is created by the
/// `channel` method in the `stream` module.
#[must_use = "streams do nothing unless polled"]
pub struct Receiver<T, E> {
    inner: Arc<Inner<T, E>>,
    on_full_token: Option<Token>,
}

struct Inner<T, E> {
    slot: Slot<Message<Result<T, E>>>,
    receiver_gone: AtomicBool,
}

enum Message<T> {
    Data(T),
    Done,
}

/// Error type returned by `FutureSender` when the receiving end of a `channel` is dropped
pub struct SendError<T, E>(Result<T, E>);

impl<T, E> fmt::Debug for SendError<T, E> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_tuple("SendError")
            .field(&"...")
            .finish()
    }
}

impl<T, E> fmt::Display for SendError<T, E> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "send failed because receiver is gone")
    }
}

impl<T, E> Error for SendError<T, E>
    where T: Any, E: Any
{
    fn description(&self) -> &str {
        "send failed because receiver is gone"
    }
}

impl<T, E> Stream for Receiver<T, E> {
    type Item = T;
    type Error = E;

    fn poll(&mut self) -> Poll<Option<T>, E> {
        if let Some(token) = self.on_full_token.take() {
            self.inner.slot.cancel(token);
        }

        match self.inner.slot.try_consume() {
            Ok(Message::Data(Ok(e))) => Ok(Async::Ready(Some(e))),
            Ok(Message::Data(Err(e))) => Err(e),
            Ok(Message::Done) => Ok(Async::Ready(None)),
            Err(..) => {
                let task = task::park();
                self.on_full_token = Some(self.inner.slot.on_full(move |_| {
                    task.unpark();
                }));
                Ok(Async::NotReady)
            }
        }
    }
}

impl<T, E> Drop for Receiver<T, E> {
    fn drop(&mut self) {
        self.inner.receiver_gone.store(true, Ordering::SeqCst);
        if let Some(token) = self.on_full_token.take() {
            self.inner.slot.cancel(token);
        }
        self.inner.slot.on_full(|slot| {
            drop(slot.try_consume());
        });
    }
}

impl<T, E> Sender<T, E> {
    /// Sends a new value along this channel to the receiver.
    ///
    /// This method consumes the sender and returns a future which will resolve
    /// to the sender again when the value sent has been consumed.
    pub fn send(self, t: Result<T, E>) -> FutureSender<T, E> {
        FutureSender {
            sender: Some(self),
            data: Some(t),
            on_empty_token: None,
        }
    }
}

impl<T, E> Drop for Sender<T, E> {
    fn drop(&mut self) {
        self.inner.slot.on_empty(None, |slot, _none| {
            slot.try_produce(Message::Done).ok().unwrap();
        });
    }
}

impl<T, E> Future for FutureSender<T, E> {
    type Item = Sender<T, E>;
    type Error = SendError<T, E>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let data = self.data.take().expect("cannot poll FutureSender twice");
        let sender = self.sender.take().expect("cannot poll FutureSender twice");
        if let Some(token) = self.on_empty_token.take() {
            sender.inner.slot.cancel(token);
        }
        if sender.inner.receiver_gone.load(Ordering::SeqCst) {
            return Err(SendError(data))
        }
        match sender.inner.slot.try_produce(Message::Data(data)) {
            Ok(()) => Ok(Async::Ready(sender)),
            Err(e) => {
                let task = task::park();
                let token = sender.inner.slot.on_empty(None, move |_slot, _item| {
                    task.unpark();
                });
                self.on_empty_token = Some(token);
                self.data = Some(match e.into_inner() {
                    Message::Data(data) => data,
                    Message::Done => panic!(),
                });
                self.sender = Some(sender);
                Ok(Async::NotReady)
            }
        }
    }
}
<|endoftext|>


<commit_before>//! The main entry point for a simulation.

use std;

use serde_json;
use na;
use kiss3d;
use glfw;

use flate2::read::GzDecoder;
use kiss3d::window::Window;
use glfw::{WindowEvent,Key};

use std::path::Path;
use std::fs::File;
use std::f32::consts::PI;

use timer::Timer;
use misc;
use palette::{Color,Palette};
use objects::{Frame,ObjectTracker};

/// The configuration options for a Parviewer instance.
#[derive(Debug, RustcDecodable, RustcEncodable, Serialize, Deserialize)]
pub struct Config {
    /// Pitch of the camera, in degrees
    pub pitch : f32,
    /// Yaw of the camera, in degrees
    pub yaw : f32,
    /// Field-of-view range of the camera, in degrees
    pub fov : f32,
    /// Distance of the camera from the origin
    pub distance : f32,
    /// Window width
    pub width : u32,
    /// Window height
    pub height : u32,
    /// How long to pause before looping. None indicates no looping.
    pub pauseloop : Option<f32>,
    /// framerate limit
    pub framerate : f32,
}

/// Open a `json` or `json.gz` file, and deserialize it into a `Vec<Frame>`
pub fn open_file(path : &Path) -> Result<Vec<Frame>, serde_json::error::Error> {
    let mut buf : std::io::BufReader<File> = std::io::BufReader::new(try!(File::open(path)));
    // let f = try!(File::open(path));

    //~ let coded = json::from_reader(&mut buf).unwrap();
    //~ let mut decoder =json::Decoder::new(coded);
    //~ let frames: Vec<Frame> = Decodable::decode(&mut decoder).unwrap();

    let ext : Option<&str> = path.extension().and_then(|s| {s.to_str()});

    if ext == Some("gz") {
        println!("gz ext!");
    }

    let coded_opt = match ext {
        Some("gz") => {
            let mut gzbuf = try!(GzDecoder::new(buf));
            serde_json::de::from_reader(&mut gzbuf)
        },
        _ => {
            serde_json::de::from_reader(&mut buf)
            }
    };

    coded_opt
}

/// The main entry point,maintaining a window, a Config, objects, etc.
pub struct Parviewer {
    config : Config,
    frames : Vec<Frame>,
    /// Palette
    pub palette : Palette,
    /// Track where we are
    pub timer : Timer,
    /// kiss3d Window
    pub window : Window,
    /// Camera
    pub camera : kiss3d::camera::ArcBall,
    nodes : ObjectTracker,
    font : std::rc::Rc<kiss3d::text::Font>
}

impl Parviewer {
    /// Create a new Parviewer instance from a give Config
    pub fn new(frames : Vec<Frame>, palette : Palette, config : Config)
                -> Result<Parviewer, Box<std::error::Error>> {

        // TODO: this is also a configuration option
        let title : String = format!("Parviewer");
        let width : u32 = config.width;
        let height : u32 = config.height;
        let mut window = Window::new_with_size(&*title, width, height);
        // TODO: cube configuration
        let _ = misc::draw_cube(&mut window);

        let eye              = na::Pnt3::new(0.0f32, 0.0, config.distance);
        let at               = na::orig();
        let mut arc_ball     = kiss3d::camera::ArcBall::new_with_frustrum(config.fov * PI / 180., 0.1, 1024.0, eye, at);

        arc_ball.set_yaw(config.yaw * PI / 180.);
        arc_ball.set_pitch(config.pitch * PI / 180.);

        //window.set_background_color(1.0, 1.0, 1.0);
        window.set_light(kiss3d::light::Light::StickToCamera);
        window.set_framerate_limit(Some(config.framerate as u64));

        let nodes = ObjectTracker::new(&mut window);

        // let mut capsule = window.add_capsule(0.25, 0.5);
        // // capsule.set_local_scale(1.0, 1.0, 1.0);
        //
        // let diam = 0.5;
        // let axnorm = 1.0;
        // let h = axnorm - diam;
        //
        // let mut capsule2 = window.add_capsule(0.5, h / diam);
        // capsule2.set_local_scale(diam, diam, diam);
        // capsule2.set_local_translation(na::Vec3::new(0.5, 0., 0.));

        // TODO: config?
        let dts_first = vec![1., 2., 3., 4., 6., 8., 12., 16., 24., 32., 48., 64., 96., 128.];
        let mut dts = dts_first.iter().rev().map(|n|{1./n}).collect::<Vec<f32>>();
        dts.extend(dts_first);
        dts.dedup();

        let mut timer = Timer::new(dts, Some(frames.len()));

        timer.loop_pause = config.pauseloop;
        timer.fps = config.framerate;

        let fontsize = 48;
        let font = misc::inconsolata(fontsize);

        Ok(Parviewer {
            config : config,
            frames : frames,
            palette : palette,
            timer : timer,
            window : window,
            nodes : nodes,
            camera : arc_ball,
            font : font
        })
    }

    /// View the current config.
    pub fn get_config(&self) -> &Config {
        &self.config
    }

    /// Borrow current frame
    pub fn get_frame(&self) -> &Frame {
        let ix = self.timer.get_index();
        &self.frames[ix]
    }

    /// Draw some text in the window, with coordinates in the window frame (i.e., 0 to 1).
    pub fn draw_text(&mut self, t: &str, x: f32, y: f32, color: Color) {
        let max_width = self.window.width() * 2.;
        // TODO: Figure out why the bottom is window.height() * 2.
        let max_height = self.window.height() * 2. - (self.font.height() as f32);
        let text_loc = na::Pnt2::new(x * max_width, y * max_height);
        let text_color = color.to_pnt3();

        self.window.draw_text(t, &text_loc, &self.font, &text_color);
    }

    /// Draw some text in the window, with coordinates in the window frame (i.e., 0 to 1).
    pub fn draw_frame_text(&mut self, x: f32, y: f32, color: Color) {
        let ix = self.timer.get_index();
        let frame = &self.frames[ix];
        if frame.text.len() > 0 {
            let max_width = self.window.width() * 2.;
            // TODO: Figure out why the bottom is window.height() * 2.
            let max_height = self.window.height() * 2. - (self.font.height() as f32);
            let text_loc = na::Pnt2::new(x * max_width, y * max_height);
            let text_color = color.to_pnt3();

            self.window.draw_text(&*frame.text, &text_loc, &self.font, &text_color);
        }
    }

    /// Standard key handling, called by run.
    pub fn handle_events(&mut self) {
        for mut event in self.window.events().iter() {
            match event.value {
                WindowEvent::Key(key, _, glfw::Action::Release, _) => {
                    // Default to inhibiting, although this can be overridden
                    let mut inhibit = true;
                    match key {
                        Key::Q => {
                            self.window.close();
                            return;
                        },
                        Key::Comma => {self.timer.slower();},
                        Key::Period => {self.timer.faster();},
                        Key::F => {self.timer.switch_direction();},
                        Key::Up => {
                            self.camera.set_pitch(PI/3.);
                            self.camera.set_yaw(PI/4.);
                        },
                        Key::Down => {
                            self.camera.set_pitch(PI/2.);
                            self.camera.set_yaw(0.);
                        },
                        Key::W => {
                            println!("yaw: {:6.2}, pitch: {:6.2}, distance: {:6.2}",
                                self.camera.yaw() * 180. / PI,
                                self.camera.pitch() * 180. / PI,
                                self.camera.dist()
                            );
                        },
                        Key::Num1 => {self.palette.toggle_partial(0);},
                        Key::Num2 => {self.palette.toggle_partial(1);},
                        Key::Num3 => {self.palette.toggle_partial(2);},
                        Key::Num4 => {self.palette.toggle_partial(3);},
                        Key::Num5 => {self.palette.toggle_partial(4);},
                        Key::Num6 => {self.palette.toggle_partial(5);},
                        Key::Num7 => {self.palette.toggle_partial(6);},
                        Key::Num8 => {self.palette.toggle_partial(7);},
                        Key::Num9 => {self.palette.set_all_partial(true);},
                        Key::Num0 => {self.palette.set_all_partial(false);},
                        code => {
                            println!("You released the key with code: {:?}", code);
                            inhibit = false;
                        }

                    }
                    event.inhibited = inhibit;
                },
                _ => {}
            }
        }
    }

    /// Start the whole running sequence.
    pub fn run<F>(&mut self, mut update: F)
            where F: FnMut(&mut Parviewer, bool) {
        {
            // Set it to the first position, and then return the borrow of `self` for
            // the render function to use
            let ref frame = self.frames[0];
            self.nodes.update(frame, &mut self.palette);
        }

        let mut lastframe : isize = 0;
        while self.window.render_with_camera(&mut self.camera) {
            self.timer.incr();
            let ix = self.timer.get_index();

            let new_index = lastframe != (ix as isize);
            if new_index {
                let ref frame = self.frames[ix];
                self.nodes.update(frame, &mut self.palette);
                lastframe = ix as isize;
            }

            update(self, new_index);

            self.handle_events();
        };
    }
}
<commit_msg>Added pause option<commit_after>//! The main entry point for a simulation.

use std;

use serde_json;
use na;
use kiss3d;
use glfw;

use flate2::read::GzDecoder;
use kiss3d::window::Window;
use glfw::{WindowEvent,Key};

use std::path::Path;
use std::fs::File;
use std::f32::consts::PI;

use timer::Timer;
use misc;
use palette::{Color,Palette};
use objects::{Frame,ObjectTracker};

/// The configuration options for a Parviewer instance.
#[derive(Debug, RustcDecodable, RustcEncodable, Serialize, Deserialize)]
pub struct Config {
    /// Pitch of the camera, in degrees
    pub pitch : f32,
    /// Yaw of the camera, in degrees
    pub yaw : f32,
    /// Field-of-view range of the camera, in degrees
    pub fov : f32,
    /// Distance of the camera from the origin
    pub distance : f32,
    /// Window width
    pub width : u32,
    /// Window height
    pub height : u32,
    /// How long to pause before looping. None indicates no looping.
    pub pauseloop : Option<f32>,
    /// framerate limit
    pub framerate : f32,
}

/// Open a `json` or `json.gz` file, and deserialize it into a `Vec<Frame>`
pub fn open_file(path : &Path) -> Result<Vec<Frame>, serde_json::error::Error> {
    let mut buf : std::io::BufReader<File> = std::io::BufReader::new(try!(File::open(path)));
    // let f = try!(File::open(path));

    //~ let coded = json::from_reader(&mut buf).unwrap();
    //~ let mut decoder =json::Decoder::new(coded);
    //~ let frames: Vec<Frame> = Decodable::decode(&mut decoder).unwrap();

    let ext : Option<&str> = path.extension().and_then(|s| {s.to_str()});

    if ext == Some("gz") {
        println!("gz ext!");
    }

    let coded_opt = match ext {
        Some("gz") => {
            let mut gzbuf = try!(GzDecoder::new(buf));
            serde_json::de::from_reader(&mut gzbuf)
        },
        _ => {
            serde_json::de::from_reader(&mut buf)
            }
    };

    coded_opt
}

/// The main entry point,maintaining a window, a Config, objects, etc.
pub struct Parviewer {
    config : Config,
    frames : Vec<Frame>,
    /// Palette
    pub palette : Palette,
    /// Track where we are
    pub timer : Timer,
    /// kiss3d Window
    pub window : Window,
    /// Camera
    pub camera : kiss3d::camera::ArcBall,
    nodes : ObjectTracker,
    font : std::rc::Rc<kiss3d::text::Font>,

    /// Do not increment timer when paused
    pub paused : bool
}

impl Parviewer {
    /// Create a new Parviewer instance from a give Config
    pub fn new(frames : Vec<Frame>, palette : Palette, config : Config)
                -> Result<Parviewer, Box<std::error::Error>> {

        // TODO: this is also a configuration option
        let title : String = format!("Parviewer");
        let width : u32 = config.width;
        let height : u32 = config.height;
        let mut window = Window::new_with_size(&*title, width, height);
        // TODO: cube configuration
        let _ = misc::draw_cube(&mut window);

        let eye              = na::Pnt3::new(0.0f32, 0.0, config.distance);
        let at               = na::orig();
        let mut arc_ball     = kiss3d::camera::ArcBall::new_with_frustrum(config.fov * PI / 180., 0.1, 1024.0, eye, at);

        arc_ball.set_yaw(config.yaw * PI / 180.);
        arc_ball.set_pitch(config.pitch * PI / 180.);

        //window.set_background_color(1.0, 1.0, 1.0);
        window.set_light(kiss3d::light::Light::StickToCamera);
        window.set_framerate_limit(Some(config.framerate as u64));

        let nodes = ObjectTracker::new(&mut window);

        // let mut capsule = window.add_capsule(0.25, 0.5);
        // // capsule.set_local_scale(1.0, 1.0, 1.0);
        //
        // let diam = 0.5;
        // let axnorm = 1.0;
        // let h = axnorm - diam;
        //
        // let mut capsule2 = window.add_capsule(0.5, h / diam);
        // capsule2.set_local_scale(diam, diam, diam);
        // capsule2.set_local_translation(na::Vec3::new(0.5, 0., 0.));

        // TODO: config?
        let dts_first = vec![1., 2., 3., 4., 6., 8., 12., 16., 24., 32., 48., 64., 96., 128.];
        let mut dts = dts_first.iter().rev().map(|n|{1./n}).collect::<Vec<f32>>();
        dts.extend(dts_first);
        dts.dedup();

        let mut timer = Timer::new(dts, Some(frames.len()));

        timer.loop_pause = config.pauseloop;
        timer.fps = config.framerate;

        let fontsize = 48;
        let font = misc::inconsolata(fontsize);

        Ok(Parviewer {
            config : config,
            frames : frames,
            palette : palette,
            timer : timer,
            window : window,
            nodes : nodes,
            camera : arc_ball,
            font : font,
            paused : false
        })
    }

    /// View the current config.
    pub fn get_config(&self) -> &Config {
        &self.config
    }

    /// Borrow current frame
    pub fn get_frame(&self) -> &Frame {
        let ix = self.timer.get_index();
        &self.frames[ix]
    }

    /// Draw some text in the window, with coordinates in the window frame (i.e., 0 to 1).
    pub fn draw_text(&mut self, t: &str, x: f32, y: f32, color: Color) {
        let max_width = self.window.width() * 2.;
        // TODO: Figure out why the bottom is window.height() * 2.
        let max_height = self.window.height() * 2. - (self.font.height() as f32);
        let text_loc = na::Pnt2::new(x * max_width, y * max_height);
        let text_color = color.to_pnt3();

        self.window.draw_text(t, &text_loc, &self.font, &text_color);
    }

    /// Draw some text in the window, with coordinates in the window frame (i.e., 0 to 1).
    pub fn draw_frame_text(&mut self, x: f32, y: f32, color: Color) {
        let ix = self.timer.get_index();
        let frame = &self.frames[ix];
        if frame.text.len() > 0 {
            let max_width = self.window.width() * 2.;
            // TODO: Figure out why the bottom is window.height() * 2.
            let max_height = self.window.height() * 2. - (self.font.height() as f32);
            let text_loc = na::Pnt2::new(x * max_width, y * max_height);
            let text_color = color.to_pnt3();

            self.window.draw_text(&*frame.text, &text_loc, &self.font, &text_color);
        }
    }

    /// Standard key handling, called by run.
    pub fn handle_events(&mut self) {
        for mut event in self.window.events().iter() {
            match event.value {
                WindowEvent::Key(key, _, glfw::Action::Release, _) => {
                    // Default to inhibiting, although this can be overridden
                    let mut inhibit = true;
                    match key {
                        Key::Q => {
                            self.window.close();
                            return;
                        },
                        Key::Comma => {self.timer.slower();},
                        Key::Period => {self.timer.faster();},
                        Key::F => {self.timer.switch_direction();},
                        Key::Up => {
                            self.camera.set_pitch(PI/3.);
                            self.camera.set_yaw(PI/4.);
                        },
                        Key::Down => {
                            self.camera.set_pitch(PI/2.);
                            self.camera.set_yaw(0.);
                        },
                        Key::W => {
                            println!("yaw: {:6.2}, pitch: {:6.2}, distance: {:6.2}",
                                self.camera.yaw() * 180. / PI,
                                self.camera.pitch() * 180. / PI,
                                self.camera.dist()
                            );
                        },
                        Key::Space => {
                            self.paused = !self.paused;
                        },
                        Key::Num1 => {self.palette.toggle_partial(0);},
                        Key::Num2 => {self.palette.toggle_partial(1);},
                        Key::Num3 => {self.palette.toggle_partial(2);},
                        Key::Num4 => {self.palette.toggle_partial(3);},
                        Key::Num5 => {self.palette.toggle_partial(4);},
                        Key::Num6 => {self.palette.toggle_partial(5);},
                        Key::Num7 => {self.palette.toggle_partial(6);},
                        Key::Num8 => {self.palette.toggle_partial(7);},
                        Key::Num9 => {self.palette.set_all_partial(true);},
                        Key::Num0 => {self.palette.set_all_partial(false);},
                        code => {
                            println!("You released the key with code: {:?}", code);
                            inhibit = false;
                        }

                    }
                    event.inhibited = inhibit;
                },
                _ => {}
            }
        }
    }

    /// Start the whole running sequence.
    pub fn run<F>(&mut self, mut update: F)
            where F: FnMut(&mut Parviewer, bool) {
        {
            // Set it to the first position, and then return the borrow of `self` for
            // the render function to use
            let ref frame = self.frames[0];
            self.nodes.update(frame, &mut self.palette);
        }

        let mut lastframe : isize = 0;
        while self.window.render_with_camera(&mut self.camera) {
            if !self.paused {self.timer.incr();}
            let ix = self.timer.get_index();

            let new_index = lastframe != (ix as isize);
            if new_index {
                let ref frame = self.frames[ix];
                self.nodes.update(frame, &mut self.palette);
                lastframe = ix as isize;
            }

            update(self, new_index);

            self.handle_events();
        };
    }
}
<|endoftext|>