<commit_before>use super::RdxSort;

use core::ptr;

use std::cmp;
use std::mem;

/// Generic Radix Sort implementation
///
/// Works by splitting the work in rounds. During every round, the data is sorted into buckets and
/// is then collected again. Rounds are count from `0` to (exclusive) `cfg_nrounds()`.
///
/// The number of buckets is fixed for all rounds. That does not mean that the template has to use
/// all of them, since unused buckets are just empty and have no effect on the collected results.
/// Same hold for the number of rounds. Over-booking one or both of them wastes resources of
/// course.
///
/// **WARNING: The result returned from `get_bucket()` is not checked. Wrong implementations may
/// crash the program, or destroy the world, or both!!!**
pub trait RdxSortTemplate {
    /// Sets the number of buckets used by the generic implementation.
    fn cfg_nbuckets() -> usize;

    /// Sets the number of rounds scheduled by the generic implementation.
    fn cfg_nrounds() -> usize;

    /// Returns the bucket, depending on the round.
    ///
    /// This should respect the radix, e.g.:
    ///
    /// - if the number of buckets is `2` and the type is an unsigned integer, then the result is
    ///   the bit starting with the least significant one.
    /// - if the number of buckets is `8` and the type is an unsigned integer, then the result is
    ///   the byte starting with the least significant one.
    ///
    /// **Never** return a bucker greater or equal the number of buckets. See warning above!
    fn get_bucket(&self, round: usize) -> usize;

    /// Describes the fact that the content of a bucket should be copied back in reverse order
    /// after a certain round.
    fn reverse(round: usize, bucket: usize) -> bool;
}

/// Implements `t1` as alias of `t2`, e.g `usize = u64` on platforms that have 64 bit pointers.
#[macro_export]
macro_rules! rdxsort_template_alias {
    ($t1:ty = $t2:ty) => {
        impl RdxSortTemplate for $t1 {
            #[inline]
            fn cfg_nbuckets() -> usize {
                <$t2 as RdxSortTemplate>::cfg_nbuckets()
            }

            #[inline]
            fn cfg_nrounds() -> usize {
                <$t2 as RdxSortTemplate>::cfg_nrounds()
            }

            #[inline]
            fn get_bucket(&self, round: usize) -> usize {
                (*self as $t2).get_bucket(round)
            }

            #[inline]
            fn reverse(round: usize, bucket: usize) -> bool {
                <$t2 as RdxSortTemplate>::reverse(round, bucket)
            }
        }
    }
}

#[inline]
fn helper_bucket<T, I>(buckets_b: &mut Vec<Vec<T>>, iter: I, cfg_nbuckets: usize, round: usize)
    where T: RdxSortTemplate,
          I: Iterator<Item = T>
{
    for x in iter {
        let b = x.get_bucket(round);
        assert!(b < cfg_nbuckets,
                "Your RdxSortTemplate implementation returns a bucket >= cfg_nbuckets()!");
        unsafe {
            buckets_b.get_unchecked_mut(b).push(x);
        }
    }
}

impl<T> RdxSort for [T] where T: RdxSortTemplate + Clone
{
    fn rdxsort(&mut self) {
        // config
        let cfg_nbuckets = T::cfg_nbuckets();
        let cfg_nrounds = T::cfg_nrounds();

        // early return
        if cfg_nrounds == 0 {
            return;
        }

        let n = self.len();
        let presize = cmp::max(16, (n << 2) / cfg_nbuckets);  // TODO: justify the presize value
        let mut buckets_a: Vec<Vec<T>> = Vec::with_capacity(cfg_nbuckets);
        let mut buckets_b: Vec<Vec<T>> = Vec::with_capacity(cfg_nbuckets);
        for _ in 0..cfg_nbuckets {
            buckets_a.push(Vec::with_capacity(presize));
            buckets_b.push(Vec::with_capacity(presize));
        }

        helper_bucket(&mut buckets_a, self.iter().cloned(), cfg_nbuckets, 0);

        for round in 1..cfg_nrounds {
            for bucket in &mut buckets_b {
                bucket.clear();
            }
            for (i, bucket) in buckets_a.iter().enumerate() {
                if T::reverse(round - 1, i) {
                    helper_bucket(&mut buckets_b,
                                  bucket.iter().rev().cloned(),
                                  cfg_nbuckets,
                                  round);
                } else {
                    helper_bucket(&mut buckets_b, bucket.iter().cloned(), cfg_nbuckets, round);
                }
            }
            mem::swap(&mut buckets_a, &mut buckets_b);
        }

        let mut pos = 0;
        for (i, bucket) in buckets_a.iter_mut().enumerate() {
            assert!(pos + bucket.len() <= self.len(),
                    "bug: a buckets got oversized");

            if T::reverse(cfg_nrounds - 1, i) {
                for x in bucket.iter().rev().cloned() {
                    unsafe {
                        *self.get_unchecked_mut(pos) = x;
                    }
                    pos += 1;
                }
            } else {
                unsafe {
                    ptr::copy_nonoverlapping(bucket.as_ptr(),
                                             self.get_unchecked_mut(pos),
                                             bucket.len());
                }
                pos += bucket.len();
            }
        }

        assert!(pos == self.len(), "bug: bucket size does not sum up");
    }
}

impl<T> RdxSort for Vec<T> where [T]: RdxSort
{
    fn rdxsort(&mut self) {
        self.as_mut_slice().rdxsort();
    }
}
<commit_msg>missing  dot<commit_after>use super::RdxSort;

use core::ptr;

use std::cmp;
use std::mem;

/// Generic Radix Sort implementation
///
/// Works by splitting the work in rounds. During every round, the data is sorted into buckets and
/// is then collected again. Rounds are count from `0` to (exclusive) `cfg_nrounds()`.
///
/// The number of buckets is fixed for all rounds. That does not mean that the template has to use
/// all of them, since unused buckets are just empty and have no effect on the collected results.
/// Same hold for the number of rounds. Over-booking one or both of them wastes resources of
/// course.
///
/// **WARNING: The result returned from `get_bucket()` is not checked. Wrong implementations may
/// crash the program, or destroy the world, or both!!!**
pub trait RdxSortTemplate {
    /// Sets the number of buckets used by the generic implementation.
    fn cfg_nbuckets() -> usize;

    /// Sets the number of rounds scheduled by the generic implementation.
    fn cfg_nrounds() -> usize;

    /// Returns the bucket, depending on the round.
    ///
    /// This should respect the radix, e.g.:
    ///
    /// - if the number of buckets is `2` and the type is an unsigned integer, then the result is
    ///   the bit starting with the least significant one.
    /// - if the number of buckets is `8` and the type is an unsigned integer, then the result is
    ///   the byte starting with the least significant one.
    ///
    /// **Never** return a bucker greater or equal the number of buckets. See warning above!
    fn get_bucket(&self, round: usize) -> usize;

    /// Describes the fact that the content of a bucket should be copied back in reverse order
    /// after a certain round.
    fn reverse(round: usize, bucket: usize) -> bool;
}

/// Implements `t1` as alias of `t2`, e.g. `usize = u64` on platforms that have 64 bit pointers.
#[macro_export]
macro_rules! rdxsort_template_alias {
    ($t1:ty = $t2:ty) => {
        impl RdxSortTemplate for $t1 {
            #[inline]
            fn cfg_nbuckets() -> usize {
                <$t2 as RdxSortTemplate>::cfg_nbuckets()
            }

            #[inline]
            fn cfg_nrounds() -> usize {
                <$t2 as RdxSortTemplate>::cfg_nrounds()
            }

            #[inline]
            fn get_bucket(&self, round: usize) -> usize {
                (*self as $t2).get_bucket(round)
            }

            #[inline]
            fn reverse(round: usize, bucket: usize) -> bool {
                <$t2 as RdxSortTemplate>::reverse(round, bucket)
            }
        }
    }
}

#[inline]
fn helper_bucket<T, I>(buckets_b: &mut Vec<Vec<T>>, iter: I, cfg_nbuckets: usize, round: usize)
    where T: RdxSortTemplate,
          I: Iterator<Item = T>
{
    for x in iter {
        let b = x.get_bucket(round);
        assert!(b < cfg_nbuckets,
                "Your RdxSortTemplate implementation returns a bucket >= cfg_nbuckets()!");
        unsafe {
            buckets_b.get_unchecked_mut(b).push(x);
        }
    }
}

impl<T> RdxSort for [T] where T: RdxSortTemplate + Clone
{
    fn rdxsort(&mut self) {
        // config
        let cfg_nbuckets = T::cfg_nbuckets();
        let cfg_nrounds = T::cfg_nrounds();

        // early return
        if cfg_nrounds == 0 {
            return;
        }

        let n = self.len();
        let presize = cmp::max(16, (n << 2) / cfg_nbuckets);  // TODO: justify the presize value
        let mut buckets_a: Vec<Vec<T>> = Vec::with_capacity(cfg_nbuckets);
        let mut buckets_b: Vec<Vec<T>> = Vec::with_capacity(cfg_nbuckets);
        for _ in 0..cfg_nbuckets {
            buckets_a.push(Vec::with_capacity(presize));
            buckets_b.push(Vec::with_capacity(presize));
        }

        helper_bucket(&mut buckets_a, self.iter().cloned(), cfg_nbuckets, 0);

        for round in 1..cfg_nrounds {
            for bucket in &mut buckets_b {
                bucket.clear();
            }
            for (i, bucket) in buckets_a.iter().enumerate() {
                if T::reverse(round - 1, i) {
                    helper_bucket(&mut buckets_b,
                                  bucket.iter().rev().cloned(),
                                  cfg_nbuckets,
                                  round);
                } else {
                    helper_bucket(&mut buckets_b, bucket.iter().cloned(), cfg_nbuckets, round);
                }
            }
            mem::swap(&mut buckets_a, &mut buckets_b);
        }

        let mut pos = 0;
        for (i, bucket) in buckets_a.iter_mut().enumerate() {
            assert!(pos + bucket.len() <= self.len(),
                    "bug: a buckets got oversized");

            if T::reverse(cfg_nrounds - 1, i) {
                for x in bucket.iter().rev().cloned() {
                    unsafe {
                        *self.get_unchecked_mut(pos) = x;
                    }
                    pos += 1;
                }
            } else {
                unsafe {
                    ptr::copy_nonoverlapping(bucket.as_ptr(),
                                             self.get_unchecked_mut(pos),
                                             bucket.len());
                }
                pos += bucket.len();
            }
        }

        assert!(pos == self.len(), "bug: bucket size does not sum up");
    }
}

impl<T> RdxSort for Vec<T> where [T]: RdxSort
{
    fn rdxsort(&mut self) {
        self.as_mut_slice().rdxsort();
    }
}
<|endoftext|>


<commit_before>use std::path::PathBuf;

use xshell::pushd;

use crate::{cmd, Metadata, Result};

const MSRV: &str = "1.45";

/// Task to run CI tests.
pub struct CiTask {
    /// Which version of Rust to test against.
    version: Option<String>,

    /// The root of the workspace.
    project_root: PathBuf,
}

impl CiTask {
    pub(crate) fn new(version: Option<String>) -> Result<Self> {
        let project_root = Metadata::load()?.workspace_root;
        Ok(Self { version, project_root })
    }

    pub(crate) fn run(self) -> Result<()> {
        let _p = xshell::pushd(&self.project_root)?;

        match self.version.as_deref() {
            Some("msrv") => self.build_msrv()?,
            Some("stable") => self.build_stable()?,
            Some("nightly") => self.build_nightly()?,
            Some(_) => return Err("Wrong Rust version specified.".into()),
            None => {
                self.build_msrv().and(self.build_stable()).and(self.build_nightly())?;
            }
        }

        Ok(())
    }

    fn build_msrv(&self) -> xshell::Result<()> {
        let _p = pushd("ruma")?;
        cmd!("rustup run {MSRV} cargo build --features full --quiet").run()
    }

    fn build_stable(&self) -> xshell::Result<()> {
        vec![
            cmd!("rustup run stable cargo test --workspace --quiet").run(),
            cmd!("rustup run stable cargo test -p ruma-identifiers --no-default-features --quiet")
                .run(),
            cmd!("rustup run stable cargo test -p ruma-identifiers --all-features --quiet").run(),
            cmd!("rustup run stable cargo test -p ruma-client-api --all-features --quiet").run(),
            cmd!("rustup run stable cargo check -p ruma-client --no-default-features --quiet")
                .run(),
            cmd!("rustup run stable cargo check -p ruma-client --all-features --quiet").run(),
        ]
        .into_iter()
        .collect()
    }

    fn build_nightly(&self) -> xshell::Result<()> {
        vec![
            cmd!("rustup run nightly cargo fmt -- --check").run(),
            cmd!(
                "rustup run nightly cargo clippy -p ruma
                    --all-targets --all-features --quiet -- -D warnings"
            )
            .run(),
            cmd!(
                "rustup run nightly cargo clippy -p ruma-client
                    --all-targets --quiet -- -D warnings"
            )
            .run(),
        ]
        .into_iter()
        .collect()
    }
}
<commit_msg>ci: Fix msrv check<commit_after>use std::path::PathBuf;

use xshell::pushd;

use crate::{cmd, Metadata, Result};

const MSRV: &str = "1.45";

/// Task to run CI tests.
pub struct CiTask {
    /// Which version of Rust to test against.
    version: Option<String>,

    /// The root of the workspace.
    project_root: PathBuf,
}

impl CiTask {
    pub(crate) fn new(version: Option<String>) -> Result<Self> {
        let project_root = Metadata::load()?.workspace_root;
        Ok(Self { version, project_root })
    }

    pub(crate) fn run(self) -> Result<()> {
        let _p = pushd(&self.project_root)?;

        match self.version.as_deref() {
            Some("msrv") => self.build_msrv()?,
            Some("stable") => self.build_stable()?,
            Some("nightly") => self.build_nightly()?,
            Some(_) => return Err("Wrong Rust version specified.".into()),
            None => {
                self.build_msrv().and(self.build_stable()).and(self.build_nightly())?;
            }
        }

        Ok(())
    }

    fn build_msrv(&self) -> xshell::Result<()> {
        let _p = pushd("crates/ruma")?;
        cmd!("rustup run {MSRV} cargo build --features full --quiet").run()
    }

    fn build_stable(&self) -> xshell::Result<()> {
        vec![
            cmd!("rustup run stable cargo test --workspace --quiet").run(),
            cmd!("rustup run stable cargo test -p ruma-identifiers --no-default-features --quiet")
                .run(),
            cmd!("rustup run stable cargo test -p ruma-identifiers --all-features --quiet").run(),
            cmd!("rustup run stable cargo test -p ruma-client-api --all-features --quiet").run(),
            cmd!("rustup run stable cargo check -p ruma-client --no-default-features --quiet")
                .run(),
            cmd!("rustup run stable cargo check -p ruma-client --all-features --quiet").run(),
        ]
        .into_iter()
        .collect()
    }

    fn build_nightly(&self) -> xshell::Result<()> {
        vec![
            cmd!("rustup run nightly cargo fmt -- --check").run(),
            cmd!(
                "rustup run nightly cargo clippy -p ruma
                    --all-targets --all-features --quiet -- -D warnings"
            )
            .run(),
            cmd!(
                "rustup run nightly cargo clippy -p ruma-client
                    --all-targets --quiet -- -D warnings"
            )
            .run(),
        ]
        .into_iter()
        .collect()
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::os::unix::io::{AsRawFd, FromRawFd};
use std::fs::File;

use libc::{c_int, pid_t};
use libc::{getpgrp, kill, ioctl};
use nix;
use nix::errno::Errno;
use nix::unistd::{isatty, dup};

mod ffi {
    use libc::{c_int};

    pub static TIOCSPGRP: c_int = 0x5410;
    pub static TIOCGPGRP: c_int = 0x540F;
}

#[derive(Debug)]
pub struct TtyGuard {
    tty: Option<File>,
    my_pgrp: pid_t,
}

impl TtyGuard {
    pub fn take(&mut self) -> Result<(), io::Error> {
        let &mut TtyGuard { ref tty, my_pgrp, .. } = self;
        tty.as_ref().map_or(Ok(()), |f| {
            unsafe { give_tty_to(f.as_raw_fd(), my_pgrp) }?;
            Ok(())
        })
    }
    pub fn give(&mut self, pid: pid_t) -> Result<(), io::Error> {
        let &mut TtyGuard { ref tty, .. } = self;
        tty.as_ref().map_or(Ok(()), |f| {
            unsafe { give_tty_to(f.as_raw_fd(), pid) }?;
            Ok(())
        })
    }
    /// Check terminal and take it if it's not owned
    pub fn check(&mut self) -> Result<(), io::Error> {
        let &mut TtyGuard { ref tty, my_pgrp, .. } = self;
        tty.as_ref().map_or(Ok(()), |f| {
            let tty_owner_grp = unsafe { get_group(f.as_raw_fd()) }?;
            if tty_owner_grp != 0 {
                let kill_res = unsafe { kill(tty_owner_grp, 0) };
                if kill_res < 0 && Errno::last() == Errno::ESRCH {
                    unsafe { give_tty_to(f.as_raw_fd(), my_pgrp) }?;
                }
            }
            Ok(())
        })
    }
    pub fn new() -> Result<TtyGuard, nix::Error> {
        let my_pgrp = unsafe { getpgrp() };
        if my_pgrp != 0 {
            // my_pgrp can be zero if group owner is outside of the PID ns
            for i in 0..3 {
                if isatty(i).unwrap_or(false) {
                    // after we determined which FD is a TTY there is no way
                    // to ensure that the same fd will be at the same number
                    // So we duplicate it:
                    let guard = TtyGuard {
                        tty: Some(unsafe { File::from_raw_fd(dup(i)?) }),
                        my_pgrp: unsafe { getpgrp() },
                    };
                    return Ok(guard)
                }
            }
        }
        Ok(TtyGuard {
            tty: None,
            my_pgrp: my_pgrp,
        })
    }
}

impl Drop for TtyGuard {
    fn drop(&mut self) {
        self.take().ok();
    }
}

// dealing with file descriptors is always unsafe
unsafe fn get_group(fd: c_int)
    -> Result<pid_t, io::Error>
{
    let mut pgrp = 0;
    let res = ioctl(fd, ffi::TIOCGPGRP, &mut pgrp);
    if res == 0 {
        Ok(pgrp)
    } else {
        Err(io::Error::last_os_error())
    }
}

// dealing with file descriptors is always unsafe
unsafe fn give_tty_to(fd: c_int, pgrp: pid_t) -> Result<(), io::Error> {
    let res = ioctl(fd, ffi::TIOCSPGRP, &pgrp);
    if res == 0 {
        Ok(())
    } else {
        Err(io::Error::last_os_error())
    }
}
<commit_msg>Now compiles for gnu libc (still doesn't work though)<commit_after>use std::io;
use std::os::unix::io::{AsRawFd, FromRawFd};
use std::fs::File;

use libc::{c_int, pid_t};
use libc::{getpgrp, kill, ioctl};
use nix;
use nix::errno::Errno;
use nix::unistd::{isatty, dup};

#[cfg(target_env="musl")]
mod ffi {
    use libc::{c_int};

    pub static TIOCSPGRP: c_int = 0x5410;
    pub static TIOCGPGRP: c_int = 0x540F;
}

#[cfg(target_env="gnu")]
mod ffi {
    pub static TIOCSPGRP: u64 = 0x5410;
    pub static TIOCGPGRP: u64 = 0x540F;
}

#[derive(Debug)]
pub struct TtyGuard {
    tty: Option<File>,
    my_pgrp: pid_t,
}

impl TtyGuard {
    pub fn take(&mut self) -> Result<(), io::Error> {
        let &mut TtyGuard { ref tty, my_pgrp, .. } = self;
        tty.as_ref().map_or(Ok(()), |f| {
            unsafe { give_tty_to(f.as_raw_fd(), my_pgrp) }?;
            Ok(())
        })
    }
    pub fn give(&mut self, pid: pid_t) -> Result<(), io::Error> {
        let &mut TtyGuard { ref tty, .. } = self;
        tty.as_ref().map_or(Ok(()), |f| {
            unsafe { give_tty_to(f.as_raw_fd(), pid) }?;
            Ok(())
        })
    }
    /// Check terminal and take it if it's not owned
    pub fn check(&mut self) -> Result<(), io::Error> {
        let &mut TtyGuard { ref tty, my_pgrp, .. } = self;
        tty.as_ref().map_or(Ok(()), |f| {
            let tty_owner_grp = unsafe { get_group(f.as_raw_fd()) }?;
            if tty_owner_grp != 0 {
                let kill_res = unsafe { kill(tty_owner_grp, 0) };
                if kill_res < 0 && Errno::last() == Errno::ESRCH {
                    unsafe { give_tty_to(f.as_raw_fd(), my_pgrp) }?;
                }
            }
            Ok(())
        })
    }
    pub fn new() -> Result<TtyGuard, nix::Error> {
        let my_pgrp = unsafe { getpgrp() };
        if my_pgrp != 0 {
            // my_pgrp can be zero if group owner is outside of the PID ns
            for i in 0..3 {
                if isatty(i).unwrap_or(false) {
                    // after we determined which FD is a TTY there is no way
                    // to ensure that the same fd will be at the same number
                    // So we duplicate it:
                    let guard = TtyGuard {
                        tty: Some(unsafe { File::from_raw_fd(dup(i)?) }),
                        my_pgrp: unsafe { getpgrp() },
                    };
                    return Ok(guard)
                }
            }
        }
        Ok(TtyGuard {
            tty: None,
            my_pgrp: my_pgrp,
        })
    }
}

impl Drop for TtyGuard {
    fn drop(&mut self) {
        self.take().ok();
    }
}

// dealing with file descriptors is always unsafe
unsafe fn get_group(fd: c_int)
    -> Result<pid_t, io::Error>
{
    let mut pgrp = 0;
    let res = ioctl(fd, ffi::TIOCGPGRP, &mut pgrp);
    if res == 0 {
        Ok(pgrp)
    } else {
        Err(io::Error::last_os_error())
    }
}

// dealing with file descriptors is always unsafe
unsafe fn give_tty_to(fd: c_int, pgrp: pid_t) -> Result<(), io::Error> {
    let res = ioctl(fd, ffi::TIOCSPGRP, &pgrp);
    if res == 0 {
        Ok(())
    } else {
        Err(io::Error::last_os_error())
    }
}
<|endoftext|>


<commit_before>use crate::term2;
use rustup::dist::Notification as In;
use rustup::utils::tty;
use rustup::utils::Notification as Un;
use rustup::Notification;
use std::collections::VecDeque;
use std::fmt;
use std::io::Write;
use term::Terminal;
use time::precise_time_s;

/// Keep track of this many past download amounts
const DOWNLOAD_TRACK_COUNT: usize = 5;

/// Tracks download progress and displays information about it to a terminal.
pub struct DownloadTracker {
    /// Content-Length of the to-be downloaded object.
    content_len: Option<usize>,
    /// Total data downloaded in bytes.
    total_downloaded: usize,
    /// Data downloaded this second.
    downloaded_this_sec: usize,
    /// Keeps track of amount of data downloaded every last few secs.
    /// Used for averaging the download speed. NB: This does not necessarily
    /// represent adjacent seconds; thus it may not show the average at all.
    downloaded_last_few_secs: VecDeque<usize>,
    /// Time stamp of the last second
    last_sec: Option<f64>,
    /// Time stamp of the start of the download
    start_sec: f64,
    /// The terminal we write the information to.
    /// XXX: Could be a term trait, but with #1818 on the horizon that
    ///      is a pointless change to make - better to let that transition
    ///      happen and take stock after that.
    term: term2::StdoutTerminal,
    /// Whether we displayed progress for the download or not.
    ///
    /// If the download is quick enough, we don't have time to
    /// display the progress info.
    /// In that case, we do not want to do some cleanup stuff we normally do.
    ///
    /// If we have displayed progress, this is the number of characters we
    /// rendered, so we can erase it cleanly.
    displayed_charcount: Option<usize>,
    /// What units to show progress in
    units: Vec<String>,
}

impl DownloadTracker {
    /// Creates a new DownloadTracker.
    pub fn new() -> Self {
        DownloadTracker {
            content_len: None,
            total_downloaded: 0,
            downloaded_this_sec: 0,
            downloaded_last_few_secs: VecDeque::with_capacity(DOWNLOAD_TRACK_COUNT),
            start_sec: precise_time_s(),
            last_sec: None,
            term: term2::stdout(),
            displayed_charcount: None,
            units: vec!["B".into(); 1],
        }
    }

    pub fn handle_notification(&mut self, n: &Notification<'_>) -> bool {
        match *n {
            Notification::Install(In::Utils(Un::DownloadContentLengthReceived(content_len))) => {
                self.content_length_received(content_len);

                true
            }
            Notification::Install(In::Utils(Un::DownloadDataReceived(data))) => {
                if tty::stdout_isatty() {
                    self.data_received(data.len());
                }
                true
            }
            Notification::Install(In::Utils(Un::DownloadFinished)) => {
                self.download_finished();
                true
            }
            Notification::Install(In::Utils(Un::DownloadPushUnits(units))) => {
                self.push_units(units.into());
                true
            }
            Notification::Install(In::Utils(Un::DownloadPopUnits)) => {
                self.pop_units();
                true
            }

            _ => false,
        }
    }

    /// Notifies self that Content-Length information has been received.
    pub fn content_length_received(&mut self, content_len: u64) {
        self.content_len = Some(content_len as usize);
    }

    /// Notifies self that data of size `len` has been received.
    pub fn data_received(&mut self, len: usize) {
        self.total_downloaded += len;
        self.downloaded_this_sec += len;

        let current_time = precise_time_s();

        match self.last_sec {
            None => self.last_sec = Some(current_time),
            Some(prev) => {
                let elapsed = current_time - prev;
                if elapsed >= 1.0 {
                    self.display();
                    self.last_sec = Some(current_time);
                    if self.downloaded_last_few_secs.len() == DOWNLOAD_TRACK_COUNT {
                        self.downloaded_last_few_secs.pop_back();
                    }
                    self.downloaded_last_few_secs
                        .push_front(self.downloaded_this_sec);
                    self.downloaded_this_sec = 0;
                }
            }
        }
    }
    /// Notifies self that the download has finished.
    pub fn download_finished(&mut self) {
        if self.displayed_charcount.is_some() {
            // Display the finished state
            self.display();
            let _ = writeln!(self.term);
        }
        self.prepare_for_new_download();
    }
    // we're doing modular arithmetic, treat as integer
    pub fn from_seconds(sec: u32) -> (u32, u32, u32, u32) {
        let d = sec / (24 * 3600);
        let h = sec % (24 * 3600) / 3600;
        let min = sec % 3600 / 60;
        let sec = sec % 60;

        (d, h, min, sec)
    }
    /// Resets the state to be ready for a new download.
    fn prepare_for_new_download(&mut self) {
        self.content_len = None;
        self.total_downloaded = 0;
        self.downloaded_this_sec = 0;
        self.downloaded_last_few_secs.clear();
        self.start_sec = precise_time_s();
        self.last_sec = None;
        self.displayed_charcount = None;
    }
    /// Display the tracked download information to the terminal.
    fn display(&mut self) {
        // Panic if someone pops the default bytes unit...
        let units = &self.units.last().unwrap();
        let total_h = Size(self.total_downloaded, units);
        let sum: usize = self.downloaded_last_few_secs.iter().sum();
        let len = self.downloaded_last_few_secs.len();
        let speed = if len > 0 { sum / len } else { 0 };
        let speed_h = Size(speed, units);
        let elapsed_h = Duration(precise_time_s() - self.start_sec);

        // First, move to the start of the current line and clear it.
        let _ = self.term.carriage_return();
        // We'd prefer to use delete_line() but on Windows it seems to
        // sometimes do unusual things
        // let _ = self.term.as_mut().unwrap().delete_line();
        // So instead we do:
        if let Some(n) = self.displayed_charcount {
            // This is not ideal as very narrow terminals might mess up,
            // but it is more likely to succeed until term's windows console
            // fixes whatever's up with delete_line().
            let _ = write!(self.term, "{}", " ".repeat(n));
            let _ = self.term.flush();
            let _ = self.term.carriage_return();
        }

        let output = match self.content_len {
            Some(content_len) => {
                let content_len_h = Size(content_len, units);
                let content_len = content_len as f64;
                let percent = (self.total_downloaded as f64 / content_len) * 100.;
                let remaining = content_len - self.total_downloaded as f64;
                let eta_h = Duration(remaining / speed as f64);
                format!(
                    "{} / {} ({:3.0} %) {}/s in {} ETA: {}",
                    total_h, content_len_h, percent, speed_h, elapsed_h, eta_h
                )
            }
            None => format!(
                "Total: {} Speed: {}/s Elapsed: {}",
                total_h, speed_h, elapsed_h
            ),
        };

        let _ = write!(self.term, "{}", output);
        // Since stdout is typically line-buffered and we don't print a newline, we manually flush.
        let _ = self.term.flush();
        self.displayed_charcount = Some(output.chars().count());
    }

    pub fn push_units(&mut self, new_units: String) {
        self.units.push(new_units);
    }

    pub fn pop_units(&mut self) {
        self.units.pop();
    }
}

/// Human readable representation of duration(seconds).
struct Duration(f64);

impl fmt::Display for Duration {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // repurposing the alternate mode for ETA
        let sec = self.0;

        if sec.is_infinite() {
            write!(f, "Unknown")
        } else {
            match DownloadTracker::from_seconds(sec as u32) {
                (d, h, m, s) if d > 0 => write!(f, "{:3.0}d {:2.0}h {:2.0}m {:2.0}s", d, h, m, s),
                (0, h, m, s) if h > 0 => write!(f, "{:2.0}h {:2.0}m {:2.0}s", h, m, s),
                (0, 0, m, s) if m > 0 => write!(f, "{:2.0}m {:2.0}s", m, s),
                (_, _, _, s) => write!(f, "{:2.0}s", s),
            }
        }
    }
}

/// Human readable size (some units)
struct Size<'a>(usize, &'a str);

impl<'a> fmt::Display for Size<'a> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        const KI: f64 = 1024.0;
        const MI: f64 = KI * KI;
        let size = self.0 as f64;

        if size >= MI {
            write!(f, "{:5.1} Mi{}", size / MI, self.1) // XYZ.P Mi
        } else if size >= KI {
            write!(f, "{:5.1} Ki{}", size / KI, self.1)
        } else {
            write!(f, "{:3.0} {}", size, self.1)
        }
    }
}

#[cfg(test)]
mod tests {

    #[test]
    fn download_tracker_from_seconds_test() {
        use crate::download_tracker::DownloadTracker;
        assert_eq!(DownloadTracker::from_seconds(2), (0, 0, 0, 2));

        assert_eq!(DownloadTracker::from_seconds(60), (0, 0, 1, 0));

        assert_eq!(DownloadTracker::from_seconds(3600), (0, 1, 0, 0));

        assert_eq!(DownloadTracker::from_seconds(3600 * 24), (1, 0, 0, 0));

        assert_eq!(DownloadTracker::from_seconds(52292), (0, 14, 31, 32));

        assert_eq!(DownloadTracker::from_seconds(222292), (2, 13, 44, 52));
    }

}
<commit_msg>Fix clippy: unreadable_literal<commit_after>use crate::term2;
use rustup::dist::Notification as In;
use rustup::utils::tty;
use rustup::utils::Notification as Un;
use rustup::Notification;
use std::collections::VecDeque;
use std::fmt;
use std::io::Write;
use term::Terminal;
use time::precise_time_s;

/// Keep track of this many past download amounts
const DOWNLOAD_TRACK_COUNT: usize = 5;

/// Tracks download progress and displays information about it to a terminal.
pub struct DownloadTracker {
    /// Content-Length of the to-be downloaded object.
    content_len: Option<usize>,
    /// Total data downloaded in bytes.
    total_downloaded: usize,
    /// Data downloaded this second.
    downloaded_this_sec: usize,
    /// Keeps track of amount of data downloaded every last few secs.
    /// Used for averaging the download speed. NB: This does not necessarily
    /// represent adjacent seconds; thus it may not show the average at all.
    downloaded_last_few_secs: VecDeque<usize>,
    /// Time stamp of the last second
    last_sec: Option<f64>,
    /// Time stamp of the start of the download
    start_sec: f64,
    /// The terminal we write the information to.
    /// XXX: Could be a term trait, but with #1818 on the horizon that
    ///      is a pointless change to make - better to let that transition
    ///      happen and take stock after that.
    term: term2::StdoutTerminal,
    /// Whether we displayed progress for the download or not.
    ///
    /// If the download is quick enough, we don't have time to
    /// display the progress info.
    /// In that case, we do not want to do some cleanup stuff we normally do.
    ///
    /// If we have displayed progress, this is the number of characters we
    /// rendered, so we can erase it cleanly.
    displayed_charcount: Option<usize>,
    /// What units to show progress in
    units: Vec<String>,
}

impl DownloadTracker {
    /// Creates a new DownloadTracker.
    pub fn new() -> Self {
        DownloadTracker {
            content_len: None,
            total_downloaded: 0,
            downloaded_this_sec: 0,
            downloaded_last_few_secs: VecDeque::with_capacity(DOWNLOAD_TRACK_COUNT),
            start_sec: precise_time_s(),
            last_sec: None,
            term: term2::stdout(),
            displayed_charcount: None,
            units: vec!["B".into(); 1],
        }
    }

    pub fn handle_notification(&mut self, n: &Notification<'_>) -> bool {
        match *n {
            Notification::Install(In::Utils(Un::DownloadContentLengthReceived(content_len))) => {
                self.content_length_received(content_len);

                true
            }
            Notification::Install(In::Utils(Un::DownloadDataReceived(data))) => {
                if tty::stdout_isatty() {
                    self.data_received(data.len());
                }
                true
            }
            Notification::Install(In::Utils(Un::DownloadFinished)) => {
                self.download_finished();
                true
            }
            Notification::Install(In::Utils(Un::DownloadPushUnits(units))) => {
                self.push_units(units.into());
                true
            }
            Notification::Install(In::Utils(Un::DownloadPopUnits)) => {
                self.pop_units();
                true
            }

            _ => false,
        }
    }

    /// Notifies self that Content-Length information has been received.
    pub fn content_length_received(&mut self, content_len: u64) {
        self.content_len = Some(content_len as usize);
    }

    /// Notifies self that data of size `len` has been received.
    pub fn data_received(&mut self, len: usize) {
        self.total_downloaded += len;
        self.downloaded_this_sec += len;

        let current_time = precise_time_s();

        match self.last_sec {
            None => self.last_sec = Some(current_time),
            Some(prev) => {
                let elapsed = current_time - prev;
                if elapsed >= 1.0 {
                    self.display();
                    self.last_sec = Some(current_time);
                    if self.downloaded_last_few_secs.len() == DOWNLOAD_TRACK_COUNT {
                        self.downloaded_last_few_secs.pop_back();
                    }
                    self.downloaded_last_few_secs
                        .push_front(self.downloaded_this_sec);
                    self.downloaded_this_sec = 0;
                }
            }
        }
    }
    /// Notifies self that the download has finished.
    pub fn download_finished(&mut self) {
        if self.displayed_charcount.is_some() {
            // Display the finished state
            self.display();
            let _ = writeln!(self.term);
        }
        self.prepare_for_new_download();
    }
    // we're doing modular arithmetic, treat as integer
    pub fn from_seconds(sec: u32) -> (u32, u32, u32, u32) {
        let d = sec / (24 * 3600);
        let h = sec % (24 * 3600) / 3600;
        let min = sec % 3600 / 60;
        let sec = sec % 60;

        (d, h, min, sec)
    }
    /// Resets the state to be ready for a new download.
    fn prepare_for_new_download(&mut self) {
        self.content_len = None;
        self.total_downloaded = 0;
        self.downloaded_this_sec = 0;
        self.downloaded_last_few_secs.clear();
        self.start_sec = precise_time_s();
        self.last_sec = None;
        self.displayed_charcount = None;
    }
    /// Display the tracked download information to the terminal.
    fn display(&mut self) {
        // Panic if someone pops the default bytes unit...
        let units = &self.units.last().unwrap();
        let total_h = Size(self.total_downloaded, units);
        let sum: usize = self.downloaded_last_few_secs.iter().sum();
        let len = self.downloaded_last_few_secs.len();
        let speed = if len > 0 { sum / len } else { 0 };
        let speed_h = Size(speed, units);
        let elapsed_h = Duration(precise_time_s() - self.start_sec);

        // First, move to the start of the current line and clear it.
        let _ = self.term.carriage_return();
        // We'd prefer to use delete_line() but on Windows it seems to
        // sometimes do unusual things
        // let _ = self.term.as_mut().unwrap().delete_line();
        // So instead we do:
        if let Some(n) = self.displayed_charcount {
            // This is not ideal as very narrow terminals might mess up,
            // but it is more likely to succeed until term's windows console
            // fixes whatever's up with delete_line().
            let _ = write!(self.term, "{}", " ".repeat(n));
            let _ = self.term.flush();
            let _ = self.term.carriage_return();
        }

        let output = match self.content_len {
            Some(content_len) => {
                let content_len_h = Size(content_len, units);
                let content_len = content_len as f64;
                let percent = (self.total_downloaded as f64 / content_len) * 100.;
                let remaining = content_len - self.total_downloaded as f64;
                let eta_h = Duration(remaining / speed as f64);
                format!(
                    "{} / {} ({:3.0} %) {}/s in {} ETA: {}",
                    total_h, content_len_h, percent, speed_h, elapsed_h, eta_h
                )
            }
            None => format!(
                "Total: {} Speed: {}/s Elapsed: {}",
                total_h, speed_h, elapsed_h
            ),
        };

        let _ = write!(self.term, "{}", output);
        // Since stdout is typically line-buffered and we don't print a newline, we manually flush.
        let _ = self.term.flush();
        self.displayed_charcount = Some(output.chars().count());
    }

    pub fn push_units(&mut self, new_units: String) {
        self.units.push(new_units);
    }

    pub fn pop_units(&mut self) {
        self.units.pop();
    }
}

/// Human readable representation of duration(seconds).
struct Duration(f64);

impl fmt::Display for Duration {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // repurposing the alternate mode for ETA
        let sec = self.0;

        if sec.is_infinite() {
            write!(f, "Unknown")
        } else {
            match DownloadTracker::from_seconds(sec as u32) {
                (d, h, m, s) if d > 0 => write!(f, "{:3.0}d {:2.0}h {:2.0}m {:2.0}s", d, h, m, s),
                (0, h, m, s) if h > 0 => write!(f, "{:2.0}h {:2.0}m {:2.0}s", h, m, s),
                (0, 0, m, s) if m > 0 => write!(f, "{:2.0}m {:2.0}s", m, s),
                (_, _, _, s) => write!(f, "{:2.0}s", s),
            }
        }
    }
}

/// Human readable size (some units)
struct Size<'a>(usize, &'a str);

impl<'a> fmt::Display for Size<'a> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        const KI: f64 = 1024.0;
        const MI: f64 = KI * KI;
        let size = self.0 as f64;

        if size >= MI {
            write!(f, "{:5.1} Mi{}", size / MI, self.1) // XYZ.P Mi
        } else if size >= KI {
            write!(f, "{:5.1} Ki{}", size / KI, self.1)
        } else {
            write!(f, "{:3.0} {}", size, self.1)
        }
    }
}

#[cfg(test)]
mod tests {

    #[test]
    fn download_tracker_from_seconds_test() {
        use crate::download_tracker::DownloadTracker;
        assert_eq!(DownloadTracker::from_seconds(2), (0, 0, 0, 2));

        assert_eq!(DownloadTracker::from_seconds(60), (0, 0, 1, 0));

        assert_eq!(DownloadTracker::from_seconds(3_600), (0, 1, 0, 0));

        assert_eq!(DownloadTracker::from_seconds(3_600 * 24), (1, 0, 0, 0));

        assert_eq!(DownloadTracker::from_seconds(52_292), (0, 14, 31, 32));

        assert_eq!(DownloadTracker::from_seconds(222_292), (2, 13, 44, 52));
    }

}
<|endoftext|>


<commit_before>extern crate rand;
extern crate common;

use common::*;
use common::Projection::*;

use rand::{StdRng, SeedableRng, Rng};

#[cfg(debug_assertions)]
#[no_mangle]
pub fn new_state() -> State {
    println!("debug on");

    let seed: &[_] = &[42];
    let rng: StdRng = SeedableRng::from_seed(seed);

    make_state(rng)
}
#[cfg(not(debug_assertions))]
#[no_mangle]
pub fn new_state() -> State {
    let timestamp = std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .map(|dur| dur.as_secs())
        .unwrap_or(42);

    println!("{}", timestamp);
    let seed: &[_] = &[timestamp as usize];
    let rng: StdRng = SeedableRng::from_seed(seed);

    make_state(rng)
}

fn make_state(rng: StdRng) -> State {
    let mut state = State {
        rng,
        polys: Vec::new(),
        cam_x: 0.0,
        cam_y: 0.0,
        zoom: 1.0,
    };

    add_random_poly(&mut state);

    state
}

#[no_mangle]
//returns true if quit requested
pub fn update_and_render(p: &Platform, state: &mut State, events: &mut Vec<Event>) -> bool {
    for event in events {
        println!("{:?}", *event);

        match *event {
            Event::Quit |
            Event::KeyDown(Keycode::Escape) |
            Event::KeyDown(Keycode::F10) => {
                return true;
            }
            Event::KeyDown(Keycode::Space) => {
                add_random_poly(state);
            }
            Event::KeyDown(Keycode::R) => {
                state.polys.clear();
                add_random_poly(state);
            }
            Event::KeyDown(Keycode::Up) => {
                state.cam_y += 0.0625;
            }
            Event::KeyDown(Keycode::Down) => {
                state.cam_y -= 0.0625;
            }
            Event::KeyDown(Keycode::Right) => {
                state.cam_x += 0.0625;
            }
            Event::KeyDown(Keycode::Left) => {
                state.cam_x -= 0.0625;
            }
            Event::KeyDown(Keycode::Num0) => {
                state.cam_x = 0.0;
                state.cam_y = 0.0;
                state.zoom = 1.0;
            }
            Event::KeyDown(Keycode::W) => {
                state.zoom *= 1.25;
            }
            Event::KeyDown(Keycode::S) => {
                state.zoom /= 1.25;
            }
            _ => {}
        }
    }

    let aspect_ratio = 800.0 / 600.0;
    let near = 0.5;
    let far = 1024.0;

    let scale = state.zoom * near;
    let top = scale;
    let bottom = -top;
    let right = aspect_ratio * scale;
    let left = -right;

    let projection = get_projection(&ProjectionSpec {
        top,
        bottom,
        left,
        right,
        near,
        far,
        projection: Perspective,
        // projection: Orthographic,
    });

    let camera = [
        1.0,
        0.0,
        0.0,
        0.0,
        0.0,
        1.0,
        0.0,
        0.0,
        0.0,
        0.0,
        1.0,
        0.0,
        state.cam_x,
        state.cam_y,
        0.0,
        1.0,
    ];

    let view = mat4x4_mul(&camera, &projection);

    for poly in state.polys.iter() {
        let world_matrix = [
            1.0,
            0.0,
            0.0,
            0.0,
            0.0,
            1.0,
            0.0,
            0.0,
            0.0,
            0.0,
            1.0,
            0.0,
            poly.x,
            poly.y,
            0.0,
            1.0,
        ];

        let matrix = mat4x4_mul(&world_matrix, &view);

        // (p.draw_poly_with_matrix)(matrix, poly.index);
        (p.draw_textured_poly_with_matrix)(matrix, poly.index, 0);
    }

    false
}

fn add_random_poly(state: &mut State) {
    let poly = Polygon {
        x: state.rng.gen_range(-9.0, 10.0) / 10.0,
        y: state.rng.gen_range(-9.0, 10.0) / 10.0,
        index: state.rng.gen_range(0, 4),
        scale: state.rng.gen_range(0.0, 2.0),
    };

    state.polys.push(poly);
}

//These are the verticies of the polygons which can be drawn.
//The index refers to the index of the inner vector within the outer vecton.
#[cfg_attr(rustfmt, rustfmt_skip)]
#[no_mangle]
pub fn get_vert_vecs() -> Vec<Vec<f32>> {
    vec![
        // star heptagon
        vec![
            -0.012640, 0.255336,
            0.152259, 0.386185,
            0.223982, 0.275978,
            0.191749, 0.169082,
            0.396864, 0.121742,
            0.355419, -0.003047,
            0.251747, -0.044495,
            0.342622, -0.234376,
            0.219218, -0.279777,
            0.122174, -0.224565,
            0.030379, -0.414003,
            -0.082058, -0.345830,
            -0.099398, -0.235534,
            -0.304740, -0.281878,
            -0.321543, -0.151465,
            -0.246122, -0.069141,
            -0.410383, 0.062507,
            -0.318899, 0.156955,
            -0.207511, 0.149317,
            -0.207000, 0.359823,
            -0.076118, 0.347186,
            -0.012640, 0.255336,
        ],
        // heptagon
        vec![
            0.555765, -0.002168,
            0.344819, -0.435866,
            -0.125783, -0.541348,
            -0.501668, -0.239184,
            -0.499786, 0.243091,
            -0.121556, 0.542313,
            0.348209, 0.433163,
            0.555765, -0.002168,
        ],
        // star hexagon
        vec![
            0.267355, 0.153145,
            0.158858, 0.062321,
            0.357493, -0.060252,
            0.266305, -0.154964,
            0.133401, -0.106415,
            0.126567, -0.339724,
            -0.001050, -0.308109,
            -0.025457, -0.168736,
            -0.230926, -0.279472,
            -0.267355, -0.153145,
            -0.158858, -0.062321,
            -0.357493, 0.060252,
            -0.266305, 0.154964,
            -0.133401, 0.106415,
            -0.126567, 0.339724,
            0.001050, 0.308109,
            0.025457, 0.168736,
            0.230926, 0.279472,
            0.267355, 0.153145,
        ],
        //hexagon
        vec![
        0.002000, -0.439500,
        -0.379618, -0.221482,
        -0.381618, 0.218018,
        -0.002000, 0.439500,
        0.379618, 0.221482,
        0.381618, -0.218018,
        0.002000, -0.439500,
        ],
    ]
}
<commit_msg>add new polygon types to quickly confirm that stencil inversion works on textured polys<commit_after>extern crate rand;
extern crate common;

use common::*;
use common::Projection::*;

use rand::{StdRng, SeedableRng, Rng};

#[cfg(debug_assertions)]
#[no_mangle]
pub fn new_state() -> State {
    println!("debug on");

    let seed: &[_] = &[42];
    let rng: StdRng = SeedableRng::from_seed(seed);

    make_state(rng)
}
#[cfg(not(debug_assertions))]
#[no_mangle]
pub fn new_state() -> State {
    let timestamp = std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .map(|dur| dur.as_secs())
        .unwrap_or(42);

    println!("{}", timestamp);
    let seed: &[_] = &[timestamp as usize];
    let rng: StdRng = SeedableRng::from_seed(seed);

    make_state(rng)
}

fn make_state(rng: StdRng) -> State {
    let mut state = State {
        rng,
        polys: Vec::new(),
        cam_x: 0.0,
        cam_y: 0.0,
        zoom: 1.0,
    };

    add_random_poly(&mut state);

    state
}

#[no_mangle]
//returns true if quit requested
pub fn update_and_render(p: &Platform, state: &mut State, events: &mut Vec<Event>) -> bool {
    for event in events {
        println!("{:?}", *event);

        match *event {
            Event::Quit |
            Event::KeyDown(Keycode::Escape) |
            Event::KeyDown(Keycode::F10) => {
                return true;
            }
            Event::KeyDown(Keycode::Space) => {
                add_random_poly(state);
            }
            Event::KeyDown(Keycode::R) => {
                state.polys.clear();
                add_random_poly(state);
            }
            Event::KeyDown(Keycode::Up) => {
                state.cam_y += 0.0625;
            }
            Event::KeyDown(Keycode::Down) => {
                state.cam_y -= 0.0625;
            }
            Event::KeyDown(Keycode::Right) => {
                state.cam_x += 0.0625;
            }
            Event::KeyDown(Keycode::Left) => {
                state.cam_x -= 0.0625;
            }
            Event::KeyDown(Keycode::Num0) => {
                state.cam_x = 0.0;
                state.cam_y = 0.0;
                state.zoom = 1.0;
            }
            Event::KeyDown(Keycode::W) => {
                state.zoom *= 1.25;
            }
            Event::KeyDown(Keycode::S) => {
                state.zoom /= 1.25;
            }
            _ => {}
        }
    }

    let aspect_ratio = 800.0 / 600.0;
    let near = 0.5;
    let far = 1024.0;

    let scale = state.zoom * near;
    let top = scale;
    let bottom = -top;
    let right = aspect_ratio * scale;
    let left = -right;

    let projection = get_projection(&ProjectionSpec {
        top,
        bottom,
        left,
        right,
        near,
        far,
        projection: Perspective,
        // projection: Orthographic,
    });

    let camera = [
        1.0,
        0.0,
        0.0,
        0.0,
        0.0,
        1.0,
        0.0,
        0.0,
        0.0,
        0.0,
        1.0,
        0.0,
        state.cam_x,
        state.cam_y,
        0.0,
        1.0,
    ];

    let view = mat4x4_mul(&camera, &projection);

    for poly in state.polys.iter() {
        let world_matrix = [
            1.0,
            0.0,
            0.0,
            0.0,
            0.0,
            1.0,
            0.0,
            0.0,
            0.0,
            0.0,
            1.0,
            0.0,
            poly.x,
            poly.y,
            0.0,
            1.0,
        ];

        let matrix = mat4x4_mul(&world_matrix, &view);

        (p.draw_poly_with_matrix)(matrix, poly.index);
    }

    false
}

fn add_random_poly(state: &mut State) {
    let poly = Polygon {
        x: state.rng.gen_range(-9.0, 10.0) / 10.0,
        y: state.rng.gen_range(-9.0, 10.0) / 10.0,
        index: state.rng.gen_range(0, 6),
        scale: state.rng.gen_range(0.0, 2.0),
    };

    state.polys.push(poly);
}

//These are the verticies of the polygons which can be drawn.
//The index refers to the index of the inner vector within the outer vecton.
#[cfg_attr(rustfmt, rustfmt_skip)]
#[no_mangle]
pub fn get_vert_vecs() -> Vec<Vec<f32>> {
    vec![
        // star heptagon
        vec![
            -0.012640, 0.255336,
            0.152259, 0.386185,
            0.223982, 0.275978,
            0.191749, 0.169082,
            0.396864, 0.121742,
            0.355419, -0.003047,
            0.251747, -0.044495,
            0.342622, -0.234376,
            0.219218, -0.279777,
            0.122174, -0.224565,
            0.030379, -0.414003,
            -0.082058, -0.345830,
            -0.099398, -0.235534,
            -0.304740, -0.281878,
            -0.321543, -0.151465,
            -0.246122, -0.069141,
            -0.410383, 0.062507,
            -0.318899, 0.156955,
            -0.207511, 0.149317,
            -0.207000, 0.359823,
            -0.076118, 0.347186,
            -0.012640, 0.255336,
        ],
        // heptagon
        vec![
            0.555765, -0.002168,
            0.344819, -0.435866,
            -0.125783, -0.541348,
            -0.501668, -0.239184,
            -0.499786, 0.243091,
            -0.121556, 0.542313,
            0.348209, 0.433163,
            0.555765, -0.002168,
        ],
        // star hexagon
        vec![
            0.267355, 0.153145,
            0.158858, 0.062321,
            0.357493, -0.060252,
            0.266305, -0.154964,
            0.133401, -0.106415,
            0.126567, -0.339724,
            -0.001050, -0.308109,
            -0.025457, -0.168736,
            -0.230926, -0.279472,
            -0.267355, -0.153145,
            -0.158858, -0.062321,
            -0.357493, 0.060252,
            -0.266305, 0.154964,
            -0.133401, 0.106415,
            -0.126567, 0.339724,
            0.001050, 0.308109,
            0.025457, 0.168736,
            0.230926, 0.279472,
            0.267355, 0.153145,
        ],
        //hexagon
        vec![
        0.002000, -0.439500,
        -0.379618, -0.221482,
        -0.381618, 0.218018,
        -0.002000, 0.439500,
        0.379618, 0.221482,
        0.381618, -0.218018,
        0.002000, -0.439500,
        ],
        //invert 7 point star
        vec![
        -1.037129, 0.000000,
        -0.487625, 0.071884,
        -0.036111, 0.158214,
        0.934421, 0.449993,
        0.470524, 0.146807,
        0.101182, -0.126878,
        -0.646639, -0.810860,
        -0.360230, -0.336421,
        -0.146212, 0.070412,
        0.230783, 1.011126,
        0.178589, 0.459403,
        0.162283, 0.000000,
        0.230783, -1.011126,
        0.038425, -0.491395,
        -0.146212, -0.070412,
        -0.646639, 0.810860,
        -0.247828, 0.426059,
        0.101182, 0.126878,
        0.934421, -0.449993,
        0.408145, -0.276338,
        -0.036111, -0.158214,
        -1.037129, -0.000000,
        ],
        //invers 6 point star
        vec![
        -1.037129, 0.000000,
        -0.583093, -0.055358,
        -0.204743, -0.117901,
        0.517890, -0.299004,
        0.243039, -0.029458,
        -0.000266, 0.236263,
        -0.518564, 0.898180,
        -0.339488, 0.477294,
        -0.204477, 0.118362,
        0.000000, -0.598008,
        0.096008, -0.225207,
        0.204477, 0.118362,
        0.518564, 0.898180,
        0.243605, 0.532652,
        0.000266, 0.236263,
        -0.517890, -0.299004,
        -0.147031, -0.195748,
        0.204743, -0.117901,
        1.037129, 0.000000,
        0.583093, 0.055358,
        0.204743, 0.117901,
        -0.517890, 0.299004,
        -0.243039, 0.029458,
        0.000266, -0.236263,
        0.518564, -0.898180,
        0.339488, -0.477294,
        0.204477, -0.118362,
        -0.000000, 0.598008,
        -0.096008, 0.225207,
        -0.204477, -0.118362,
        -0.518564, -0.898180,
        -0.243605, -0.532652,
        -0.000266, -0.236263,
        0.517890, 0.299004,
        0.147031, 0.195748,
        -0.204743, 0.117901,
        -1.037129, -0.000000,
        -0.583093, -0.055358,
        -0.204743, -0.117901,
        0.517890, -0.299004,
        0.147031, -0.195748,
        -0.204743, -0.117901,
        -1.037129, 0.000000
        ]
    ]
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate chrono;
extern crate regex;
#[macro_use] extern crate itertools;
use clap::{Arg, App};
use std::fs;
use std::io;

pub mod common;
pub mod day01;
pub mod day02;
pub mod day03;
pub mod day04;
pub mod day05;

fn get_impl(day: &str) -> Box<common::Solution> {
    match day.parse() {
        Ok(1) => Box::new(day01::Day01::new()),
        Ok(2) => Box::new(day02::Day02::new()),
        Ok(3) => Box::new(day03::Day03::new()),
        Ok(4) => Box::new(day04::Day04::new()),
        Ok(5) => Box::new(day05::Day05::new()),
        Ok(val) => panic!("Unimplemented day {}", val),
        _ => panic!("Invalid number"),
    }
}

fn main() {
    let matches = App::new("Advent of Code")
        .version("2018")
        .author("Bert Peters <bert@bertptrs.nl>")
        .arg(Arg::with_name("day")
             .value_name("DAY")
             .help("Number of the day to execute")
             .required(true)
             .takes_value(true))
        .arg(Arg::with_name("part2")
             .short("2")
             .help("Whether to run part 2")
             .long("part2"))
        .arg(Arg::with_name("input")
             .short("i")
             .long("input")
             .help("Optional input file, stdin otherwise")
             .takes_value(true))
        .get_matches();

    let mut implementation = get_impl(matches.value_of("day").unwrap());
    let mut data: Box<io::Read> = match matches.value_of("input") {
        Some(filename) => { Box::new(fs::File::open(filename).unwrap()) }
        None => { Box::new(io::stdin()) }
    };

    if matches.is_present("part2") {
        println!("{}", implementation.part2(&mut data));
    } else {
        println!("{}", implementation.part1(&mut data));
    }
}

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

    #[test]
    fn test_get_impl() {
        // Verify that we can load all days
        let last_implemented = 5;
        for d in 1..=last_implemented {
            get_impl(&format!("{}", d));
        }
    }
}
<commit_msg>More easily time the program.<commit_after>extern crate chrono;
extern crate clap;
#[macro_use] extern crate itertools;
extern crate regex;

use std::fs;
use std::io;
use std::time::Instant;

use clap::{App, Arg};

pub mod common;
pub mod day01;
pub mod day02;
pub mod day03;
pub mod day04;
pub mod day05;

fn get_impl(day: &str) -> Box<common::Solution> {
    match day.parse() {
        Ok(1) => Box::new(day01::Day01::new()),
        Ok(2) => Box::new(day02::Day02::new()),
        Ok(3) => Box::new(day03::Day03::new()),
        Ok(4) => Box::new(day04::Day04::new()),
        Ok(5) => Box::new(day05::Day05::new()),
        Ok(val) => panic!("Unimplemented day {}", val),
        _ => panic!("Invalid number"),
    }
}

fn main() {
    let matches = App::new("Advent of Code")
        .version("2018")
        .author("Bert Peters <bert@bertptrs.nl>")
        .arg(Arg::with_name("day")
             .value_name("DAY")
             .help("Number of the day to execute")
             .required(true)
             .takes_value(true))
        .arg(Arg::with_name("part2")
             .short("2")
             .help("Whether to run part 2")
             .long("part2"))
        .arg(Arg::with_name("input")
             .short("i")
             .long("input")
             .help("Optional input file, stdin otherwise")
             .takes_value(true))
        .arg(Arg::with_name("time")
             .short("t")
             .long("time")
             .help("Print the time for the result"))
        .get_matches();

    let mut implementation = get_impl(matches.value_of("day").unwrap());
    let mut data: Box<io::Read> = match matches.value_of("input") {
        Some(filename) => { Box::new(fs::File::open(filename).unwrap()) }
        None => { Box::new(io::stdin()) }
    };

    let begin = Instant::now();
    let result = if matches.is_present("part2") {
        implementation.part2(&mut data)
    } else {
        implementation.part1(&mut data)
    };
    if matches.is_present("time") {
        eprintln!("Duration: {:?}", Instant::now().duration_since(begin));
    }
    println!("{}", result);
}

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

    #[test]
    fn test_get_impl() {
        // Verify that we can load all days
        let last_implemented = 5;
        for d in 1..=last_implemented {
            get_impl(&format!("{}", d));
        }
    }
}
<|endoftext|>


<commit_before>use dungeon::{Dungeon};
use celloption::{Occupant};
use genotype::{Genotype};
use phenotype::{Seed};
use config::{Config};
use util::{odds};

use std::iter::{range_step};
use std::collections::{HashMap, HashSet};
use rand::{Rng};

#[derive(Clone, Debug)]
pub struct DesirableProperties {
    seed: Seed,
    room_number: u32,
    room_size: u32,
    doors: u32,
    monsters: u32,
    path_length: u32,
    branching: f64,
    occupants: Vec<(Occupant, (u32, u32))>,
    rooms: Vec<Room>,
    mazes: Vec<Maze>,
    connectors: Vec<Connector>,
}

#[derive(Clone, Debug)]
struct Room {
    x: u32,
    y: u32,
    w: u32,
    h: u32,
    region: u32,
}

#[derive(Clone, Debug)]
struct Maze {
    path: HashSet<(u32, u32)>,
    region: u32,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
enum Direction {
    North,
    East,
    South,
    West
}

#[derive(Clone, Debug)]
struct Connector {
    location: (u32, u32),
    regions: Vec<u32>,
}

impl Connector {
    pub fn new(location: (u32, u32), regions: &Vec<u32>) -> Connector {
        Connector {
            location: location,
            regions: regions.clone(),
        }
    }

    pub fn find_all(mazes: &Vec<Maze>, rooms: &Vec<Room>) -> Vec<Connector> {
        // given all the mazes and rooms
        // for all the available spots (room sides, maze paths)
        //   see if we have a connector (a blank spot that joins the two)
        //   if we have more than two connectors, save it as a connector

        vec![]
    }
}

pub type CollisionFn<'a> = Box<Fn(&(u32, u32)) -> bool + 'a>;

impl Maze {
    pub fn new<T: Rng>(rng: &mut T,
                       previous: &HashSet<(u32, u32)>,
                       collides: CollisionFn,
                       branching: f64,
                       region: u32,
                       x: u32,
                       y: u32) -> Maze {
        let path = Maze::grow(rng, previous, collides, branching, x, y);
        Maze {
            region: region,
            path: path
        }
    }

    fn grow<T: Rng>(rng: &mut T,
                    previous: &HashSet<(u32, u32)>,
                    collides: CollisionFn,
                    branching: f64,
                    orig_x: u32,
                    orig_y: u32) -> HashSet<(u32, u32)> {
        let branching_factor = (branching * 100.0) as u64;
        let mut path: Vec<(u32, u32)> = Vec::new();
        let mut all_paths: HashSet<(u32, u32)> = previous.clone();
        let all = vec!(Direction::North, Direction::East, Direction::South, Direction::West);
        let mut direction = rng.choose(all.as_slice()).unwrap().clone();
        let sc = vec!((Direction::North, (0, 1)),
                      (Direction::East, (1, 0)),
                      (Direction::South, (0, -1)),
                      (Direction::West, (-1, 0)));
        path.push((orig_x, orig_y));
        all_paths.insert((orig_x, orig_y));
        while !path.is_empty() {
            let (x, y) = path[path.len()-1];
            let coord_at = |(vx, vy): (i32, i32), n| ((x as i32 + vx*n) as u32, (y as i32 + vy*n) as u32);
            let uncarved: HashMap<Direction, (i32, i32)> = sc.iter().filter(|&&(_, new_dir)| {
                let coord1 = coord_at(new_dir, 1);
                let coord2 = coord_at(new_dir, 2);
                let coord3 = coord_at(new_dir, 3);
                !all_paths.contains(&coord1) &&
                    !all_paths.contains(&coord2) &&
                    !all_paths.contains(&coord3) &&
                    !collides(&coord2) &&
                    !collides(&coord3)
            }).cloned().collect();
            if !uncarved.is_empty() {
                let same_direction = odds(rng, branching_factor, 100);
                let rel = if same_direction && uncarved.contains_key(&direction) {
                    uncarved[direction]
                } else {
                    let (dir, coords) = uncarved.into_iter().next().unwrap();
                    direction = dir;
                    coords
                };
                let coord1 = coord_at(rel, 1);
                let coord2 = coord_at(rel, 2);
                all_paths.insert(coord1);
                all_paths.insert(coord2);
                path.push(coord2);
            } else {
                path.pop();
            }
        }
        all_paths.difference(previous).cloned().collect()
    }
}

impl Room {
    pub fn random<T: Rng>(rng: &mut T, width: u32, height: u32, room_size: u32, region: u32) -> Room {
        let w: u32 = rng.gen_range(3, room_size);
        let h: u32 = rng.gen_range(3, room_size);
        assert!(width >= w);
        assert!(height >= h);
        let x: u32 = rng.gen_range(1, width - w);
        let y: u32 = rng.gen_range(1, height - h);
        let make_odd = |n| if n % 2 == 0 { n - 1 } else { n };
        Room {
            x: make_odd(x),
            y: make_odd(y),
            w: make_odd(w),
            h: make_odd(h),
            region: region,
        }
    }

    pub fn intersects(&self, rooms: &Vec<Room>) -> bool {
        for r in rooms {
            let rw = r.x + r.w;
            let rh = r.y + r.h;
            let roomw = self.x + self.w;
            let roomh = self.y + self.h;
            if roomw > r.x && roomh > r.y && self.x < rw && self.y < rh {
                return true
            }
        }
        false
    }

    pub fn contains(&self, x: u32, y: u32) -> bool {
        let roomw = self.x + self.w;
        let roomh = self.y + self.h;
        x >= self.x && x < roomw && y >= self.y && y < roomh
    }

    pub fn border(&self) -> Vec<(u32, u32)> {
        let mut surrounding = vec![];
        for i in range(0, self.w) {
            surrounding.push(((self.x + i), self.y));
            surrounding.push(((self.x + i), self.y + self.h - 1));
        }
        for i in range(0, self.h) {
            surrounding.push((self.x, self.y + i));
            surrounding.push((self.x + self.w - 1, self.y + i));
        }
        surrounding
    }
}

impl DesirableProperties {
    pub fn new(config: &Config, seed: &Seed) -> DesirableProperties {
        // read in the configurations
        let desirables = config.get_table(None, "desirable_patterns");
        let room_number = config.get_integer(desirables, "room_number") as u32;
        let room_size = config.get_integer(desirables, "room_size") as u32;
        let doors = config.get_integer(desirables, "doors") as u32;
        let monsters = config.get_integer(desirables, "monsters") as u32;
        let path_length = config.get_integer(desirables, "path_length") as u32;
        let branching = config.get_float(desirables, "branching");
        DesirableProperties {
            seed: seed.clone(),
            room_size: room_size,
            room_number: room_number,
            doors: doors,
            monsters: monsters,
            path_length: path_length,
            branching: branching,
            occupants: vec![],
            rooms: vec![],
            mazes: vec![],
            connectors: vec![],
        }
    }

}

impl Genotype for DesirableProperties {
    fn initialize<T: Rng>(&self, rng: &mut T) -> DesirableProperties {
        let w = self.seed.width;
        let h = self.seed.height;
        let occupants = self.seed.random_occupants(rng).iter().take(self.monsters as usize).cloned().collect();
        let mut region = 0;
        // randomly generate rooms
        let mut rooms = vec![];
        for _ in range(0, self.room_number) {
            for _ in range(0, 10) {
                let room = Room::random(rng, w, h, self.room_size, region);
                if !room.intersects(&rooms) {
                    rooms.push(room);
                    region += 1;
                    break;
                }
            }
        }
        // fill in mazes
        let mut mazes = vec![];
        let mut positions: HashSet<(u32, u32)> = HashSet::new();
        let is_occupied = |x, y| rooms.clone().iter().fold(false, |accum, ref m| accum || m.contains(x, y));
        for x in range_step(1, w, 2) {
            for y in range_step(1, h, 2) {
                if !is_occupied(x, y) && !positions.contains(&(x, y)) {
                    let collides: CollisionFn = box |&(cx, cy)| cx >= w || cy >= h || is_occupied(cx, cy);
                    let maze = Maze::new(rng, &positions, collides, self.branching, region, x, y);
                    positions = positions.union(&maze.path).cloned().collect();
                    mazes.push(maze);
                    region += 1;
                }
            }
        }
        // find connectors
        let connectors = Connector::find_all(&mazes, &rooms);
        // remove dead ends
        DesirableProperties {
            seed: self.seed.clone(),
            room_number: self.room_number,
            room_size: self.room_size,
            doors: self.doors,
            monsters: self.monsters,
            path_length: self.path_length,
            branching: self.branching,
            occupants: occupants,
            rooms: rooms.clone(),
            mazes: mazes,
            connectors: connectors,
        }
    }

    fn mutate<T: Rng>(&mut self, _: &mut T, _: f64) {
        // mutate a certain % of the rooms and start again
    }

    fn generate(&self) -> Dungeon {
        let w = self.seed.width;
        let h = self.seed.height;
        let mut dungeon = Dungeon::new(w, h, None);
        let wall = self.seed.tiles.get("wall").unwrap();
        let door = self.seed.tiles.get("door").unwrap();
        let floor = self.seed.tiles.get("floor").unwrap();
        for room in self.rooms.iter() {
            for i in range(room.x, room.x + room.w) {
                for j in range(room.y, room.y + room.h) {
                    dungeon.cells[i as usize][j as usize].tile = Some(wall.clone())
                }
            }
            for (i, j) in room.border() {
                dungeon.cells[i as usize][j as usize].tile = Some(floor.clone())
            }
        }
        for maze in self.mazes.iter() {
            for path in maze.path.iter() {
                let (x, y): (u32, u32) = *path;
                dungeon.cells[x as usize][y as usize].tile = Some(floor.clone());
            }
        }
        for connector in self.connectors.iter() {
            let (x, y) = connector.location;
            dungeon.cells[x as usize][y as usize].tile = Some(door.clone());
        }
        dungeon.clone()
    }
}
<commit_msg>Calculate connectors.<commit_after>use dungeon::{Dungeon};
use celloption::{Occupant};
use genotype::{Genotype};
use phenotype::{Seed};
use config::{Config};
use util::{odds};

use std::iter::{range_step};
use std::collections::{HashMap, HashSet};
use rand::{Rng};

#[derive(Clone, Debug)]
pub struct DesirableProperties {
    seed: Seed,
    room_number: u32,
    room_size: u32,
    doors: u32,
    monsters: u32,
    path_length: u32,
    branching: f64,
    occupants: Vec<(Occupant, (u32, u32))>,
    rooms: Vec<Room>,
    mazes: Vec<Maze>,
    connectors: Vec<Connector>,
}

#[derive(Clone, Debug)]
struct Room {
    x: u32,
    y: u32,
    w: u32,
    h: u32,
    region: u32,
}

#[derive(Clone, Debug)]
struct Maze {
    path: HashSet<(u32, u32)>,
    region: u32,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
enum Direction {
    North,
    East,
    South,
    West
}

static CARDINALS: [(Direction, (i32, i32)); 4] = [(Direction::North, (0, 1)),
                                                  (Direction::East, (1, 0)),
                                                  (Direction::South, (0, -1)),
                                                  (Direction::West, (-1, 0))];

// helper function: given a coordinate and a relative direction, get
// the coordinate n spaces away in that direction.
fn scale(coord: (u32, u32), dir: (i32, i32), n: i32) -> (u32, u32) {
    let (x, y) = coord;
    let (dx, dy) = dir;
    (((x as i32 + dx * n) as u32), ((y as i32 + dy * n) as u32))
}

#[derive(Clone, Debug)]
struct Connector {
    location: (u32, u32),
    regions: HashSet<u32>,
}

impl Connector {
    pub fn new(location: (u32, u32), regions: &HashSet<u32>) -> Connector {
        Connector {
            location: location,
            regions: regions.clone(),
        }
    }

    pub fn find_all(mazes: &Vec<Maze>, rooms: &Vec<Room>) -> Vec<Connector> {
        // build up a hashmap of coords to region id
        let mut lookup: HashMap<(u32, u32), u32> = HashMap::new();
        for maze in mazes {
            for coord in maze.clone().path {
                lookup.insert(coord, maze.region);
            }
        }
        for room in rooms {
            for coord in room.border() {
                lookup.insert(coord, room.region);
            }
        }
        // find connectors (blank spaces between two regions)
        let mut connectors: Vec<Connector> = Vec::new();
        let mut examined: HashSet<(u32, u32)> = HashSet::new();
        for (&coord, &region) in lookup.iter() {
            examined.insert(coord);
            let possibles: Vec<(u32, u32)> = CARDINALS.iter().map(|&(_, rel_dir)| scale(coord, rel_dir, 1)).collect();
            for new_coord in possibles {
                if !examined.contains(&new_coord) || !lookup.contains_key(&new_coord) {
                    let regions: HashSet<u32> = CARDINALS.iter().map(|&(_, rel_dir)| {
                        let coord = scale(new_coord, rel_dir, 1);
                        if lookup.contains_key(&coord) {
                            lookup[coord]
                        } else {
                            region
                        }
                    }).collect();
                    if regions.len() >= 2 {
                        let connector = Connector::new(new_coord, &regions);
                        connectors.push(connector);
                    }
                    examined.insert(new_coord);
                }
            }
        }
        connectors
    }
}

pub type CollisionFn<'a> = Box<Fn(&(u32, u32)) -> bool + 'a>;

impl Maze {
    pub fn new<T: Rng>(rng: &mut T,
                       previous: &HashSet<(u32, u32)>,
                       collides: CollisionFn,
                       branching: f64,
                       region: u32,
                       x: u32,
                       y: u32) -> Maze {
        let path = Maze::grow(rng, previous, collides, branching, x, y);
        Maze {
            region: region,
            path: path
        }
    }

    fn grow<T: Rng>(rng: &mut T,
                    previous: &HashSet<(u32, u32)>,
                    collides: CollisionFn,
                    branching: f64,
                    orig_x: u32,
                    orig_y: u32) -> HashSet<(u32, u32)> {
        let branching_factor = (branching * 100.0) as u64;
        let mut path: Vec<(u32, u32)> = Vec::new();
        let mut all_paths: HashSet<(u32, u32)> = previous.clone();
        let all = vec!(Direction::North, Direction::East, Direction::South, Direction::West);
        let mut direction = rng.choose(all.as_slice()).unwrap().clone();
        path.push((orig_x, orig_y));
        all_paths.insert((orig_x, orig_y));
        // "growing-tree" algorithm
        while !path.is_empty() {
            let new_coord = path[path.len()-1];
            let uncarved: HashMap<Direction, (i32, i32)> = CARDINALS.iter().filter(|&&(_, new_dir)| {
                let coord1 = scale(new_coord, new_dir, 1);
                let coord2 = scale(new_coord, new_dir, 2);
                let coord3 = scale(new_coord, new_dir, 3);
                !all_paths.contains(&coord1) &&
                    !all_paths.contains(&coord2) &&
                    !all_paths.contains(&coord3) &&
                    !collides(&coord2) &&
                    !collides(&coord3)
            }).cloned().collect();
            if !uncarved.is_empty() {
                let same_direction = odds(rng, branching_factor, 100);
                let rel_dir = if same_direction && uncarved.contains_key(&direction) {
                    uncarved[direction]
                } else {
                    let (dir, coords) = uncarved.into_iter().next().unwrap();
                    direction = dir;
                    coords
                };
                let coord1 = scale(new_coord, rel_dir, 1);
                let coord2 = scale(new_coord, rel_dir, 2);
                all_paths.insert(coord1);
                all_paths.insert(coord2);
                path.push(coord2);
            } else {
                path.pop();
            }
        }
        all_paths.difference(previous).cloned().collect()
    }
}

impl Room {
    pub fn random<T: Rng>(rng: &mut T, width: u32, height: u32, room_size: u32, region: u32) -> Room {
        let w: u32 = rng.gen_range(3, room_size);
        let h: u32 = rng.gen_range(3, room_size);
        assert!(width >= w);
        assert!(height >= h);
        let x: u32 = rng.gen_range(1, width - w);
        let y: u32 = rng.gen_range(1, height - h);
        let make_odd = |n| if n % 2 == 0 { n - 1 } else { n };
        Room {
            x: make_odd(x),
            y: make_odd(y),
            w: make_odd(w),
            h: make_odd(h),
            region: region,
        }
    }

    pub fn intersects(&self, rooms: &Vec<Room>) -> bool {
        for r in rooms {
            let rw = r.x + r.w;
            let rh = r.y + r.h;
            let roomw = self.x + self.w;
            let roomh = self.y + self.h;
            if roomw > r.x && roomh > r.y && self.x < rw && self.y < rh {
                return true
            }
        }
        false
    }

    pub fn contains(&self, x: u32, y: u32) -> bool {
        let roomw = self.x + self.w;
        let roomh = self.y + self.h;
        x >= self.x && x < roomw && y >= self.y && y < roomh
    }

    pub fn border(&self) -> Vec<(u32, u32)> {
        let mut surrounding = vec![];
        for i in range(0, self.w) {
            surrounding.push(((self.x + i), self.y));
            surrounding.push(((self.x + i), self.y + self.h - 1));
        }
        for i in range(0, self.h) {
            surrounding.push((self.x, self.y + i));
            surrounding.push((self.x + self.w - 1, self.y + i));
        }
        surrounding
    }
}

impl DesirableProperties {
    pub fn new(config: &Config, seed: &Seed) -> DesirableProperties {
        // read in the configurations
        let desirables = config.get_table(None, "desirable_patterns");
        let room_number = config.get_integer(desirables, "room_number") as u32;
        let room_size = config.get_integer(desirables, "room_size") as u32;
        let doors = config.get_integer(desirables, "doors") as u32;
        let monsters = config.get_integer(desirables, "monsters") as u32;
        let path_length = config.get_integer(desirables, "path_length") as u32;
        let branching = config.get_float(desirables, "branching");
        DesirableProperties {
            seed: seed.clone(),
            room_size: room_size,
            room_number: room_number,
            doors: doors,
            monsters: monsters,
            path_length: path_length,
            branching: branching,
            occupants: vec![],
            rooms: vec![],
            mazes: vec![],
            connectors: vec![],
        }
    }

}

impl Genotype for DesirableProperties {
    fn initialize<T: Rng>(&self, rng: &mut T) -> DesirableProperties {
        let w = self.seed.width;
        let h = self.seed.height;
        let occupants = self.seed.random_occupants(rng).iter().take(self.monsters as usize).cloned().collect();
        let mut region = 0;
        // randomly generate rooms
        let mut rooms = vec![];
        for _ in range(0, self.room_number) {
            for _ in range(0, 10) {
                let room = Room::random(rng, w, h, self.room_size, region);
                if !room.intersects(&rooms) {
                    rooms.push(room);
                    region += 1;
                    break;
                }
            }
        }
        // fill in mazes
        let mut mazes = vec![];
        let mut positions: HashSet<(u32, u32)> = HashSet::new();
        let is_occupied = |x, y| rooms.clone().iter().fold(false, |accum, ref m| accum || m.contains(x, y));
        for x in range_step(1, w, 2) {
            for y in range_step(1, h, 2) {
                if !is_occupied(x, y) && !positions.contains(&(x, y)) {
                    let collides: CollisionFn = box |&(cx, cy)| cx >= w || cy >= h || is_occupied(cx, cy);
                    let maze = Maze::new(rng, &positions, collides, self.branching, region, x, y);
                    positions = positions.union(&maze.path).cloned().collect();
                    mazes.push(maze);
                    region += 1;
                }
            }
        }
        // find connectors
        let connectors = Connector::find_all(&mazes, &rooms);
        // remove dead ends
        DesirableProperties {
            seed: self.seed.clone(),
            room_number: self.room_number,
            room_size: self.room_size,
            doors: self.doors,
            monsters: self.monsters,
            path_length: self.path_length,
            branching: self.branching,
            occupants: occupants,
            rooms: rooms.clone(),
            mazes: mazes,
            connectors: connectors,
        }
    }

    fn mutate<T: Rng>(&mut self, _: &mut T, _: f64) {
        // mutate a certain % of the rooms and start again
    }

    fn generate(&self) -> Dungeon {
        let w = self.seed.width;
        let h = self.seed.height;
        let mut dungeon = Dungeon::new(w, h, None);
        let wall = self.seed.tiles.get("wall").unwrap();
        let door = self.seed.tiles.get("door").unwrap();
        let floor = self.seed.tiles.get("floor").unwrap();
        for room in self.rooms.iter() {
            for i in range(room.x, room.x + room.w) {
                for j in range(room.y, room.y + room.h) {
                    dungeon.cells[i as usize][j as usize].tile = Some(wall.clone())
                }
            }
            // will overdraw, but that's OK.
            for (i, j) in room.border() {
                dungeon.cells[i as usize][j as usize].tile = Some(floor.clone())
            }
        }
        for maze in self.mazes.iter() {
            for path in maze.path.iter() {
                let (x, y): (u32, u32) = *path;
                dungeon.cells[x as usize][y as usize].tile = Some(floor.clone());
            }
        }
        for connector in self.connectors.iter() {
            let (x, y) = connector.location;
            dungeon.cells[x as usize][y as usize].tile = Some(door.clone());
        }
        dungeon.clone()
    }
}
<|endoftext|>


<commit_before>/*
 * An example redis server accepting GET and SET requests
 * listening on 127.0.0.1:8000.
 *
 * You can test it with "redis-cli -p 8000".
 *
 * Copyright (c) 2014 by Michael Neumann
 *
 */

extern crate redis = "redis#0.1";
extern crate sync = "sync#0.10-pre";

use std::io::net::ip::SocketAddr;
use std::io::net::tcp::{TcpListener,TcpStream};
use std::io::{Listener,Acceptor,Writer};
use std::io::BufferedStream;
use std::task;
use std::hashmap::HashMap;
use sync::RWArc;

fn handle_connection(conn: TcpStream, shared_ht: RWArc<HashMap<~[u8],~[u8]>>) {
    debug!("Got connection");

    let mut io = BufferedStream::new(conn);

    loop {
        match redis::parse(&mut io).unwrap() {
            redis::List(ref lst) => {
                match (lst.len(), lst.get(0), lst.get(1), lst.get(2)) {
                    (2, Some(redis::Data(/*GET*/[71, 69, 84])), Some(redis::Data(key)))  => {
                        debug!("GET: {:s}", std::str::from_utf8(key).unwrap());
                        let mut cwr = redis::CommandWriter::new();
                        shared_ht.read(|ht| {
                            match ht.find(&key) {
                                Some(val) => {
                                    cwr.args(1);
                                    cwr.arg_bin(*val);
                                }
                                None => {
                                    cwr.nil();
                                }
                            }
                        });
                        cwr.with_buf(|bytes| {io.write(bytes); io.flush()});
                        continue;
                    }

                    (3, redis::Data(/*SET*/[83, 69, 84]), redis::Data(key),
                                                          redis::Data(val)) => {

                        debug!("SET: {:s} {:?}", std::str::from_utf8(key).unwrap(), val);
                        shared_ht.write(|ht| ht.insert(key.clone(), val.clone()));
                        let mut cwr = redis::CommandWriter::new();
                        cwr.status("OK");
                        cwr.with_buf(|bytes| {io.write(bytes); io.flush()});
                        continue;
                    }

                    _ => { /* fallthrough: error */ }
                }
            }
            _ => { /* fallthrough: error */ }
        }

        /* error */
        let mut cwr = redis::CommandWriter::new();
        cwr.error("Invalid Command");
        cwr.with_buf(|bytes| {io.write(bytes); io.flush()});
    }
}

fn main() {
    let addr: SocketAddr = from_str("127.0.0.1:8000").unwrap();
    let shared_ht = RWArc::new(HashMap::new());

    match TcpListener::bind(addr) {
        Ok(listener) => {
            match listener.listen() {
                Ok(ref mut acceptor) => {
                    loop {
                        match acceptor.accept() {
                            Ok(conn) => {
                                let ht = shared_ht.clone();
                                task::spawn(proc() {
                                    handle_connection(conn, ht)
                                });
                            }
                            Err(_) => {}
                        }
                    }
                }
                Err(_) => {}
            }
        }
        Err(_) => {}
    }
}
<commit_msg>Get rid of all vector patterns<commit_after>/*
 * An example redis server accepting GET and SET requests
 * listening on 127.0.0.1:8000.
 *
 * You can test it with "redis-cli -p 8000".
 *
 * Copyright (c) 2014 by Michael Neumann
 *
 */

extern crate redis = "redis#0.1";
extern crate sync = "sync#0.10-pre";

use std::io::net::ip::SocketAddr;
use std::io::net::tcp::{TcpListener,TcpStream};
use std::io::{Listener,Acceptor,Writer};
use std::io::BufferedStream;
use std::task;
use std::hashmap::HashMap;
use sync::RWArc;

fn handle_connection(conn: TcpStream, shared_ht: RWArc<HashMap<~[u8],~[u8]>>) {
    debug!("Got connection");

    let mut io = BufferedStream::new(conn);

    loop {
        match redis::parse(&mut io).unwrap() {
            redis::List(ref lst) => {
                match lst.get(0) {
                    Some(redis::Data(ref command)) {
                        if command == bytes!("GET") {
                            match (lst.len(), lst.get(1)) {
                                (2, Some(redis::Data(key)))  => {
                                    debug!("GET: {:s}", std::str::from_utf8(key).unwrap());
                                    let mut cwr = redis::CommandWriter::new();
                                    shared_ht.read(|ht| {
                                        match ht.find(&key) {
                                            Some(val) => {
                                                cwr.args(1);
                                                cwr.arg_bin(*val);
                                            }
                                            None => {
                                                cwr.nil();
                                            }
                                        }
                                    });
                                    cwr.with_buf(|bytes| {io.write(bytes); io.flush()});
                                    continue;
                                }
                                _ => { /* fallthrough: error */ }
                            }
                        }
                        else if command == bytes!("SET") {
                            match (lst.len(), lst.get(1), lst.get(2)) {
                                (3, redis::Data(key), redis::Data(val)) => {
                                    debug!("SET: {:s} {:?}", std::str::from_utf8(key).unwrap(), val);
                                    shared_ht.write(|ht| ht.insert(key.clone(), val.clone()));
                                    let mut cwr = redis::CommandWriter::new();
                                    cwr.status("OK");
                                    cwr.with_buf(|bytes| {io.write(bytes); io.flush()});
                                    continue;
                                }
                                _ => { /* fallthrough: error */ }
                            }
                        }
                        else {
                            /* fallthrough: error */
                        }
                    }
                    _ => { /* fallthrough: error */ }
                }
            }
            _ => { /* fallthrough: error */ }
        }

        /* error */
        let mut cwr = redis::CommandWriter::new();
        cwr.error("Invalid Command");
        cwr.with_buf(|bytes| {io.write(bytes); io.flush()});
    }
}

fn main() {
    let addr: SocketAddr = from_str("127.0.0.1:8000").unwrap();
    let shared_ht = RWArc::new(HashMap::new());

    match TcpListener::bind(addr) {
        Ok(listener) => {
            match listener.listen() {
                Ok(ref mut acceptor) => {
                    loop {
                        match acceptor.accept() {
                            Ok(conn) => {
                                let ht = shared_ht.clone();
                                task::spawn(proc() {
                                    handle_connection(conn, ht)
                                });
                            }
                            Err(_) => {}
                        }
                    }
                }
                Err(_) => {}
            }
        }
        Err(_) => {}
    }
}
<|endoftext|>


<commit_before>extern crate clingo;
extern crate rand;

use std::env;
use rand::distributions::{IndependentSample, Range};
use std::sync::atomic::{AtomicBool, Ordering};
use clingo::*;

extern "C" fn on_event(
    etype: clingo_solve_event_type_t,
    event: *mut ::std::os::raw::c_void,
    data: *mut ::std::os::raw::c_void,
    goon: *mut bool,
) -> bool {
    if etype == clingo_solve_event_type_finish as u32 {
        let atomic_bool = unsafe { (data as *mut AtomicBool).as_ref() }.unwrap();
        atomic_bool.store(false, Ordering::Relaxed);
    }
    true
}

fn main() {

    // collect clingo options from the command line
    let options = env::args().skip(1).collect();

    // create a control object and pass command line arguments
    let logger = None;
    let logger_data = std::ptr::null_mut();
    let ctl = ClingoControl::new(options, logger, logger_data, 20)
        .expect("Failed creating ClingoControl.");

    // add a logic program to the base part
    let parameters: Vec<&str> = Vec::new();
    ctl.add(
        "base",
        parameters,
        "#const n = 17.\
         1 { p(X); q(X) } 1 :- X = 1..n.\
         :- not n+1 { p(1..n); \
         q(1..n) }.",
    ).expect("Failed to add a logic program.");

    // ground the base part
    let part = ClingoPart::new_part("base", &[]);
    let parts = vec![part];
    let ground_callback = None;
    let ground_callback_data = std::ptr::null_mut();
    ctl.ground(parts, ground_callback, ground_callback_data)
        .expect("Failed to ground a logic program.");

    // create a solve handle with an attached vent handler
    let assumptions = vec![];
    let solve_event_callback: ClingoSolveEventCallback = Some(on_event);
    let mut running = AtomicBool::new(true);
    let running_ref = &mut running as *mut std::sync::atomic::AtomicBool;
    let handle = ctl.solve(
        (clingo_solve_mode_async as clingo_solve_mode_bitset_t) +
            (clingo_solve_mode_yield as clingo_solve_mode_bitset_t),
        assumptions,
        solve_event_callback,
        running_ref as *mut std::os::raw::c_void,
    ).expect("Failed to retrieve solve handle.");

    // let's approximate pi
    let mut samples = 0.;
    let mut in_circle = 0.;
    let between = Range::new(-1f64, 1.);
    let mut rng = rand::thread_rng();

    while running.load(Ordering::Relaxed) {
        samples += 1.;
        let x = between.ind_sample(&mut rng);
        let y = between.ind_sample(&mut rng);
        if x * x + y * y <= 1. {
            in_circle += 1.;
        }
    }
    println!("pi = {}", 4. * in_circle / samples);

    // get the solve result
    handle.get().expect(
        "Failed to get result from solve handle.",
    );

    // close the handle
    handle.close().expect("Failed to close solve handle.");
}
<commit_msg>fix unused variables warning<commit_after>extern crate clingo;
extern crate rand;

use std::env;
use rand::distributions::{IndependentSample, Range};
use std::sync::atomic::{AtomicBool, Ordering};
use clingo::*;

extern "C" fn on_event(
    etype: clingo_solve_event_type_t,
    _event: *mut ::std::os::raw::c_void,
    data: *mut ::std::os::raw::c_void,
    _goon: *mut bool,
) -> bool {
    if etype == clingo_solve_event_type_finish as u32 {
        let atomic_bool = unsafe { (data as *mut AtomicBool).as_ref() }.unwrap();
        atomic_bool.store(false, Ordering::Relaxed);
    }
    true
}

fn main() {

    // collect clingo options from the command line
    let options = env::args().skip(1).collect();

    // create a control object and pass command line arguments
    let logger = None;
    let logger_data = std::ptr::null_mut();
    let ctl = ClingoControl::new(options, logger, logger_data, 20)
        .expect("Failed creating ClingoControl.");

    // add a logic program to the base part
    let parameters: Vec<&str> = Vec::new();
    ctl.add(
        "base",
        parameters,
        "#const n = 17.\
         1 { p(X); q(X) } 1 :- X = 1..n.\
         :- not n+1 { p(1..n); \
         q(1..n) }.",
    ).expect("Failed to add a logic program.");

    // ground the base part
    let part = ClingoPart::new_part("base", &[]);
    let parts = vec![part];
    let ground_callback = None;
    let ground_callback_data = std::ptr::null_mut();
    ctl.ground(parts, ground_callback, ground_callback_data)
        .expect("Failed to ground a logic program.");

    // create a solve handle with an attached vent handler
    let assumptions = vec![];
    let solve_event_callback: ClingoSolveEventCallback = Some(on_event);
    let mut running = AtomicBool::new(true);
    let running_ref = &mut running as *mut std::sync::atomic::AtomicBool;
    let handle = ctl.solve(
        (clingo_solve_mode_async as clingo_solve_mode_bitset_t) +
            (clingo_solve_mode_yield as clingo_solve_mode_bitset_t),
        assumptions,
        solve_event_callback,
        running_ref as *mut std::os::raw::c_void,
    ).expect("Failed to retrieve solve handle.");

    // let's approximate pi
    let mut samples = 0.;
    let mut in_circle = 0.;
    let between = Range::new(-1f64, 1.);
    let mut rng = rand::thread_rng();

    while running.load(Ordering::Relaxed) {
        samples += 1.;
        let x = between.ind_sample(&mut rng);
        let y = between.ind_sample(&mut rng);
        if x * x + y * y <= 1. {
            in_circle += 1.;
        }
    }
    println!("pi = {}", 4. * in_circle / samples);

    // get the solve result
    handle.get().expect(
        "Failed to get result from solve handle.",
    );

    // close the handle
    handle.close().expect("Failed to close solve handle.");
}
<|endoftext|>