<commit_before>use std::collections::HashMap;
use std::fmt;
use std::marker::PhantomData;
use std::ops::Deref;
use std::str::FromStr;

use antidote::{Mutex, RwLock};
use chrono::NaiveDateTime;
use irc::client::prelude::*;
use rand::{thread_rng, Rng};
use time;

use crate::plugin::*;
use crate::FrippyClient;
pub mod database;
use self::database::Database;

use self::error::*;
use crate::error::ErrorKind as FrippyErrorKind;
use crate::error::FrippyError;
use failure::ResultExt;

use frippy_derive::PluginName;

enum QuoteResponse {
    Public(String),
    Private(String),
}

#[derive(Clone)]
enum PreviousCommand {
    Get,
    GetUser(String, Option<i32>),
    Search(String, i32),
    SearchUser(String, String, i32),
}

#[derive(PluginName)]
pub struct Quote<T: Database, C: Client> {
    quotes: RwLock<T>,
    previous_map: Mutex<HashMap<String, PreviousCommand>>,
    phantom: PhantomData<C>,
}

impl<T: Database, C: Client> Quote<T, C> {
    pub fn new(db: T) -> Self {
        Quote {
            quotes: RwLock::new(db),
            previous_map: Mutex::new(HashMap::new()),
            phantom: PhantomData,
        }
    }

    fn create_quote(
        &self,
        quotee: &str,
        channel: &str,
        content: &str,
        author: &str,
    ) -> Result<&str, QuoteError> {
        let count = self.quotes.read().count_user_quotes(quotee, channel)?;
        let tm = time::now().to_timespec();

        let quote = database::NewQuote {
            quotee,
            channel,
            idx: count + 1,
            content,
            author,
            created: NaiveDateTime::from_timestamp(tm.sec, 0u32),
        };

        let response = self
            .quotes
            .write()
            .insert_quote(&quote)
            .map(|()| "Successfully added!")?;

        Ok(response)
    }

    fn add(&self, command: &mut PluginCommand) -> Result<&str, QuoteError> {
        if command.tokens.len() < 2 {
            Err(ErrorKind::InvalidCommand)?;
        }

        if command.target == command.source {
            Err(ErrorKind::PrivateMessageNotAllowed)?;
        }

        let quotee = command.tokens.remove(0);
        let channel = &command.target;
        let content = command.tokens.join(" ");

        Ok(self.create_quote(&quotee, channel, &content, &command.source)?)
    }

    fn get(&self, command: &PluginCommand) -> Result<String, QuoteError> {
        let tokens = command
            .tokens
            .iter()
            .filter(|t| !t.is_empty())
            .collect::<Vec<_>>();
        let quotee = &tokens.get(0);
        let channel = &command.target;

        match quotee {
            Some(quotee) => {
                let idx = match tokens.get(1) {
                    Some(s) => Some(i32::from_str(s).context(ErrorKind::InvalidIndex)?),
                    None => None,
                };

                self.get_user(quotee, channel, idx)
            }
            None => self.get_random(channel),
        }
    }

    fn get_user(
        &self,
        quotee: &str,
        channel: &str,
        idx: Option<i32>,
    ) -> Result<String, QuoteError> {
        let count = self.quotes.read().count_user_quotes(quotee, channel)?;
        if count < 1 {
            Err(ErrorKind::NotFound)?;
        }

        let mut idx = if let Some(idx) = idx {
            self.previous_map.lock().insert(
                channel.to_owned(),
                PreviousCommand::GetUser(quotee.to_owned(), Some(idx)),
            );

            idx
        } else {
            self.previous_map.lock().insert(
                channel.to_owned(),
                PreviousCommand::GetUser(quotee.to_owned(), None),
            );

            thread_rng().gen_range(1, count + 1)
        };

        if idx < 0 {
            idx += count + 1;
        }

        let quote = self
            .quotes
            .read()
            .get_user_quote(quotee, channel, idx)
            .context(ErrorKind::NotFound)?;

        let response = format!(
            "\"{}\" - {}[{}/{}]",
            quote.content, quote.quotee, quote.idx, count
        );

        Ok(response)
    }

    fn get_random(&self, channel: &str) -> Result<String, QuoteError> {
        let count = self.quotes.read().count_channel_quotes(channel)?;

        if count < 1 {
            Err(ErrorKind::NotFound)?;
        }
        self.previous_map
            .lock()
            .insert(channel.to_owned(), PreviousCommand::Get);

        let idx = thread_rng().gen_range(1, count + 1);

        let quote = self
            .quotes
            .read()
            .get_channel_quote(channel, idx)
            .context(ErrorKind::NotFound)?;

        Ok(format!(
            "\"{}\" - {}[{}]",
            quote.content, quote.quotee, quote.idx
        ))
    }

    fn search(&self, command: &mut PluginCommand) -> Result<String, QuoteError> {
        if command.tokens.len() < 2 {
            Err(ErrorKind::InvalidCommand)?;
        }

        let channel = &command.target;
        match command.tokens.remove(0).deref() {
            "user" => {
                let user = command.tokens.remove(0);

                if command.tokens.is_empty() {
                    Err(ErrorKind::InvalidCommand)?;
                }

                let query = command.tokens.join(" ");
                self.search_user(&user, channel, &query, 0)
            }
            "channel" => {
                if command.tokens.is_empty() {
                    Err(ErrorKind::InvalidCommand)?;
                }

                let query = command.tokens.join(" ");
                self.search_channel(channel, &query, 0)
            }
            _ => Err(ErrorKind::InvalidCommand.into()),
        }
    }

    fn next(&self, channel: String) -> Result<String, QuoteError> {
        let previous = self
            .previous_map
            .lock()
            .get(&channel)
            .cloned()
            .ok_or(ErrorKind::NoPrevious)?;

        match previous {
            PreviousCommand::Get => self.get_random(&channel),
            PreviousCommand::GetUser(user, idx) => {
                let idx = idx.map(|idx| if idx < 0 { idx - 1 } else { idx + 1 });

                self.get_user(&user, &channel, idx)
            }
            PreviousCommand::Search(query, offset) => {
                self.search_channel(&channel, &query, offset + 1)
            }
            PreviousCommand::SearchUser(user, query, offset) => {
                self.search_user(&user, &channel, &query, offset + 1)
            }
        }
    }

    fn search_user(
        &self,
        user: &str,
        channel: &str,
        query: &str,
        offset: i32,
    ) -> Result<String, QuoteError> {
        self.previous_map.lock().insert(
            channel.to_owned(),
            PreviousCommand::SearchUser(user.to_owned(), query.to_owned(), offset),
        );

        let quote = self
            .quotes
            .read()
            .search_user_quote(&query, &user, channel, offset)
            .context(ErrorKind::NotFound)?;

        let response = format!("\"{}\" - {}[{}]", quote.content, quote.quotee, quote.idx);

        Ok(response)
    }

    fn search_channel(
        &self,
        channel: &str,
        query: &str,
        offset: i32,
    ) -> Result<String, QuoteError> {
        self.previous_map.lock().insert(
            channel.to_owned(),
            PreviousCommand::Search(query.to_owned(), offset),
        );

        let quote = self
            .quotes
            .read()
            .search_channel_quote(&query, channel, offset)
            .context(ErrorKind::NotFound)?;

        let response = format!("\"{}\" - {}[{}]", quote.content, quote.quotee, quote.idx);

        Ok(response)
    }

    fn info(&self, command: &PluginCommand) -> Result<String, QuoteError> {
        let tokens = command
            .tokens
            .iter()
            .filter(|t| !t.is_empty())
            .collect::<Vec<_>>();
        match tokens.len() {
            0 => {
                let channel = &command.target;
                let count = self.quotes.read().count_channel_quotes(channel)?;

                Ok(match count {
                    0 => Err(ErrorKind::NotFound)?,
                    1 => format!("1 quote was saved in {}", channel),
                    _ => format!("{} quotes were saved in {}", count, channel),
                })
            }
            1 => {
                let quotee = &command.tokens[0];
                let channel = &command.target;
                let count = self.quotes.read().count_user_quotes(quotee, channel)?;

                Ok(match count {
                    0 => Err(ErrorKind::NotFound)?,
                    1 => format!("{} has 1 quote", quotee),
                    _ => format!("{} has {} quotes", quotee, count),
                })
            }
            _ => {
                let quotee = &command.tokens[0];
                let channel = &command.target;
                let idx = i32::from_str(&command.tokens[1]).context(ErrorKind::InvalidIndex)?;

                let idx = if idx < 0 {
                    self.quotes.read().count_user_quotes(quotee, channel)? + idx + 1
                } else {
                    idx
                };

                let quote = self
                    .quotes
                    .read()
                    .get_user_quote(quotee, channel, idx)
                    .context(ErrorKind::NotFound)?;

                Ok(format!(
                    "{}'s quote was added by {} at {} UTC",
                    quotee, quote.author, quote.created
                ))
            }
        }
    }

    fn help(&self) -> &str {
        "usage: quotes <subcommand>\r\n\
         subcommands: add, get, search, next, info, help"
    }
}

impl<T: Database, C: FrippyClient> Plugin for Quote<T, C> {
    type Client = C;
    fn execute(&self, _: &Self::Client, _: &Message) -> ExecutionStatus {
        ExecutionStatus::Done
    }

    fn execute_threaded(&self, _: &Self::Client, _: &Message) -> Result<(), FrippyError> {
        panic!("Quotes should not use threading")
    }

    fn command(
        &self,
        client: &Self::Client,
        mut command: PluginCommand,
    ) -> Result<(), FrippyError> {
        use self::QuoteResponse::{Private, Public};

        if command.tokens.is_empty() {
            client
                .send_notice(&command.source, &ErrorKind::InvalidCommand.to_string())
                .context(FrippyErrorKind::Connection)?;

            return Ok(());
        }

        let target = command.target.clone();
        let source = command.source.clone();

        let sub_command = command.tokens.remove(0);
        let result = match sub_command.as_ref() {
            "add" => self.add(&mut command).map(|s| Private(s.to_owned())),
            "get" => self.get(&command).map(Public),
            "search" => self.search(&mut command).map(Public),
            "next" => self.next(command.target).map(Public),
            "info" => self.info(&command).map(Public),
            "help" => Ok(Private(self.help().to_owned())),
            _ => Err(ErrorKind::InvalidCommand.into()),
        };

        match result {
            Ok(v) => match v {
                Public(m) => client
                    .send_privmsg(&target, &m)
                    .context(FrippyErrorKind::Connection)?,
                Private(m) => client
                    .send_notice(&source, &m)
                    .context(FrippyErrorKind::Connection)?,
            },
            Err(e) => {
                let message = e.to_string();
                client
                    .send_notice(&source, &message)
                    .context(FrippyErrorKind::Connection)?;
                Err(e).context(FrippyErrorKind::Quote)?
            }
        }

        Ok(())
    }

    fn evaluate(&self, _: &Self::Client, _: PluginCommand) -> Result<String, String> {
        Err(String::from(
            "Evaluation of commands is not implemented for Quote at this time",
        ))
    }
}

impl<T: Database, C: FrippyClient> fmt::Debug for Quote<T, C> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Quote {{ ... }}")
    }
}

pub mod error {
    use failure::Fail;
    use frippy_derive::Error;

    #[derive(Copy, Clone, Eq, PartialEq, Debug, Fail, Error)]
    #[error = "QuoteError"]
    pub enum ErrorKind {
        /// Invalid command error
        #[fail(display = "Incorrect command. Send \"quote help\" for help")]
        InvalidCommand,

        /// Invalid index error
        #[fail(display = "Invalid index")]
        InvalidIndex,

        /// No previous command error
        #[fail(display = "No previous command was found for this channel")]
        NoPrevious,

        /// Private message error
        #[fail(display = "You can only add quotes in channel messages")]
        PrivateMessageNotAllowed,

        /// Download  error
        #[fail(display = "Download failed")]
        Download,

        /// Duplicate error
        #[fail(display = "Entry already exists")]
        Duplicate,

        /// Not found error
        #[fail(display = "Quote was not found")]
        NotFound,

        /// MySQL error
        #[cfg(feature = "mysql")]
        #[fail(display = "Failed to execute MySQL Query")]
        MysqlError,

        /// No connection error
        #[cfg(feature = "mysql")]
        #[fail(display = "No connection to the database")]
        NoConnection,
    }
}
<commit_msg>Quote: Make subcommands case insensitive<commit_after>use std::collections::HashMap;
use std::fmt;
use std::marker::PhantomData;
use std::ops::Deref;
use std::str::FromStr;

use antidote::{Mutex, RwLock};
use chrono::NaiveDateTime;
use irc::client::prelude::*;
use rand::{thread_rng, Rng};
use time;

pub mod database;
use self::database::Database;

use crate::plugin::*;
use crate::FrippyClient;

use self::error::*;
use crate::error::ErrorKind as FrippyErrorKind;
use crate::error::FrippyError;
use failure::ResultExt;

use frippy_derive::PluginName;

enum QuoteResponse {
    Public(String),
    Private(String),
}

#[derive(Clone)]
enum PreviousCommand {
    Get,
    GetUser(String, Option<i32>),
    Search(String, i32),
    SearchUser(String, String, i32),
}

#[derive(PluginName)]
pub struct Quote<T: Database, C: Client> {
    quotes: RwLock<T>,
    previous_map: Mutex<HashMap<String, PreviousCommand>>,
    phantom: PhantomData<C>,
}

impl<T: Database, C: Client> Quote<T, C> {
    pub fn new(db: T) -> Self {
        Quote {
            quotes: RwLock::new(db),
            previous_map: Mutex::new(HashMap::new()),
            phantom: PhantomData,
        }
    }

    fn create_quote(
        &self,
        quotee: &str,
        channel: &str,
        content: &str,
        author: &str,
    ) -> Result<&str, QuoteError> {
        let count = self.quotes.read().count_user_quotes(quotee, channel)?;
        let tm = time::now().to_timespec();

        let quote = database::NewQuote {
            quotee,
            channel,
            idx: count + 1,
            content,
            author,
            created: NaiveDateTime::from_timestamp(tm.sec, 0u32),
        };

        let response = self
            .quotes
            .write()
            .insert_quote(&quote)
            .map(|()| "Successfully added!")?;

        Ok(response)
    }

    fn add(&self, command: &mut PluginCommand) -> Result<&str, QuoteError> {
        if command.tokens.len() < 2 {
            Err(ErrorKind::InvalidCommand)?;
        }

        if command.target == command.source {
            Err(ErrorKind::PrivateMessageNotAllowed)?;
        }

        let quotee = command.tokens.remove(0);
        let channel = &command.target;
        let content = command.tokens.join(" ");

        Ok(self.create_quote(&quotee, channel, &content, &command.source)?)
    }

    fn get(&self, command: &PluginCommand) -> Result<String, QuoteError> {
        let tokens = command
            .tokens
            .iter()
            .filter(|t| !t.is_empty())
            .collect::<Vec<_>>();
        let quotee = &tokens.get(0);
        let channel = &command.target;

        match quotee {
            Some(quotee) => {
                let idx = match tokens.get(1) {
                    Some(s) => Some(i32::from_str(s).context(ErrorKind::InvalidIndex)?),
                    None => None,
                };

                self.get_user(quotee, channel, idx)
            }
            None => self.get_random(channel),
        }
    }

    fn get_user(
        &self,
        quotee: &str,
        channel: &str,
        idx: Option<i32>,
    ) -> Result<String, QuoteError> {
        let count = self.quotes.read().count_user_quotes(quotee, channel)?;
        if count < 1 {
            Err(ErrorKind::NotFound)?;
        }

        let mut idx = if let Some(idx) = idx {
            self.previous_map.lock().insert(
                channel.to_owned(),
                PreviousCommand::GetUser(quotee.to_owned(), Some(idx)),
            );

            idx
        } else {
            self.previous_map.lock().insert(
                channel.to_owned(),
                PreviousCommand::GetUser(quotee.to_owned(), None),
            );

            thread_rng().gen_range(1, count + 1)
        };

        if idx < 0 {
            idx += count + 1;
        }

        let quote = self
            .quotes
            .read()
            .get_user_quote(quotee, channel, idx)
            .context(ErrorKind::NotFound)?;

        let response = format!(
            "\"{}\" - {}[{}/{}]",
            quote.content, quote.quotee, quote.idx, count
        );

        Ok(response)
    }

    fn get_random(&self, channel: &str) -> Result<String, QuoteError> {
        let count = self.quotes.read().count_channel_quotes(channel)?;

        if count < 1 {
            Err(ErrorKind::NotFound)?;
        }
        self.previous_map
            .lock()
            .insert(channel.to_owned(), PreviousCommand::Get);

        let idx = thread_rng().gen_range(1, count + 1);

        let quote = self
            .quotes
            .read()
            .get_channel_quote(channel, idx)
            .context(ErrorKind::NotFound)?;

        Ok(format!(
            "\"{}\" - {}[{}]",
            quote.content, quote.quotee, quote.idx
        ))
    }

    fn search(&self, command: &mut PluginCommand) -> Result<String, QuoteError> {
        if command.tokens.len() < 2 {
            Err(ErrorKind::InvalidCommand)?;
        }

        let channel = &command.target;
        match command.tokens.remove(0).deref() {
            "user" => {
                let user = command.tokens.remove(0);

                if command.tokens.is_empty() {
                    Err(ErrorKind::InvalidCommand)?;
                }

                let query = command.tokens.join(" ");
                self.search_user(&user, channel, &query, 0)
            }
            "channel" => {
                if command.tokens.is_empty() {
                    Err(ErrorKind::InvalidCommand)?;
                }

                let query = command.tokens.join(" ");
                self.search_channel(channel, &query, 0)
            }
            _ => Err(ErrorKind::InvalidCommand.into()),
        }
    }

    fn next(&self, channel: String) -> Result<String, QuoteError> {
        let previous = self
            .previous_map
            .lock()
            .get(&channel)
            .cloned()
            .ok_or(ErrorKind::NoPrevious)?;

        match previous {
            PreviousCommand::Get => self.get_random(&channel),
            PreviousCommand::GetUser(user, idx) => {
                let idx = idx.map(|idx| if idx < 0 { idx - 1 } else { idx + 1 });

                self.get_user(&user, &channel, idx)
            }
            PreviousCommand::Search(query, offset) => {
                self.search_channel(&channel, &query, offset + 1)
            }
            PreviousCommand::SearchUser(user, query, offset) => {
                self.search_user(&user, &channel, &query, offset + 1)
            }
        }
    }

    fn search_user(
        &self,
        user: &str,
        channel: &str,
        query: &str,
        offset: i32,
    ) -> Result<String, QuoteError> {
        self.previous_map.lock().insert(
            channel.to_owned(),
            PreviousCommand::SearchUser(user.to_owned(), query.to_owned(), offset),
        );

        let quote = self
            .quotes
            .read()
            .search_user_quote(&query, &user, channel, offset)
            .context(ErrorKind::NotFound)?;

        let response = format!("\"{}\" - {}[{}]", quote.content, quote.quotee, quote.idx);

        Ok(response)
    }

    fn search_channel(
        &self,
        channel: &str,
        query: &str,
        offset: i32,
    ) -> Result<String, QuoteError> {
        self.previous_map.lock().insert(
            channel.to_owned(),
            PreviousCommand::Search(query.to_owned(), offset),
        );

        let quote = self
            .quotes
            .read()
            .search_channel_quote(&query, channel, offset)
            .context(ErrorKind::NotFound)?;

        let response = format!("\"{}\" - {}[{}]", quote.content, quote.quotee, quote.idx);

        Ok(response)
    }

    fn info(&self, command: &PluginCommand) -> Result<String, QuoteError> {
        let tokens = command
            .tokens
            .iter()
            .filter(|t| !t.is_empty())
            .collect::<Vec<_>>();
        match tokens.len() {
            0 => {
                let channel = &command.target;
                let count = self.quotes.read().count_channel_quotes(channel)?;

                Ok(match count {
                    0 => Err(ErrorKind::NotFound)?,
                    1 => format!("1 quote was saved in {}", channel),
                    _ => format!("{} quotes were saved in {}", count, channel),
                })
            }
            1 => {
                let quotee = &command.tokens[0];
                let channel = &command.target;
                let count = self.quotes.read().count_user_quotes(quotee, channel)?;

                Ok(match count {
                    0 => Err(ErrorKind::NotFound)?,
                    1 => format!("{} has 1 quote", quotee),
                    _ => format!("{} has {} quotes", quotee, count),
                })
            }
            _ => {
                let quotee = &command.tokens[0];
                let channel = &command.target;
                let idx = i32::from_str(&command.tokens[1]).context(ErrorKind::InvalidIndex)?;

                let idx = if idx < 0 {
                    self.quotes.read().count_user_quotes(quotee, channel)? + idx + 1
                } else {
                    idx
                };

                let quote = self
                    .quotes
                    .read()
                    .get_user_quote(quotee, channel, idx)
                    .context(ErrorKind::NotFound)?;

                Ok(format!(
                    "{}'s quote was added by {} at {} UTC",
                    quotee, quote.author, quote.created
                ))
            }
        }
    }

    fn help(&self) -> &str {
        "usage: quotes <subcommand>\r\n\
         subcommands: add, get, search, next, info, help"
    }
}

impl<T: Database, C: FrippyClient> Plugin for Quote<T, C> {
    type Client = C;
    fn execute(&self, _: &Self::Client, _: &Message) -> ExecutionStatus {
        ExecutionStatus::Done
    }

    fn execute_threaded(&self, _: &Self::Client, _: &Message) -> Result<(), FrippyError> {
        panic!("Quotes should not use threading")
    }

    fn command(
        &self,
        client: &Self::Client,
        mut command: PluginCommand,
    ) -> Result<(), FrippyError> {
        use self::QuoteResponse::{Private, Public};

        if command.tokens.is_empty() {
            client
                .send_notice(&command.source, &ErrorKind::InvalidCommand.to_string())
                .context(FrippyErrorKind::Connection)?;

            return Ok(());
        }

        let target = command.target.clone();
        let source = command.source.clone();

        let sub_command = command.tokens.remove(0).to_lowercase();
        let result = match sub_command.as_ref() {
            "add" => self.add(&mut command).map(|s| Private(s.to_owned())),
            "get" => self.get(&command).map(Public),
            "search" => self.search(&mut command).map(Public),
            "next" => self.next(command.target).map(Public),
            "info" => self.info(&command).map(Public),
            "help" => Ok(Private(self.help().to_owned())),
            _ => Err(ErrorKind::InvalidCommand.into()),
        };

        match result {
            Ok(v) => match v {
                Public(m) => client
                    .send_privmsg(&target, &m)
                    .context(FrippyErrorKind::Connection)?,
                Private(m) => client
                    .send_notice(&source, &m)
                    .context(FrippyErrorKind::Connection)?,
            },
            Err(e) => {
                let message = e.to_string();
                client
                    .send_notice(&source, &message)
                    .context(FrippyErrorKind::Connection)?;
                Err(e).context(FrippyErrorKind::Quote)?
            }
        }

        Ok(())
    }

    fn evaluate(&self, _: &Self::Client, _: PluginCommand) -> Result<String, String> {
        Err(String::from(
            "Evaluation of commands is not implemented for Quote at this time",
        ))
    }
}

impl<T: Database, C: FrippyClient> fmt::Debug for Quote<T, C> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Quote {{ ... }}")
    }
}

pub mod error {
    use failure::Fail;
    use frippy_derive::Error;

    #[derive(Copy, Clone, Eq, PartialEq, Debug, Fail, Error)]
    #[error = "QuoteError"]
    pub enum ErrorKind {
        /// Invalid command error
        #[fail(display = "Incorrect command. Send \"quote help\" for help")]
        InvalidCommand,

        /// Invalid index error
        #[fail(display = "Invalid index")]
        InvalidIndex,

        /// No previous command error
        #[fail(display = "No previous command was found for this channel")]
        NoPrevious,

        /// Private message error
        #[fail(display = "You can only add quotes in channel messages")]
        PrivateMessageNotAllowed,

        /// Download  error
        #[fail(display = "Download failed")]
        Download,

        /// Duplicate error
        #[fail(display = "Entry already exists")]
        Duplicate,

        /// Not found error
        #[fail(display = "Quote was not found")]
        NotFound,

        /// MySQL error
        #[cfg(feature = "mysql")]
        #[fail(display = "Failed to execute MySQL Query")]
        MysqlError,

        /// No connection error
        #[cfg(feature = "mysql")]
        #[fail(display = "No connection to the database")]
        NoConnection,
    }
}
<|endoftext|>


<commit_before>s_no_extra_traits! {
    #[allow(missing_debug_implementations)]
    #[repr(align(16))]
    pub struct max_align_t {
        priv_: [f32; 8]
    }
}

s!{
    pub struct ucontext_t {
        pub uc_flags: ::c_ulong,
        pub uc_link: *mut ucontext_t,
        pub uc_stack: ::stack_t,
        pub uc_sigmask: ::sigset_t,
        pub uc_mcontext: mcontext_t,
    }

    #[repr(align(16))]
    pub struct mcontext_t {
        // What we want here is a single [u64; 36 + 512], but splitting things
        // up allows Debug to be auto-derived.
        __regs1: [[u64; 18]; 2], // 36
        __regs2: [[u64; 32]; 16], // 512
    }
}
<commit_msg>Auto merge of #2000 - lu-zero:aarch64-musl-mcontext_t, r=JohnTitor<commit_after>s_no_extra_traits! {
    #[allow(missing_debug_implementations)]
    #[repr(align(16))]
    pub struct max_align_t {
        priv_: [f32; 8]
    }
}

s! {
    pub struct ucontext_t {
        pub uc_flags: ::c_ulong,
        pub uc_link: *mut ucontext_t,
        pub uc_stack: ::stack_t,
        pub uc_sigmask: ::sigset_t,
        pub uc_mcontext: mcontext_t,
    }

    #[repr(align(16))]
    pub struct mcontext_t {
        pub fault_address: ::c_ulong,
        pub regs: [::c_ulong; 31],
        pub sp: ::c_ulong,
        pub pc: ::c_ulong,
        pub pstate: ::c_ulong,
        __reserved: [[u64; 32]; 16],
    }
}
<|endoftext|>


<commit_before>use std::collections::hash_set::HashSet;
use std::iter::FromIterator;

use api::server_data::ServerData;
use api::result::*;
use types::GeneUniquename;

#[derive(Serialize, Deserialize, Eq, PartialEq, Clone)]
pub enum QueryNode {
#[serde(rename = "or")]
    Or(Vec<QueryNode>),
#[serde(rename = "and")]
    And(Vec<QueryNode>),
#[serde(rename = "termid")]
    TermId(String),
#[serde(rename = "gene_list")]
    GeneList(Vec<GeneUniquename>),
}

fn exec_or(server_data: &ServerData, nodes: &Vec<QueryNode>) -> Result {
    if nodes.len() == 0 {
        return Result {
            status: ResultStatus::Error("illegal query: OR operator has no nodes".into()),
            rows: vec![],
        }
    }

    let mut seen_genes = HashSet::new();
    let mut or_rows = vec![];

    for node in nodes {
        let node_result = node.exec(server_data);
        if node_result.status != ResultStatus::Ok {
            return Result {
                status: node_result.status,
                rows: vec![],
            }
        }
        for node_row in &node_result.rows {
            if !seen_genes.contains(&node_row.gene_uniquename) {
                or_rows.push(ResultRow {
                    gene_uniquename: node_row.gene_uniquename.clone(),
                });
                seen_genes.insert(node_row.gene_uniquename.clone());
            }
        }
    }
    Result {
        status: ResultStatus::Ok,
        rows: or_rows
    }
}

fn exec_and(server_data: &ServerData, nodes: &Vec<QueryNode>) -> Result {
    if nodes.len() == 0 {
        return Result {
            status: ResultStatus::Error("illegal query: AND operator has no nodes".into()),
            rows: vec![],
        };
    }

    let first_node_result = nodes[0].exec(server_data);

    if first_node_result.status != ResultStatus::Ok {
        return Result {
            status: first_node_result.status,
            rows: vec![],
        };
    }

    let current_genes =
        first_node_result.rows.into_iter().map(|row| row.gene_uniquename);

    let mut current_gene_set =
        HashSet::from_iter(current_genes);

    for node in nodes[1..].iter() {
        let node_result = node.exec(server_data);
        if node_result.status != ResultStatus::Ok {
            return Result {
                status: node_result.status,
                rows: vec![],
            }
        }

        let node_genes =
            node_result.rows.into_iter().map(|row| row.gene_uniquename)
            .collect::<HashSet<_>>();

        current_gene_set = current_gene_set.intersection(&node_genes).cloned().collect();
    }
    Result {
        status: ResultStatus::Ok,
        rows: current_gene_set.iter().map(|gene_uniquename| ResultRow {
            gene_uniquename: gene_uniquename.clone()
        }).collect(),
    }
}

fn exec_termid(server_data: &ServerData, term_id: &str) -> Result {
    let rows = server_data.genes_of_termid(term_id).iter()
        .map(|gene_uniquename| ResultRow { gene_uniquename: gene_uniquename.clone() })
        .collect::<Vec<_>>();

    Result {
        status: ResultStatus::Ok,
        rows: rows,
    }
}

fn exec_gene_list(gene_uniquenames: &Vec<GeneUniquename>) -> Result {
    Result {
        status: ResultStatus::Ok,
        rows: gene_uniquenames.iter()
            .map(|gene_uniquename| ResultRow {
                gene_uniquename: gene_uniquename.clone(),
            }).collect(),
    }
}

impl QueryNode {
    pub fn exec(&self, server_data: &ServerData) -> Result {
        use self::QueryNode::*;
        match *self {
            Or(ref nodes) => exec_or(server_data, nodes),
            And(ref nodes) => exec_and(server_data, nodes),
            TermId(ref term_id) => exec_termid(server_data, term_id),
            GeneList(ref gene_list) => exec_gene_list(gene_list),
        }
    }
}

#[derive(Serialize, Deserialize)]
pub struct Query {
    constraints: QueryNode,
}

impl Query {
    pub fn from_node(node: QueryNode) -> Query {
        Query {
            constraints: node
        }
    }

    pub fn exec(&self, server_data: &ServerData) -> Result {
        self.constraints.exec(server_data)
    }
}
<commit_msg>Change gene-list JSON representation<commit_after>use std::collections::hash_set::HashSet;
use std::iter::FromIterator;

use api::server_data::ServerData;
use api::result::*;
use types::GeneUniquename;

#[derive(Serialize, Deserialize, Eq, PartialEq, Clone)]
pub enum QueryNode {
#[serde(rename = "or")]
    Or(Vec<QueryNode>),
#[serde(rename = "and")]
    And(Vec<QueryNode>),
#[serde(rename = "termid")]
    TermId(String),
#[serde(rename = "genelist")]
    GeneList(Vec<GeneUniquename>),
}

fn exec_or(server_data: &ServerData, nodes: &Vec<QueryNode>) -> Result {
    if nodes.len() == 0 {
        return Result {
            status: ResultStatus::Error("illegal query: OR operator has no nodes".into()),
            rows: vec![],
        }
    }

    let mut seen_genes = HashSet::new();
    let mut or_rows = vec![];

    for node in nodes {
        let node_result = node.exec(server_data);
        if node_result.status != ResultStatus::Ok {
            return Result {
                status: node_result.status,
                rows: vec![],
            }
        }
        for node_row in &node_result.rows {
            if !seen_genes.contains(&node_row.gene_uniquename) {
                or_rows.push(ResultRow {
                    gene_uniquename: node_row.gene_uniquename.clone(),
                });
                seen_genes.insert(node_row.gene_uniquename.clone());
            }
        }
    }
    Result {
        status: ResultStatus::Ok,
        rows: or_rows
    }
}

fn exec_and(server_data: &ServerData, nodes: &Vec<QueryNode>) -> Result {
    if nodes.len() == 0 {
        return Result {
            status: ResultStatus::Error("illegal query: AND operator has no nodes".into()),
            rows: vec![],
        };
    }

    let first_node_result = nodes[0].exec(server_data);

    if first_node_result.status != ResultStatus::Ok {
        return Result {
            status: first_node_result.status,
            rows: vec![],
        };
    }

    let current_genes =
        first_node_result.rows.into_iter().map(|row| row.gene_uniquename);

    let mut current_gene_set =
        HashSet::from_iter(current_genes);

    for node in nodes[1..].iter() {
        let node_result = node.exec(server_data);
        if node_result.status != ResultStatus::Ok {
            return Result {
                status: node_result.status,
                rows: vec![],
            }
        }

        let node_genes =
            node_result.rows.into_iter().map(|row| row.gene_uniquename)
            .collect::<HashSet<_>>();

        current_gene_set = current_gene_set.intersection(&node_genes).cloned().collect();
    }
    Result {
        status: ResultStatus::Ok,
        rows: current_gene_set.iter().map(|gene_uniquename| ResultRow {
            gene_uniquename: gene_uniquename.clone()
        }).collect(),
    }
}

fn exec_termid(server_data: &ServerData, term_id: &str) -> Result {
    let rows = server_data.genes_of_termid(term_id).iter()
        .map(|gene_uniquename| ResultRow { gene_uniquename: gene_uniquename.clone() })
        .collect::<Vec<_>>();

    Result {
        status: ResultStatus::Ok,
        rows: rows,
    }
}

fn exec_gene_list(gene_uniquenames: &Vec<GeneUniquename>) -> Result {
    Result {
        status: ResultStatus::Ok,
        rows: gene_uniquenames.iter()
            .map(|gene_uniquename| ResultRow {
                gene_uniquename: gene_uniquename.clone(),
            }).collect(),
    }
}

impl QueryNode {
    pub fn exec(&self, server_data: &ServerData) -> Result {
        use self::QueryNode::*;
        match *self {
            Or(ref nodes) => exec_or(server_data, nodes),
            And(ref nodes) => exec_and(server_data, nodes),
            TermId(ref term_id) => exec_termid(server_data, term_id),
            GeneList(ref gene_list) => exec_gene_list(gene_list),
        }
    }
}

#[derive(Serialize, Deserialize)]
pub struct Query {
    constraints: QueryNode,
}

impl Query {
    pub fn from_node(node: QueryNode) -> Query {
        Query {
            constraints: node
        }
    }

    pub fn exec(&self, server_data: &ServerData) -> Result {
        self.constraints.exec(server_data)
    }
}
<|endoftext|>


<commit_before>//! # Advent of Code 2016 - Day 2
//!
//! My solution to part 1 of Day 2 of the Advent of Code
//! 2016 challenge, "Bathroom Security." Full details of the
//! challenge can be found on [the challenge page][page].
//!
//! [page]: http://adventofcode.com/2016/day/2

pub trait Numpad: Sized + Copy {

    /// Returns the default starting position
    fn new() -> Self;

    /// Returns the numerical value of the button
    fn to_int(&self) -> u8;

    /// Consumes this button and returns the button that is
    /// above it.
    fn up(self) -> Self;

    /// Consumes this button and returns the button that is
    /// below it.
    fn down(self) -> Self;

    /// Consumes this button and returns the button that is
    /// to the left of it.
    fn left(self) -> Self;

    /// Consumes this button and returns the button that is
    /// to the right of it.
    fn right(self) -> Self;

    /// Interperates the first of the input str as a series of
    /// numpad instructions and returns the corresponding final button.
    fn find_button(self, instr_line: &str) -> Self {
                instr_line.chars()
                    .fold(self,
                          |button, direction| {
                              match direction {
                                  'L' => button.left(),
                                  'R' => button.right(),
                                  'U' => button.up(),
                                  'D' => button.down(),
                                  _   => button
                              }
                          })
            }
}

macro_rules! numpad_impl {
    (
        name => $name:ident ; start => $default:ident ;
        $(
            $button:ident => ($val:expr, $up:ident, $down:ident, $left:ident, $right:ident)
        ),+
    ) => {

        #[derive(Debug, Copy, Clone)]
        pub enum $name {
            $($button),+
        }

        impl Numpad for $name {
            fn new() -> Self {
                $name::$default
            }

            fn to_int(&self) -> u8 {
                match *self {
                    $($name::$button => $val),+
                }
            }

            fn up(self) -> Self {
                match self {
                    $($name::$button => $name::$up),+
                }
            }

            fn down(self) -> Self {
                match self {
                    $($name::$button => $name::$down),+
                }
            }

            fn left(self) -> Self {
                match self {
                    $($name::$button => $name::$left),+
                }
            }

            fn right(self) -> Self {
                match self {
                    $($name::$button => $name::$right),+
                }
            }
        }

    }
}

// 1 2 3
// 4 5 6
// 7 8 9

numpad_impl! {
    name => NumpadButton ; start => N5 ;
    // => (val, U , D , L , R )
    N1 => (0x1, N1, N4, N1, N2),
    N2 => (0x2, N2, N5, N1, N3),
    N3 => (0x3, N3, N6, N2, N3),
    N4 => (0x4, N1, N7, N4, N5),
    N5 => (0x5, N2, N8, N4, N6),
    N6 => (0x6, N3, N9, N5, N6),
    N7 => (0x7, N4, N7, N7, N8),
    N8 => (0x8, N5, N8, N7, N9),
    N9 => (0x9, N6, N9, N8, N9)
}

//     1
//   2 3 4
// 5 6 7 8 9
//   A B C
//     D
numpad_impl! {
    name => ActualButton; start => N5;
    // => (val, U , D , L , R )
    N1 => (0x1, N1, N3, N1, N1),
    N2 => (0x2, N2, N6, N2, N3),
    N3 => (0x3, N1, N7, N2, N4),
    N4 => (0x4, N4, N8, N3, N4),
    N5 => (0x5, N5, N5, N5, N6),
    N6 => (0x6, N2, Na, N5, N7),
    N7 => (0x7, N3, Nb, N6, N8),
    N8 => (0x8, N4, Nc, N7, N9),
    N9 => (0x9, N9, N9, N8, N9),
    Na => (0xa, N6, Na, Na, Nb),
    Nb => (0xb, N7, Nd, Na, Nc),
    Nc => (0xc, N8, Nc, Nb, Nc),
    Nd => (0xd, Nb, Nd, Nd, Nd)
}

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

    #[test]
    fn input_test() {
        let instructions = "ULL
RRDDD
LURDL
UUUUD";

        assert_eq!(find_door_code::<NumpadButton>(instructions),
                   vec![1, 9, 8, 5]);
    }

}

pub fn find_door_code<T: Numpad>(instructions: &str) -> Vec<u8> {
    let mut buttons = Vec::with_capacity(4);

    for (i, instr_line) in instructions.lines().enumerate() {
        let old_button = if i == 0 { T::new() } else { buttons[i-1] };
        let new_button = old_button.find_button(instr_line);

        buttons.push(new_button);
    }

    buttons.iter().map(T::to_int).collect()
}

fn main() {
    let challenge_input = "DLRURUDLULRDRUDDRLUUUDLDLDLRLRRDRRRLLLLLDDRRRDRRDRRRLRRURLRDUULRLRRDDLULRLLDUDLULURRLRLDUDLURURLDRDDULDRDRDLDLLULULLDDLRRUDULLUULRRLLLURDRLDDLDDLDRLRRLLRURRUURRRRLUDLRDDDDRDULRLLDDUURDUDRLUDULLUDLUDURRDRDUUUUDDUDLLLRLUULRUURDLRLLRRLRLLDLLRLLRRRURLRRLURRLDLLLUUDURUDDLLUURRDRDRRDLLDDLLRDRDRRLURLDLDRDLURLDULDRURRRUDLLULDUDRURULDUDLULULRRRUDLUURRDURRURRLRRLLRDDUUUUUDUULDRLDLLRRUDRRDULLLDUDDUDUURLRDLULUUDLDRDUUUDDDUDLDURRULUULUUULDRUDDLLLDLULLRLRLUDULLDLLRLDLDDDUUDURDDDLURDRRDDLDRLLRLRR
RLDUDURDRLLLLDDRRRURLLLRUUDDLRDRDDDUDLLUDDLRDURLDRDLLDRULDDRLDDDRLDRDDDRLLULDURRRLULDRLRDRDURURRDUDRURLDRLURDRLUULLULLDLUDUDRDRDDLDDDDRDURDLUDRDRURUDDLLLRLDDRURLLUDULULDDLLLDLUDLDULUUDLRLURLDRLURURRDUUDLRDDDDDRLDULUDLDDURDLURLUURDLURLDRURRLDLLRRUDRUULLRLDUUDURRLDURRLRUULDDLDLDUUDDRLDLLRRRUURLLUURURRURRLLLUDLDRRDLUULULUDDULLUDRLDDRURDRDUDULUDRLRRRUULLDRDRLULLLDURURURLURDLRRLLLDRLDUDLLLLDUUURULDDLDLLRRUDDDURULRLLUDLRDLUUDDRDDLLLRLUURLDLRUURDURDDDLLLLLULRRRURRDLUDLUURRDRLRUDUUUURRURLRDRRLRDRDULLDRDRLDURDDUURLRUDDDDDLRLLRUDDDDDURURRLDRRUUUDLURUUDRRDLLULDRRLRRRLUUUD
RDRURLLUUDURURDUUULLRDRLRRLRUDDUDRURLLDLUUDLRLLDDURRURLUDUDDURLURLRRURLLURRUDRUDLDRLLURLRUUURRUDDDURRRLULLLLURDLRLLDDRLDRLLRRDLURDLRDLDUDRUULLDUUUDLURRLLRUDDDUUURLURUUDRLRULUURLLRLUDDLLDURULLLDURDLULDLDDUDULUDDULLRDRURDRRLLDLDDDDRUDLDRRLLLRLLLRRULDLRLRLRLLDLRDRDLLUDRDRULDUURRDDDRLLRLDLDRDUDRULUDRDLDLDDLLRULURLLURDLRRDUDLULLDLULLUDRRDDRLRURRLDUDLRRUUDLDRLRLDRLRRDURRDRRDDULURUUDDUUULRLDRLLDURRDLUULLUDRDDDLRUDLRULLDDDLURLURLRDRLLURRRUDLRRLURDUUDRLRUUDUULLRUUUDUUDDUURULDLDLURLRURLRUDLULLULRULDRDRLLLRRDLU
RRRRDRLUUULLLRLDDLULRUUURRDRDRURRUURUDUULRULULRDRLRRLURDRRRULUUULRRUUULULRDDLLUURRLLDUDRLRRLDDLDLLDURLLUDLDDRRURLDLULRDUULDRLRDLLDLRULLRULLUDUDUDDUULDLUUDDLUDDUULLLLLURRDRULURDUUUDULRUDLLRUUULLUULLLRUUDDRRLRDUDDRULRDLDLLLLRLDDRRRULULLLDLRLURRDULRDRDUDDRLRLDRRDLRRRLLDLLDULLUDDUDDRULLLUDDRLLRRRLDRRURUUURRDLDLURRDLURULULRDUURLLULDULDUDLLULDDUURRRLDURDLUDURLDDRDUDDLLUULDRRLDLLUDRDURLLDRLDDUDURDLUUUUURRUULULLURLDUUULLRURLLLUURDULLUULDRULLUULRDRUULLRUDLDDLRLURRUUDRLRRRULRUUULRULRRLDLUDRRLL
ULRLDLLURDRRUULRDUDDURDDDLRRRURLDRUDDLUDDDLLLRDLRLLRRUUDRRDRUULLLULULUUDRRRDRDRUUUUULRURUULULLULDULURRLURUDRDRUDRURURUDLDURUDUDDDRLRLLLLURULUDLRLDDLRUDDUUDURUULRLLLDDLLLLRRRDDLRLUDDUULRRLLRDUDLLDLRRUUULRLRDLRDUDLLLDLRULDRURDLLULLLRRRURDLLUURUDDURLDUUDLLDDRUUDULDRDRDRDDUDURLRRRRUDURLRRUDUDUURDRDULRLRLLRLUDLURUDRUDLULLULRLLULRUDDURUURDLRUULDURDRRRLLLLLUUUULUULDLDULLRURLUDLDRLRLRLRDLDRUDULDDRRDURDDULRULDRLRULDRLDLLUDLDRLRLRUDRDDR";

    let door_code = find_door_code::<NumpadButton>(challenge_input);
    let actual_door_code = find_door_code::<ActualButton>(challenge_input);
    print!("Idealised Bathroom code = ");
    for code in door_code {
        print!("{:x}", code);
    }
    println!("");

    print!("Actual bathroom code = ");
    for code in actual_door_code {
        print!("{:X}", code);
    }
    println!("");
}
<commit_msg>Fixed indentation<commit_after>//! # Advent of Code 2016 - Day 2
//!
//! My solution to part 1 of Day 2 of the Advent of Code
//! 2016 challenge, "Bathroom Security." Full details of the
//! challenge can be found on [the challenge page][page].
//!
//! [page]: http://adventofcode.com/2016/day/2

pub trait Numpad: Sized + Copy {

    /// Returns the default starting position
    fn new() -> Self;

    /// Returns the numerical value of the button
    fn to_int(&self) -> u8;

    /// Consumes this button and returns the button that is
    /// above it.
    fn up(self) -> Self;

    /// Consumes this button and returns the button that is
    /// below it.
    fn down(self) -> Self;

    /// Consumes this button and returns the button that is
    /// to the left of it.
    fn left(self) -> Self;

    /// Consumes this button and returns the button that is
    /// to the right of it.
    fn right(self) -> Self;

    /// Interperates the first of the input str as a series of
    /// numpad instructions and returns the corresponding final button.
    fn find_button(self, instr_line: &str) -> Self {
        instr_line.chars()
            .fold(self,
                  |button, direction| {
                      match direction {
                          'L' => button.left(),
                          'R' => button.right(),
                          'U' => button.up(),
                          'D' => button.down(),
                          _   => button
                      }
                  })
    }
}

macro_rules! numpad_impl {
    (
        name => $name:ident ; start => $default:ident ;
        $(
            $button:ident => ($val:expr, $up:ident, $down:ident, $left:ident, $right:ident)
        ),+
    ) => {

        #[derive(Debug, Copy, Clone)]
        pub enum $name {
            $($button),+
        }

        impl Numpad for $name {
            fn new() -> Self {
                $name::$default
            }

            fn to_int(&self) -> u8 {
                match *self {
                    $($name::$button => $val),+
                }
            }

            fn up(self) -> Self {
                match self {
                    $($name::$button => $name::$up),+
                }
            }

            fn down(self) -> Self {
                match self {
                    $($name::$button => $name::$down),+
                }
            }

            fn left(self) -> Self {
                match self {
                    $($name::$button => $name::$left),+
                }
            }

            fn right(self) -> Self {
                match self {
                    $($name::$button => $name::$right),+
                }
            }
        }

    }
}

// 1 2 3
// 4 5 6
// 7 8 9

numpad_impl! {
    name => NumpadButton ; start => N5 ;
    // => (val, U , D , L , R )
    N1 => (0x1, N1, N4, N1, N2),
    N2 => (0x2, N2, N5, N1, N3),
    N3 => (0x3, N3, N6, N2, N3),
    N4 => (0x4, N1, N7, N4, N5),
    N5 => (0x5, N2, N8, N4, N6),
    N6 => (0x6, N3, N9, N5, N6),
    N7 => (0x7, N4, N7, N7, N8),
    N8 => (0x8, N5, N8, N7, N9),
    N9 => (0x9, N6, N9, N8, N9)
}

//     1
//   2 3 4
// 5 6 7 8 9
//   A B C
//     D
numpad_impl! {
    name => ActualButton; start => N5;
    // => (val, U , D , L , R )
    N1 => (0x1, N1, N3, N1, N1),
    N2 => (0x2, N2, N6, N2, N3),
    N3 => (0x3, N1, N7, N2, N4),
    N4 => (0x4, N4, N8, N3, N4),
    N5 => (0x5, N5, N5, N5, N6),
    N6 => (0x6, N2, Na, N5, N7),
    N7 => (0x7, N3, Nb, N6, N8),
    N8 => (0x8, N4, Nc, N7, N9),
    N9 => (0x9, N9, N9, N8, N9),
    Na => (0xa, N6, Na, Na, Nb),
    Nb => (0xb, N7, Nd, Na, Nc),
    Nc => (0xc, N8, Nc, Nb, Nc),
    Nd => (0xd, Nb, Nd, Nd, Nd)
}

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

    #[test]
    fn input_test() {
        let instructions = "ULL
RRDDD
LURDL
UUUUD";

        assert_eq!(find_door_code::<NumpadButton>(instructions),
                   vec![1, 9, 8, 5]);
    }

}

pub fn find_door_code<T: Numpad>(instructions: &str) -> Vec<u8> {
    let mut buttons = Vec::with_capacity(4);

    for (i, instr_line) in instructions.lines().enumerate() {
        let old_button = if i == 0 { T::new() } else { buttons[i-1] };
        let new_button = old_button.find_button(instr_line);

        buttons.push(new_button);
    }

    buttons.iter().map(T::to_int).collect()
}

fn main() {
    let challenge_input = "DLRURUDLULRDRUDDRLUUUDLDLDLRLRRDRRRLLLLLDDRRRDRRDRRRLRRURLRDUULRLRRDDLULRLLDUDLULURRLRLDUDLURURLDRDDULDRDRDLDLLULULLDDLRRUDULLUULRRLLLURDRLDDLDDLDRLRRLLRURRUURRRRLUDLRDDDDRDULRLLDDUURDUDRLUDULLUDLUDURRDRDUUUUDDUDLLLRLUULRUURDLRLLRRLRLLDLLRLLRRRURLRRLURRLDLLLUUDURUDDLLUURRDRDRRDLLDDLLRDRDRRLURLDLDRDLURLDULDRURRRUDLLULDUDRURULDUDLULULRRRUDLUURRDURRURRLRRLLRDDUUUUUDUULDRLDLLRRUDRRDULLLDUDDUDUURLRDLULUUDLDRDUUUDDDUDLDURRULUULUUULDRUDDLLLDLULLRLRLUDULLDLLRLDLDDDUUDURDDDLURDRRDDLDRLLRLRR
RLDUDURDRLLLLDDRRRURLLLRUUDDLRDRDDDUDLLUDDLRDURLDRDLLDRULDDRLDDDRLDRDDDRLLULDURRRLULDRLRDRDURURRDUDRURLDRLURDRLUULLULLDLUDUDRDRDDLDDDDRDURDLUDRDRURUDDLLLRLDDRURLLUDULULDDLLLDLUDLDULUUDLRLURLDRLURURRDUUDLRDDDDDRLDULUDLDDURDLURLUURDLURLDRURRLDLLRRUDRUULLRLDUUDURRLDURRLRUULDDLDLDUUDDRLDLLRRRUURLLUURURRURRLLLUDLDRRDLUULULUDDULLUDRLDDRURDRDUDULUDRLRRRUULLDRDRLULLLDURURURLURDLRRLLLDRLDUDLLLLDUUURULDDLDLLRRUDDDURULRLLUDLRDLUUDDRDDLLLRLUURLDLRUURDURDDDLLLLLULRRRURRDLUDLUURRDRLRUDUUUURRURLRDRRLRDRDULLDRDRLDURDDUURLRUDDDDDLRLLRUDDDDDURURRLDRRUUUDLURUUDRRDLLULDRRLRRRLUUUD
RDRURLLUUDURURDUUULLRDRLRRLRUDDUDRURLLDLUUDLRLLDDURRURLUDUDDURLURLRRURLLURRUDRUDLDRLLURLRUUURRUDDDURRRLULLLLURDLRLLDDRLDRLLRRDLURDLRDLDUDRUULLDUUUDLURRLLRUDDDUUURLURUUDRLRULUURLLRLUDDLLDURULLLDURDLULDLDDUDULUDDULLRDRURDRRLLDLDDDDRUDLDRRLLLRLLLRRULDLRLRLRLLDLRDRDLLUDRDRULDUURRDDDRLLRLDLDRDUDRULUDRDLDLDDLLRULURLLURDLRRDUDLULLDLULLUDRRDDRLRURRLDUDLRRUUDLDRLRLDRLRRDURRDRRDDULURUUDDUUULRLDRLLDURRDLUULLUDRDDDLRUDLRULLDDDLURLURLRDRLLURRRUDLRRLURDUUDRLRUUDUULLRUUUDUUDDUURULDLDLURLRURLRUDLULLULRULDRDRLLLRRDLU
RRRRDRLUUULLLRLDDLULRUUURRDRDRURRUURUDUULRULULRDRLRRLURDRRRULUUULRRUUULULRDDLLUURRLLDUDRLRRLDDLDLLDURLLUDLDDRRURLDLULRDUULDRLRDLLDLRULLRULLUDUDUDDUULDLUUDDLUDDUULLLLLURRDRULURDUUUDULRUDLLRUUULLUULLLRUUDDRRLRDUDDRULRDLDLLLLRLDDRRRULULLLDLRLURRDULRDRDUDDRLRLDRRDLRRRLLDLLDULLUDDUDDRULLLUDDRLLRRRLDRRURUUURRDLDLURRDLURULULRDUURLLULDULDUDLLULDDUURRRLDURDLUDURLDDRDUDDLLUULDRRLDLLUDRDURLLDRLDDUDURDLUUUUURRUULULLURLDUUULLRURLLLUURDULLUULDRULLUULRDRUULLRUDLDDLRLURRUUDRLRRRULRUUULRULRRLDLUDRRLL
ULRLDLLURDRRUULRDUDDURDDDLRRRURLDRUDDLUDDDLLLRDLRLLRRUUDRRDRUULLLULULUUDRRRDRDRUUUUULRURUULULLULDULURRLURUDRDRUDRURURUDLDURUDUDDDRLRLLLLURULUDLRLDDLRUDDUUDURUULRLLLDDLLLLRRRDDLRLUDDUULRRLLRDUDLLDLRRUUULRLRDLRDUDLLLDLRULDRURDLLULLLRRRURDLLUURUDDURLDUUDLLDDRUUDULDRDRDRDDUDURLRRRRUDURLRRUDUDUURDRDULRLRLLRLUDLURUDRUDLULLULRLLULRUDDURUURDLRUULDURDRRRLLLLLUUUULUULDLDULLRURLUDLDRLRLRLRDLDRUDULDDRRDURDDULRULDRLRULDRLDLLUDLDRLRLRUDRDDR";

    let door_code = find_door_code::<NumpadButton>(challenge_input);
    let actual_door_code = find_door_code::<ActualButton>(challenge_input);
    print!("Idealised Bathroom code = ");
    for code in door_code {
        print!("{:x}", code);
    }
    println!("");

    print!("Actual bathroom code = ");
    for code in actual_door_code {
        print!("{:X}", code);
    }
    println!("");
}
<|endoftext|>


<commit_before>#![allow(non_upper_case_globals)]
#![allow(non_snake_case)]
extern crate glfw;
use self::glfw::Context;

extern crate gl;
extern crate rand;
use self::rand::Rng;

use std::ffi::CStr;
use std::mem;
use std::os::raw::c_void;
use std::ptr;

use common::{process_events, processInput};
use shader::Shader;
use camera::Camera;
use model::Model;

use cgmath::{Matrix4, vec3, Point3, Vector4, Deg, perspective};
use cgmath::prelude::*;

// settings
const SCR_WIDTH: u32 = 1280;
const SCR_HEIGHT: u32 = 720;

pub fn main_4_10_3() {
    let mut camera = Camera {
        Position: Point3::new(0.0, 0.0, 155.0),
        ..Camera::default()
    };

    let mut firstMouse = true;
    let mut lastX: f32 = SCR_WIDTH as f32 / 2.0;
    let mut lastY: f32 = SCR_HEIGHT as f32 / 2.0;

    // timing
    let mut deltaTime: f32; // time between current frame and last frame
    let mut lastFrame: f32 = 0.0;

    // glfw: initialize and configure
    // ------------------------------
    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
    glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
    glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));
    #[cfg(target_os = "macos")]
    glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));

    // glfw window creation
    // --------------------
    let (mut window, events) = glfw.create_window(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", glfw::WindowMode::Windowed)
        .expect("Failed to create GLFW window");

    window.make_current();
    window.set_framebuffer_size_polling(true);
    window.set_cursor_pos_polling(true);
    window.set_scroll_polling(true);

    // tell GLFW to capture our mouse
    window.set_cursor_mode(glfw::CursorMode::Disabled);

    // gl: load all OpenGL function pointers
    // ---------------------------------------
    gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);

    let (asteroidShader, planetShader, rock, planet, amount) = unsafe {
        // configure global opengl state
        // -----------------------------
        gl::Enable(gl::DEPTH_TEST);

        // build and compile shaders
        // -------------------------
        let asteroidShader = Shader::new(
            "src/_4_advanced_opengl/shaders/10.3.asteroids.vs",
            "src/_4_advanced_opengl/shaders/10.3.asteroids.fs");
        let planetShader = Shader::new(
            "src/_4_advanced_opengl/shaders/10.3.planet.vs",
            "src/_4_advanced_opengl/shaders/10.3.planet.fs");

        // load models
        // -----------
        let rock = Model::new("resources/objects/rock/rock.obj");
        let planet = Model::new("resources/objects/planet/planet.obj");

        // generate a large list of semi-random model transformation matrices
        // ------------------------------------------------------------------
        let amount = 100000;
        let mut modelMatrices: Vec<Matrix4<f32>> = Vec::with_capacity(amount);
        let mut rng = rand::thread_rng();
        let radius = 150.0;
        let offset: f32 = 25.0;
        for i in 0..amount {
            let angle = i as i32 as f32 / amount as f32 * 360.0;
            let mut displacement = (rng.gen::<u32>() % (2.0 * offset * 100.0) as u32) as f32 / 100.0 - offset;
            let x = angle.sin() * radius + displacement;
            displacement = (rng.gen::<u32>() % (2.0 * offset * 100.0) as i32) as u32 / 100.0 - offset;
            let y = displacement * 0.4; // keep height of asteroid field smaller compared to width of x and z
            displacement = (rng.gen::<u32>() % (2.0 * offset * 100.0) as i32) as u32 / 100.0 - offset;
            let z = angle.cos() * radius + displacement;
            let mut model = Matrix4::<u32>::from_translation(vec3(x, y, z));

            // 2. scale: Scale between 0.05 and 0.25
            let scale = (rng.gen::<u32>() % 20) as f32 / 100.0 + 0.05;
            model = model * Matrix4::from_scale(scale);

            // 3. rotation: add random rotation around a (semi)randomly picked rotation axis vector
            let rotAngle = (rng.gen::<u32>() % 360) as f32;
            model = model * Matrix4::from_axis_angle(vec3(0.4, 0.6, 0.8).normalize(), Deg(rotAngle));

            // 4. now add to list of matrices
            modelMatrices.push(model);
        }

        // configure instanced array
        // -------------------------
        let mut buffer = 0;
        gl::GenBuffers(1, &mut buffer);
        gl::BindBuffer(gl::ARRAY_BUFFER, buffer);
        gl::BufferData(
            gl::ARRAY_BUFFER,
            (amount * mem::size_of::<Matrix4<f32>>()) as isize,
            &modelMatrices[0] as *const Matrix4<f32> as *const c_void,
            gl::STATIC_DRAW);

        // set transformation matrices as an instance vertex attribute (with divisor 1)
        // note: we're cheating a little by taking the, now publicly declared, VAO of the model's mesh(es) and adding new vertexAttribPointers
        // normally you'd want to do this in a more organized fashion, but for learning purposes this will do.
        // -----------------------------------------------------------------------------------------------------------------------------------
        let size_mat4 = mem::size_of::<Matrix4<f32>>() as i32;
        let size_vec4 = mem::size_of::<Vector4<f32>>() as i32;
        for mesh in &rock.meshes {
            let VAO = mesh.VAO;
            gl::BindVertexArray(VAO);
            // set attribute pointers for matrix (4 times vec4)
            gl::EnableVertexAttribArray(3);
            gl::VertexAttribPointer(3, 4, gl::FLOAT, gl::FALSE, size_mat4, ptr::null());
            gl::EnableVertexAttribArray(4);
            gl::VertexAttribPointer(4, 4, gl::FLOAT, gl::FALSE, size_mat4, size_vec4 as *const c_void);
            gl::EnableVertexAttribArray(5);
            gl::VertexAttribPointer(5, 4, gl::FLOAT, gl::FALSE, size_mat4, (2 * size_vec4) as *const c_void);
            gl::EnableVertexAttribArray(6);
            gl::VertexAttribPointer(6, 4, gl::FLOAT, gl::FALSE, size_mat4, (3 * size_vec4) as *const c_void);

            gl::VertexAttribDivisor(3, 1);
            gl::VertexAttribDivisor(4, 1);
            gl::VertexAttribDivisor(5, 1);
            gl::VertexAttribDivisor(6, 1);

            gl::BindVertexArray(0);
        }

        (asteroidShader, planetShader, rock, planet, amount)
    };

    // render loop
    // -----------
    while !window.should_close() {
        // per-frame time logic
        // --------------------
        let currentFrame = glfw.get_time() as f32;
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;

        // events
        // -----
        process_events(&events, &mut firstMouse, &mut lastX, &mut lastY, &mut camera);

        // input
        // -----
        processInput(&mut window, deltaTime, &mut camera);

        // render
        // ------
        unsafe {
            gl::ClearColor(0.1, 0.1, 0.1, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);

            // configure transformation matrices
            let projection: Matrix4<f32> = perspective(Deg(45.0), SCR_WIDTH as f32 / SCR_HEIGHT as f32, 0.1, 1000.0);
            let view = camera.GetViewMatrix();
            asteroidShader.useProgram();
            asteroidShader.setMat4(c_str!("projection"), &projection);
            asteroidShader.setMat4(c_str!("view"), &view);
            planetShader.useProgram();
            planetShader.setMat4(c_str!("projection"), &projection);
            planetShader.setMat4(c_str!("view"), &view);

            // draw planet
            let mut model = Matrix4::<f32>::from_translation(vec3(0.0, -3.0, 0.0));
            model = model * Matrix4::from_scale(4.0);
            planetShader.setMat4(c_str!("model"), &model);
            planet.Draw(&planetShader);

            // draw meteorites
            asteroidShader.useProgram();
            asteroidShader.setInt(c_str!("texture_diffuse1"), 0);
            gl::ActiveTexture(gl::TEXTURE0);
            gl::BindTexture(gl::TEXTURE_2D, rock.textures_loaded[0].id); // note: we also made the textures_loaded vector public (instead of private) from the model class.

            for mesh in &rock.meshes {
                gl::BindVertexArray(mesh.VAO);
                gl::DrawElementsInstanced(gl::TRIANGLES, mesh.indices.len() as i32, gl::UNSIGNED_INT, ptr::null(), amount as i32);
                gl::BindVertexArray(0);
            }
        }

        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        // -------------------------------------------------------------------------------
        window.swap_buffers();
        glfw.poll_events();
    }

}
<commit_msg>Update _10_3_asteroids_instanced.rs<commit_after>#![allow(non_upper_case_globals)]
#![allow(non_snake_case)]
extern crate glfw;
use self::glfw::Context;

extern crate gl;
extern crate rand;
use self::rand::Rng;

use std::ffi::CStr;
use std::mem;
use std::os::raw::c_void;
use std::ptr;

use common::{process_events, processInput};
use shader::Shader;
use camera::Camera;
use model::Model;

use cgmath::{Matrix4, vec3, Point3, Vector4, Deg, perspective};
use cgmath::prelude::*;

// settings
const SCR_WIDTH: u32 = 1280;
const SCR_HEIGHT: u32 = 720;

pub fn main_4_10_3() {
    let mut camera = Camera {
        Position: Point3::new(0.0, 0.0, 155.0),
        ..Camera::default()
    };

    let mut firstMouse = true;
    let mut lastX: f32 = SCR_WIDTH as f32 / 2.0;
    let mut lastY: f32 = SCR_HEIGHT as f32 / 2.0;

    // timing
    let mut deltaTime: f32; // time between current frame and last frame
    let mut lastFrame: f32 = 0.0;

    // glfw: initialize and configure
    // ------------------------------
    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
    glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
    glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));
    #[cfg(target_os = "macos")]
    glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));

    // glfw window creation
    // --------------------
    let (mut window, events) = glfw.create_window(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", glfw::WindowMode::Windowed)
        .expect("Failed to create GLFW window");

    window.make_current();
    window.set_framebuffer_size_polling(true);
    window.set_cursor_pos_polling(true);
    window.set_scroll_polling(true);

    // tell GLFW to capture our mouse
    window.set_cursor_mode(glfw::CursorMode::Disabled);

    // gl: load all OpenGL function pointers
    // ---------------------------------------
    gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);

    let (asteroidShader, planetShader, rock, planet, amount) = unsafe {
        // configure global opengl state
        // -----------------------------
        gl::Enable(gl::DEPTH_TEST);

        // build and compile shaders
        // -------------------------
        let asteroidShader = Shader::new(
            "src/_4_advanced_opengl/shaders/10.3.asteroids.vs",
            "src/_4_advanced_opengl/shaders/10.3.asteroids.fs");
        let planetShader = Shader::new(
            "src/_4_advanced_opengl/shaders/10.3.planet.vs",
            "src/_4_advanced_opengl/shaders/10.3.planet.fs");

        // load models
        // -----------
        let rock = Model::new("resources/objects/rock/rock.obj");
        let planet = Model::new("resources/objects/planet/planet.obj");

        // generate a large list of semi-random model transformation matrices
        // ------------------------------------------------------------------
        let amount = 100000;
        let mut modelMatrices: Vec<Matrix4<f32>> = Vec::with_capacity(amount);
        let mut rng = rand::thread_rng();
        let radius = 150.0;
        let offset: f32 = 25.0;
        for i in 0..amount {
            let angle = i as i32 as f32 / amount as f32 * 360.0;
            let mut displacement = (rng.gen::<u32>() % (2.0 * offset * 100.0) as u32) as f32 / 100.0 - offset;
            let x = angle.sin() * radius + displacement;
            displacement = (rng.gen::<u32>() % (2.0 * offset * 100.0) as u32) as f32 / 100.0 - offset;
            let y = displacement * 0.4; // keep height of asteroid field smaller compared to width of x and z
            displacement = (rng.gen::<u32>() % (2.0 * offset * 100.0) as u32) as f32 / 100.0 - offset;
            let z = angle.cos() * radius + displacement;
            let mut model = Matrix4::<u32>::from_translation(vec3(x, y, z));

            // 2. scale: Scale between 0.05 and 0.25
            let scale = (rng.gen::<u32>() % 20) as f32 / 100.0 + 0.05;
            model = model * Matrix4::from_scale(scale);

            // 3. rotation: add random rotation around a (semi)randomly picked rotation axis vector
            let rotAngle = (rng.gen::<u32>() % 360) as f32;
            model = model * Matrix4::from_axis_angle(vec3(0.4, 0.6, 0.8).normalize(), Deg(rotAngle));

            // 4. now add to list of matrices
            modelMatrices.push(model);
        }

        // configure instanced array
        // -------------------------
        let mut buffer = 0;
        gl::GenBuffers(1, &mut buffer);
        gl::BindBuffer(gl::ARRAY_BUFFER, buffer);
        gl::BufferData(
            gl::ARRAY_BUFFER,
            (amount * mem::size_of::<Matrix4<f32>>()) as isize,
            &modelMatrices[0] as *const Matrix4<f32> as *const c_void,
            gl::STATIC_DRAW);

        // set transformation matrices as an instance vertex attribute (with divisor 1)
        // note: we're cheating a little by taking the, now publicly declared, VAO of the model's mesh(es) and adding new vertexAttribPointers
        // normally you'd want to do this in a more organized fashion, but for learning purposes this will do.
        // -----------------------------------------------------------------------------------------------------------------------------------
        let size_mat4 = mem::size_of::<Matrix4<f32>>() as i32;
        let size_vec4 = mem::size_of::<Vector4<f32>>() as i32;
        for mesh in &rock.meshes {
            let VAO = mesh.VAO;
            gl::BindVertexArray(VAO);
            // set attribute pointers for matrix (4 times vec4)
            gl::EnableVertexAttribArray(3);
            gl::VertexAttribPointer(3, 4, gl::FLOAT, gl::FALSE, size_mat4, ptr::null());
            gl::EnableVertexAttribArray(4);
            gl::VertexAttribPointer(4, 4, gl::FLOAT, gl::FALSE, size_mat4, size_vec4 as *const c_void);
            gl::EnableVertexAttribArray(5);
            gl::VertexAttribPointer(5, 4, gl::FLOAT, gl::FALSE, size_mat4, (2 * size_vec4) as *const c_void);
            gl::EnableVertexAttribArray(6);
            gl::VertexAttribPointer(6, 4, gl::FLOAT, gl::FALSE, size_mat4, (3 * size_vec4) as *const c_void);

            gl::VertexAttribDivisor(3, 1);
            gl::VertexAttribDivisor(4, 1);
            gl::VertexAttribDivisor(5, 1);
            gl::VertexAttribDivisor(6, 1);

            gl::BindVertexArray(0);
        }

        (asteroidShader, planetShader, rock, planet, amount)
    };

    // render loop
    // -----------
    while !window.should_close() {
        // per-frame time logic
        // --------------------
        let currentFrame = glfw.get_time() as f32;
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;

        // events
        // -----
        process_events(&events, &mut firstMouse, &mut lastX, &mut lastY, &mut camera);

        // input
        // -----
        processInput(&mut window, deltaTime, &mut camera);

        // render
        // ------
        unsafe {
            gl::ClearColor(0.1, 0.1, 0.1, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);

            // configure transformation matrices
            let projection: Matrix4<f32> = perspective(Deg(45.0), SCR_WIDTH as f32 / SCR_HEIGHT as f32, 0.1, 1000.0);
            let view = camera.GetViewMatrix();
            asteroidShader.useProgram();
            asteroidShader.setMat4(c_str!("projection"), &projection);
            asteroidShader.setMat4(c_str!("view"), &view);
            planetShader.useProgram();
            planetShader.setMat4(c_str!("projection"), &projection);
            planetShader.setMat4(c_str!("view"), &view);

            // draw planet
            let mut model = Matrix4::<f32>::from_translation(vec3(0.0, -3.0, 0.0));
            model = model * Matrix4::from_scale(4.0);
            planetShader.setMat4(c_str!("model"), &model);
            planet.Draw(&planetShader);

            // draw meteorites
            asteroidShader.useProgram();
            asteroidShader.setInt(c_str!("texture_diffuse1"), 0);
            gl::ActiveTexture(gl::TEXTURE0);
            gl::BindTexture(gl::TEXTURE_2D, rock.textures_loaded[0].id); // note: we also made the textures_loaded vector public (instead of private) from the model class.

            for mesh in &rock.meshes {
                gl::BindVertexArray(mesh.VAO);
                gl::DrawElementsInstanced(gl::TRIANGLES, mesh.indices.len() as i32, gl::UNSIGNED_INT, ptr::null(), amount as i32);
                gl::BindVertexArray(0);
            }
        }

        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        // -------------------------------------------------------------------------------
        window.swap_buffers();
        glfw.poll_events();
    }

}
<|endoftext|>


<commit_before>use std::option::Option;

// use resources::Club;
// use resources::Gear;
use resources::enums::ResourceState;

use http;
use accesstoken::AccessToken;

use error::ApiError;

/// Athletes are Strava users, Strava users are athletes.
///
/// The object is returned in detailed, summary or meta representations.
///
/// See: http://strava.github.io/api/v3/athlete/
#[allow(dead_code)]
#[derive(RustcDecodable, Debug)]
pub struct Athlete {
    pub id: i32,
    pub resource_state: ResourceState,
    pub firstname: Option<String>,
    pub lastname: Option<String>,
    pub profile_medium: Option<String>,
    pub profile: Option<String>,
    pub city: Option<String>,
    pub state: Option<String>,
    pub country: Option<String>,
    pub sex: Option<String>,
    pub friend: Option<String>,
    pub follower: Option<String>,
    pub premium: Option<bool>,
    pub created_at: Option<String>,
    pub updated_at: Option<String>,
    pub approve_followers: Option<bool>,
    pub follower_count: Option<i32>,
    pub friend_count: Option<i32>,
    pub mutual_friend_count: Option<i32>,
    pub date_preference: Option<String>,
    pub measurement_preference: Option<String>,
    pub email: Option<String>,
    pub ftp: Option<i32>,
    pub weight: Option<f32>
    // pub clubs: Vec<Club>,
    // pub shoes: Vec<Gear>,
    // pub bikes: Vec<Gear>
}

impl Athlete {
    pub fn get_current(token: &AccessToken) -> Result<Athlete, ApiError> {
        let url = format!("https://strava.com/api/v3/athlete?access_token={}", token.get());
        http::get::<Athlete>(&url[..])
    }

    pub fn get_by_id(id: i32) -> Result<Athlete, ApiError> {
        let url = format!("https://strava.com/api/v3/athletes/{}", id);
        http::get::<Athlete>(&url[..])
    }
}

#[cfg(feature = "api_test")]
#[cfg(test)]
mod api_tests {
    use accesstoken::AccessToken;
    use super::Athlete;
    use resources::enums::ResourceState;

    #[test]
    fn get_current_athlete() {
        let token = AccessToken::new_from_env().unwrap();
        let athlete: Athlete = Athlete::get_current(&token).unwrap();
        assert!(athlete.resource_state == ResourceState::Detailed);
    }
}
<commit_msg>Implement getting athlete by id<commit_after>use std::option::Option;

// use resources::Club;
// use resources::Gear;
use resources::enums::ResourceState;

use http;
use accesstoken::AccessToken;

use error::ApiError;

/// Athletes are Strava users, Strava users are athletes.
///
/// The object is returned in detailed, summary or meta representations.
///
/// See: http://strava.github.io/api/v3/athlete/
#[allow(dead_code)]
#[derive(RustcDecodable, Debug)]
pub struct Athlete {
    pub id: i32,
    pub resource_state: ResourceState,
    pub firstname: Option<String>,
    pub lastname: Option<String>,
    pub profile_medium: Option<String>,
    pub profile: Option<String>,
    pub city: Option<String>,
    pub state: Option<String>,
    pub country: Option<String>,
    pub sex: Option<String>,
    pub friend: Option<String>,
    pub follower: Option<String>,
    pub premium: Option<bool>,
    pub created_at: Option<String>,
    pub updated_at: Option<String>,
    pub approve_followers: Option<bool>,
    pub follower_count: Option<i32>,
    pub friend_count: Option<i32>,
    pub mutual_friend_count: Option<i32>,
    pub date_preference: Option<String>,
    pub measurement_preference: Option<String>,
    pub email: Option<String>,
    pub ftp: Option<i32>,
    pub weight: Option<f32>
    // pub clubs: Vec<Club>,
    // pub shoes: Vec<Gear>,
    // pub bikes: Vec<Gear>
}

impl Athlete {
    pub fn get_current(token: &AccessToken) -> Result<Athlete, ApiError> {
        let url = format!("https://strava.com/api/v3/athlete?access_token={}", token.get());
        http::get::<Athlete>(&url[..])
    }

    pub fn get(token: &AccessToken, id: i32) -> Result<Athlete, ApiError> {
        let url = format!("https://strava.com/api/v3/athletes/{}?access_token={}", id, token.get());
        http::get::<Athlete>(&url[..])
    }
}

#[cfg(feature = "api_test")]
#[cfg(test)]
mod api_tests {
    use accesstoken::AccessToken;
    use super::Athlete;
    use resources::enums::ResourceState;

    #[test]
    fn get_current_athlete() {
        let token = AccessToken::new_from_env().unwrap();
        let athlete: Athlete = Athlete::get_current(&token).unwrap();
        assert_eq!(athlete.resource_state, ResourceState::Detailed);
    }

    #[test]
    fn get_athlete_by_id() {
        let id = 1712082;
        let token = AccessToken::new_from_env().unwrap();
        let athlete = Athlete::get(&token, id).unwrap();
        println!("{:?}", athlete);
        assert_eq!(athlete.id, id);
    }
}
<|endoftext|>


<commit_before>extern crate cell_gc;
extern crate lisp;

use std::fs;
use std::io::Read;
use std::path;

fn eval_test_file(file: path::PathBuf) {
    println!("Opening test file: {}", file.display());
    let mut file = fs::File::open(file).expect("Should open file OK");

    let mut source = String::new();
    file.read_to_string(&mut source)
        .expect("Should read file OK");

    println!("source =");
    println!("{}", source);

    cell_gc::with_heap(|hs| {
        let exprs = lisp::parse::parse(hs, &source).expect("Should parse s-exps OK");
        let env = lisp::vm::Environment::default_env(hs);
        for expr in exprs {
            lisp::vm::eval(hs, expr, env.clone()).expect("Should eval exprs OK");
        }
    });
}

macro_rules! test {
    ( $file:ident ) => {
        #[test]
        fn $file() {
            let file = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/", stringify!($file), ".lisp");
            let file = path::PathBuf::from(file);
            eval_test_file(file);
        }
    }
}

test!(begin);
test!(booleans);
test!(closure);
test!(cons);
test!(double);
test!(equivalence);
test!(y_combinator);
test!(y_combinator_2);
test!(define);
test!(numerical);
test!(pairs_and_lists);
test!(set);
test!(tail_calls);
test!(vectors);
<commit_msg>Superficial changes (use Path rather than PathBuf).<commit_after>extern crate cell_gc;
extern crate lisp;

use std::fs;
use std::io::Read;
use std::path::Path;

fn eval_test_file(file: &Path) {
    println!("Opening test file: {}", file.display());
    let mut file = fs::File::open(file).expect("Should open file OK");

    let mut source = String::new();
    file.read_to_string(&mut source)
        .expect("Should read file OK");

    println!("source =");
    println!("{}", source);

    cell_gc::with_heap(|hs| {
        let exprs = lisp::parse::parse(hs, &source).expect("Should parse s-exps OK");
        let env = lisp::vm::Environment::default_env(hs);
        for expr in exprs {
            lisp::vm::eval(hs, expr, env.clone()).expect("Should eval exprs OK");
        }
    });
}

macro_rules! test {
    ( $file:ident ) => {
        #[test]
        fn $file() {
            let file = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/", stringify!($file), ".lisp");
            let file = Path::new(file);
            eval_test_file(file);
        }
    }
}

test!(begin);
test!(booleans);
test!(closure);
test!(cons);
test!(double);
test!(equivalence);
test!(y_combinator);
test!(y_combinator_2);
test!(define);
test!(numerical);
test!(pairs_and_lists);
test!(set);
test!(tail_calls);
test!(vectors);
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;
use serialize_packed::{PackedOutputStream, PackedInputStream};
use io;

pub fn expect_packs_to(unpacked : &[u8],
                       packed : &[u8]) {

    use std::io::{Reader, Writer};

    // --------
    // write

    let mut bytes : std::vec::Vec<u8> = std::vec::Vec::from_elem(packed.len(), 0u8);
    {
        let mut writer = io::ArrayOutputStream::new(bytes.as_mut_slice());
        let mut packedOutputStream = PackedOutputStream {inner : &mut writer};
        packedOutputStream.write(unpacked).unwrap();
        packedOutputStream.flush().unwrap();
    }

    assert!(bytes.as_slice().equals(&packed),
            "expected: {:?}, got: {:?}", packed, bytes);

    // --------
    // read

    let mut reader = io::ArrayInputStream::new(packed);
    let mut packedInputStream = PackedInputStream {inner : &mut reader};

    let bytes = packedInputStream.read_exact(unpacked.len()).unwrap();

//    assert!(packedInputStream.eof());
    assert!(bytes.slice(0, bytes.len()).equals(&unpacked),
            "expected: {:?}, got: {:?}", unpacked, bytes);

}

static zeroes : &'static[u8] = &[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0];

#[test]
pub fn simple_packing() {
    expect_packs_to([], []);
    expect_packs_to(zeroes.slice(0, 8), [0,0]);
    expect_packs_to([0,0,12,0,0,34,0,0], [0x24,12,34]);
    expect_packs_to([1,3,2,4,5,7,6,8], [0xff,1,3,2,4,5,7,6,8,0]);
    expect_packs_to([0,0,0,0,0,0,0,0,1,3,2,4,5,7,6,8], [0,0,0xff,1,3,2,4,5,7,6,8,0]);
    expect_packs_to([0,0,12,0,0,34,0,0,1,3,2,4,5,7,6,8], [0x24,12,34,0xff,1,3,2,4,5,7,6,8,0]);
    expect_packs_to([1,3,2,4,5,7,6,8,8,6,7,4,5,2,3,1], [0xff,1,3,2,4,5,7,6,8,1,8,6,7,4,5,2,3,1]);

    expect_packs_to(
        [1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 0,2,4,0,9,0,5,1],
        [0xff,1,2,3,4,5,6,7,8, 3, 1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8,
         0xd6,2,4,9,5,1]);
    expect_packs_to(
        [1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 6,2,4,3,9,0,5,1, 1,2,3,4,5,6,7,8, 0,2,4,0,9,0,5,1],
        [0xff,1,2,3,4,5,6,7,8, 3, 1,2,3,4,5,6,7,8, 6,2,4,3,9,0,5,1, 1,2,3,4,5,6,7,8,
         0xd6,2,4,9,5,1]);

    expect_packs_to(
        [8,0,100,6,0,1,1,2, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,0,2,0,3,1],
        [0xed,8,100,6,1,1,2, 0,2, 0xd4,1,2,3,1]);

    expect_packs_to(zeroes.slice(0,16), [0,1]);
    expect_packs_to([0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0], [0,2]);

}
<commit_msg>equals -> eq<commit_after>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;
use serialize_packed::{PackedOutputStream, PackedInputStream};
use io;

pub fn expect_packs_to(unpacked : &[u8],
                       packed : &[u8]) {

    use std::io::{Reader, Writer};

    // --------
    // write

    let mut bytes : std::vec::Vec<u8> = std::vec::Vec::from_elem(packed.len(), 0u8);
    {
        let mut writer = io::ArrayOutputStream::new(bytes.as_mut_slice());
        let mut packedOutputStream = PackedOutputStream {inner : &mut writer};
        packedOutputStream.write(unpacked).unwrap();
        packedOutputStream.flush().unwrap();
    }

    assert!(bytes.as_slice().eq(&packed),
            "expected: {:?}, got: {:?}", packed, bytes);

    // --------
    // read

    let mut reader = io::ArrayInputStream::new(packed);
    let mut packedInputStream = PackedInputStream {inner : &mut reader};

    let bytes = packedInputStream.read_exact(unpacked.len()).unwrap();

//    assert!(packedInputStream.eof());
    assert!(bytes.slice(0, bytes.len()).eq(&unpacked),
            "expected: {:?}, got: {:?}", unpacked, bytes);

}

static zeroes : &'static[u8] = &[0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0];

#[test]
pub fn simple_packing() {
    expect_packs_to([], []);
    expect_packs_to(zeroes.slice(0, 8), [0,0]);
    expect_packs_to([0,0,12,0,0,34,0,0], [0x24,12,34]);
    expect_packs_to([1,3,2,4,5,7,6,8], [0xff,1,3,2,4,5,7,6,8,0]);
    expect_packs_to([0,0,0,0,0,0,0,0,1,3,2,4,5,7,6,8], [0,0,0xff,1,3,2,4,5,7,6,8,0]);
    expect_packs_to([0,0,12,0,0,34,0,0,1,3,2,4,5,7,6,8], [0x24,12,34,0xff,1,3,2,4,5,7,6,8,0]);
    expect_packs_to([1,3,2,4,5,7,6,8,8,6,7,4,5,2,3,1], [0xff,1,3,2,4,5,7,6,8,1,8,6,7,4,5,2,3,1]);

    expect_packs_to(
        [1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 0,2,4,0,9,0,5,1],
        [0xff,1,2,3,4,5,6,7,8, 3, 1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8,
         0xd6,2,4,9,5,1]);
    expect_packs_to(
        [1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 6,2,4,3,9,0,5,1, 1,2,3,4,5,6,7,8, 0,2,4,0,9,0,5,1],
        [0xff,1,2,3,4,5,6,7,8, 3, 1,2,3,4,5,6,7,8, 6,2,4,3,9,0,5,1, 1,2,3,4,5,6,7,8,
         0xd6,2,4,9,5,1]);

    expect_packs_to(
        [8,0,100,6,0,1,1,2, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,0,2,0,3,1],
        [0xed,8,100,6,1,1,2, 0,2, 0xd4,1,2,3,1]);

    expect_packs_to(zeroes.slice(0,16), [0,1]);
    expect_packs_to([0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0], [0,2]);

}
<|endoftext|>


<commit_before>use screen::*;
use context::Context;
use resource_manager::Textures;
use graphics::Texture;
use piston_window::{self, PistonWindow, ImageSize, Transformed};

pub struct Battle {
    empty_tile: Texture,
}

impl Battle {
    pub fn new(window: &PistonWindow, context: &mut Context) -> Self {
        Battle { empty_tile: context.resource_manager.load_texture(window, Textures::EmptyTile) }
    }
}

impl Screen for Battle {
    fn on_input(&mut self, input: &piston_window::Input, window: &PistonWindow, context: &mut Context) -> InputResults {
        use piston_window::{Input, Button, Key, MouseButton};

        let mut result = Vec::new();

        match input {
            &Input::Press(button) => {
                match button {
                    Button::Keyboard(Key::Escape) => {
                        result.push(InputResult::PushScreen(Box::new(MainMenu::new(&window, context))));
                    }
                    Button::Mouse(MouseButton::Left) => { /* TODO */ }
                    _ => {}
                }
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, _args: &piston_window::RenderArgs, window: &PistonWindow) {
        window.draw_2d(|context, graphics| {
            piston_window::clear([0.0, 0.0, 0.0, 1.0], graphics);

            // Draw grid.
            let (x_count, y_count) = (9, 8);
            let offset = 5;
            let (height, width) = self.empty_tile.get_size();
            for x in 0..x_count {
                for y in 0..y_count {
                    // TODO: draw_many?
                    piston_window::image(&self.empty_tile,
                                         context.transform.trans((x * (height + offset)) as f64,
                                                                 (y * (width + offset)) as f64),
                                         graphics);
                }
            }
        });
    }

    fn on_update(&mut self, _args: &piston_window::UpdateArgs) {}
}
<commit_msg>Format<commit_after>use screen::*;
use context::Context;
use resource_manager::Textures;
use graphics::Texture;
use piston_window::{self, PistonWindow, ImageSize, Transformed};

pub struct Battle {
    empty_tile: Texture,
}

impl Battle {
    pub fn new(window: &PistonWindow, context: &mut Context) -> Self {
        Battle { empty_tile: context.resource_manager.load_texture(window, Textures::EmptyTile) }
    }
}

impl Screen for Battle {
    fn on_input(&mut self, input: &piston_window::Input, window: &PistonWindow, context: &mut Context) -> InputResults {
        use piston_window::{Input, Button, Key, MouseButton};

        let mut result = Vec::new();

        match input {
            &Input::Press(button) => {
                match button {
                    Button::Keyboard(Key::Escape) => {
                        result.push(InputResult::PushScreen(Box::new(MainMenu::new(&window, context))));
                    }
                    Button::Mouse(MouseButton::Left) => {
                        // TODO
                    }
                    _ => {}
                }
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, _args: &piston_window::RenderArgs, window: &PistonWindow) {
        window.draw_2d(|context, graphics| {
            piston_window::clear([0.0, 0.0, 0.0, 1.0], graphics);

            // Draw grid.
            let (x_count, y_count) = (9, 8);
            let offset = 5;
            let (height, width) = self.empty_tile.get_size();
            for x in 0..x_count {
                for y in 0..y_count {
                    // TODO: draw_many?
                    piston_window::image(&self.empty_tile,
                                         context.transform.trans((x * (height + offset)) as f64,
                                                                 (y * (width + offset)) as f64),
                                         graphics);
                }
            }
        });
    }

    fn on_update(&mut self, _args: &piston_window::UpdateArgs) {}
}
<|endoftext|>