<commit_before>// Copyright 2015, Paul Osborne <osbpau@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/license/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option.  This file may not be copied, modified, or distributed
// except according to those terms.
//
// Portions of this implementation are based on work by Nat Pryce:
// https://github.com/npryce/rusty-pi/blob/master/src/pi/gpio.rs

use std::io::prelude::*;
use std::io;
use std::io::{Error, ErrorKind};
use std::fs;
use std::fs::{File};

pub struct Pin {
    pin_num : u64,
}

#[derive(Copy,Debug)]
pub enum Direction {In, Out, High, Low}

#[derive(Copy,Debug)]
pub enum Edge {NoInterrupt, RisingEdge, FallingEdge, BothEdges}

/// Requested that a GPIO be exported by sysfs
///
/// This is equivalent to `echo N > /sys/class/gpio/export` with
/// the exception that the case where the GPIO is already exported
/// is not an error.
pub fn export(pin_num : u64) -> io::Result<Pin> {
    match fs::metadata(&format!("/sys/class/gpio/gpio{}", pin_num)) {
        Ok(_) => {},
        Err(_) => {
            let mut export_file = try!(File::create("/sys/class/gpio/export"));
            try!(export_file.write_all(format!("{}", pin_num).as_bytes()));
        }
    };
    Ok(Pin::new(pin_num))
}

impl Pin {
    /// Write all of the provided contents to the specified devFile
    fn write_to_device_file(&self, dev_file_name: &str, value: &str) -> io::Result<()> {
        let gpio_path = format!("/sys/class/gpio/gpio{}/{}", self.pin_num, dev_file_name);
        let mut dev_file = try!(File::create(&gpio_path));
        try!(dev_file.write_all(value.as_bytes()));
        Ok(())
    }

    /// Create a new Pin with the provided pin_num
    ///
    /// This function does not export the provided pin_num.  If that
    /// functionality is desired, `export` should be used instead.
    pub fn new(pin_num : u64) -> Pin {
        Pin {
            pin_num: pin_num,
        }
    }

    /// Set this GPIO as either an input or an output
    ///
    /// The basic values allowed here are `Direction::In` and
    /// `Direction::Out` which set the Pin as either an input
    /// or output respectively.  In addition to those, two
    /// additional settings of `Direction::High` and
    /// `Direction::Low`.  These both set the Pin as an output
    /// but do so with an initial value of high or low respectively.
    /// This allows for glitch-free operation.
    ///
    /// Note that this entry may not exist if the kernel does
    /// not support changing the direction of a pin in userspace.  If
    /// this is the case, you will get an error.
    pub fn set_direction(&self, dir : Direction) -> io::Result<()> {
        self.write_to_device_file("direction", match dir {
            Direction::In => "in",
            Direction::Out => "out",
            Direction::High => "high",
            Direction::Low => "low",
        })
    }

    /// Get the value of the Pin (0 or 1)
    ///
    /// If successful, 1 will be returned if the pin is high
    /// and 0 will be returned if the pin is low (this may or may
    /// not match the signal level of the actual signal depending
    /// on the GPIO "active_low" entry).
    pub fn get_value(&self) -> io::Result<u8> {
        let mut dev_file = try!(File::open(&format!("/sys/class/gpio/gpio{}/value", self.pin_num)));
        let mut s = String::with_capacity(10);
        try!(dev_file.read_to_string(&mut s));
        match s.parse::<u8>() {
            Ok(n) => Ok(n),
            Err(_) => Err(Error::new(ErrorKind::Other, "Unexpected Error", None)),
        }
    }

    /// Set the value of the Pin
    ///
    /// This will set the value of the pin either high or low.
    /// A 0 value will set the pin low and any other value will
    /// set the pin high (1 is typical).
    pub fn set_value(&self, value : u8) -> io::Result<()> {
        let val = if value == 0 {
            "0"
        } else {
            "1"
        };
        self.write_to_device_file("value", val)
    }
}
<commit_msg>core: implement unexport function and method<commit_after>// Copyright 2015, Paul Osborne <osbpau@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/license/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option.  This file may not be copied, modified, or distributed
// except according to those terms.
//
// Portions of this implementation are based on work by Nat Pryce:
// https://github.com/npryce/rusty-pi/blob/master/src/pi/gpio.rs

use std::io::prelude::*;
use std::io;
use std::io::{Error, ErrorKind};
use std::fs;
use std::fs::{File};

pub struct Pin {
    pin_num : u64,
}

#[derive(Copy,Debug)]
pub enum Direction {In, Out, High, Low}

#[derive(Copy,Debug)]
pub enum Edge {NoInterrupt, RisingEdge, FallingEdge, BothEdges}

/// Requested that a GPIO be exported by sysfs
///
/// This is equivalent to `echo N > /sys/class/gpio/export` with
/// the exception that the case where the GPIO is already exported
/// is not an error.
pub fn export(pin_num : u64) -> io::Result<Pin> {
    match fs::metadata(&format!("/sys/class/gpio/gpio{}", pin_num)) {
        Ok(_) => {},
        Err(_) => {
            let mut export_file = try!(File::create("/sys/class/gpio/export"));
            try!(export_file.write_all(format!("{}", pin_num).as_bytes()));
        }
    };
    Ok(Pin::new(pin_num))
}

/// Unexport the GPIO with the provided pin number
///
/// This function will unexport the provided by from syfs if
/// it is currently exported.  If the pin is not currently
/// exported, it will return without error.  That is, whenever
/// this function returns Ok, the GPIO is not exported.
pub fn unexport(pin_num : u64) -> io::Result<()> {
    match fs::metadata(&format!("/sys/class/gpio/{}", pin_num)) {
        Ok(_) => {
            let mut unexport_file = try!(File::create("/sys/class/gpio/unexport"));
            try!(unexport_file.write_all(format!("{}", pin_num).as_bytes()));
        },
        Err(_) => {} // not exported
    }
    Ok(())
}

impl Pin {
    /// Write all of the provided contents to the specified devFile
    fn write_to_device_file(&self, dev_file_name: &str, value: &str) -> io::Result<()> {
        let gpio_path = format!("/sys/class/gpio/gpio{}/{}", self.pin_num, dev_file_name);
        let mut dev_file = try!(File::create(&gpio_path));
        try!(dev_file.write_all(value.as_bytes()));
        Ok(())
    }

    /// Create a new Pin with the provided pin_num
    ///
    /// This function does not export the provided pin_num.  If that
    /// functionality is desired, `export` should be used instead.
    pub fn new(pin_num : u64) -> Pin {
        Pin {
            pin_num: pin_num,
        }
    }

    /// Set this GPIO as either an input or an output
    ///
    /// The basic values allowed here are `Direction::In` and
    /// `Direction::Out` which set the Pin as either an input
    /// or output respectively.  In addition to those, two
    /// additional settings of `Direction::High` and
    /// `Direction::Low`.  These both set the Pin as an output
    /// but do so with an initial value of high or low respectively.
    /// This allows for glitch-free operation.
    ///
    /// Note that this entry may not exist if the kernel does
    /// not support changing the direction of a pin in userspace.  If
    /// this is the case, you will get an error.
    pub fn set_direction(&self, dir : Direction) -> io::Result<()> {
        self.write_to_device_file("direction", match dir {
            Direction::In => "in",
            Direction::Out => "out",
            Direction::High => "high",
            Direction::Low => "low",
        })
    }

    /// Get the value of the Pin (0 or 1)
    ///
    /// If successful, 1 will be returned if the pin is high
    /// and 0 will be returned if the pin is low (this may or may
    /// not match the signal level of the actual signal depending
    /// on the GPIO "active_low" entry).
    pub fn get_value(&self) -> io::Result<u8> {
        let mut dev_file = try!(File::open(&format!("/sys/class/gpio/gpio{}/value", self.pin_num)));
        let mut s = String::with_capacity(10);
        try!(dev_file.read_to_string(&mut s));
        match s.parse::<u8>() {
            Ok(n) => Ok(n),
            Err(_) => Err(Error::new(ErrorKind::Other, "Unexpected Error", None)),
        }
    }

    /// Set the value of the Pin
    ///
    /// This will set the value of the pin either high or low.
    /// A 0 value will set the pin low and any other value will
    /// set the pin high (1 is typical).
    pub fn set_value(&self, value : u8) -> io::Result<()> {
        let val = if value == 0 {
            "0"
        } else {
            "1"
        };
        self.write_to_device_file("value", val)
    }
}
<|endoftext|>


<commit_before>use Cost;
use linear_algebra::Vector;

/// Pass an instance of this type to a training algorithm to optimize for C=Error^2
///
/// Optimizing a `model::Constant` for `LeastSquares` should yield the mean value
pub struct LeastSquares;

impl Cost<f64> for LeastSquares {
    fn outer_derivative(&self, prediction: &f64, truth: f64) -> f64 {
        let error = prediction - truth;
        2.0 * error
    }

    fn cost(&self, prediction: f64, truth: f64) -> f64 {
        (prediction - truth).powi(2)
    }
}

/// Pass an instance of this type to a training algorithm to optimize for C=|Error|
///
/// Optimizing a `model::Constant` for `LeastAbsoluteDeviation` should yield the median.
/// Gradient for error == 0 is set to 0
pub struct LeastAbsoluteDeviation;

impl Cost<f64> for LeastAbsoluteDeviation {
    fn outer_derivative(&self, prediction: &f64, truth: f64) -> f64 {
        let error = prediction - truth;
        if error > 0.0 {
            1.0
        } else if error < 0.0 {
            -1.0
        } else {
            0.0
        }
    }
    fn cost(&self, prediction: f64, truth: f64) -> f64 {
        (prediction - truth).abs()
    }
}

/// Maximizes the likelihood function `L` by defining `C=-ln(L)`
///
/// You can use this function if your truth is a probability
/// (i.e., a value between 0 and 1). Maximizing the likelihood
/// function is equivalent to minimizing the least square error,
/// yet this cost function has shown itself to converge quicker
/// for some problems.
///
/// #Examples
///
/// ```
/// use vikos::{learn_history, Model, teacher, cost};
/// use vikos::model::Logistic;
/// use std::default::Default;
///
/// let history = [([2.7, 2.5], false),
///                ([1.4, 2.3], false),
///                ([3.3, 4.4], false),
///                ([1.3, 1.8], false),
///                ([3.0, 3.0], false),
///                ([7.6, 2.7], true),
///                ([5.3, 2.0], true),
///                ([6.9, 1.7], true),
///                ([8.6, -0.2], true),
///                ([7.6, 3.5], true)];
///
/// let mut model = Logistic::default();
/// let teacher = teacher::GradientDescent { learning_rate: 0.3 };
/// let cost = cost::MaxLikelihood {};
///
/// learn_history(&teacher,
///               &cost,
///               &mut model,
///               history.iter().cycle().take(20).cloned());
/// ```
pub struct MaxLikelihood;

impl Cost<f64> for MaxLikelihood {
    fn outer_derivative(&self, prediction: &f64, truth: f64) -> f64 {
        ((1.0 - truth) / (1.0 - prediction) - truth / prediction)
    }
    fn cost(&self, prediction: f64, truth: f64) -> f64 {
        -truth * prediction.ln() - (1.0 - truth) * (1.0 - prediction).ln()
    }
}

impl Cost<bool> for MaxLikelihood {
    fn outer_derivative(&self, prediction: &f64, truth: bool) -> f64 {
        1. / if truth { -prediction } else { 1.0 - prediction }
    }
    fn cost(&self, prediction: f64, truth: bool) -> f64 {
        -(if truth { prediction } else { 1.0 - prediction }).ln()
    }
}

impl<V> Cost<usize, V> for MaxLikelihood
    where V: Vector
{
    fn outer_derivative(&self, prediction: &V, truth: usize) -> V {
        let mut derivation = prediction.clone();
        for i in 0..prediction.dimension() {
            *derivation.mut_at(i) = self.outer_derivative(&prediction.at(i), truth == i);
        }
        derivation
    }
    fn cost(&self, prediction: V, truth: usize) -> f64 {
        (0..prediction.dimension()).fold(0.0, |s, i| s + self.cost(prediction.at(i), i == truth))
    }
}

#[cfg(test)]
mod test {

    use super::super::Cost;
    use super::{LeastSquares, LeastAbsoluteDeviation, MaxLikelihood};

    // Approximates the derivation of the cost function
    fn approx_derivate<T: Copy>(cost: &Cost<T>, prediction: f64, truth: T) -> f64 {
        let epsilon = 0.00001;
        let f_plus_epsilon = cost.cost(prediction + epsilon, truth);
        let f_minus_epsilon = cost.cost(prediction - epsilon, truth);
        println!("f_x_plus_epsilon: {}, f_x_minus_epsilon:: {}",
                 f_plus_epsilon,
                 f_minus_epsilon);
        (f_plus_epsilon - f_minus_epsilon) / (2.0 * epsilon)
    }

    // Returns absolute difference between derivate and approximation
    fn check_derivate<T: Copy>(cost: &Cost<T>, prediction: f64, truth: T) -> f64 {
        let derivate = cost.outer_derivative(&prediction, truth);
        let approx = approx_derivate(cost, prediction, truth);
        println!("derivation: {}, approximation: {}", derivate, approx);
        (derivate - approx).abs()
    }

    #[test]
    fn least_squares_derivation() {

        let cost = LeastSquares {};
        assert!(check_derivate(&cost, 10.0, 12.0) < 0.001);
    }

    #[test]
    fn least_absolute_derivation() {

        let cost = LeastAbsoluteDeviation {};
        assert!(check_derivate(&cost, 0.0, 0.0) < 0.001);
        assert!(check_derivate(&cost, 1.0, 0.0) < 0.001);
        assert!(check_derivate(&cost, -1.0, 0.0) < 0.001);
    }

    #[test]
    fn neg_log_likelihood_derivation() {

        let cost = MaxLikelihood {};
        assert!(check_derivate(&cost, 0.2, false) < 0.001);
        assert!(check_derivate(&cost, 0.8, true) < 0.001);
        assert!(check_derivate(&cost, 0.2, 0.0) < 0.001);
        assert!(check_derivate(&cost, 0.8, 1.0) < 0.001);
        assert_eq!(cost.outer_derivative(&0.2, false),
                   cost.outer_derivative(&0.2, 0.0));
        assert_eq!(cost.outer_derivative(&0.8, true),
                   cost.outer_derivative(&0.8, 1.0));
    }
}
<commit_msg>Replace if-elseif by call to f64::signum()<commit_after>use Cost;
use linear_algebra::Vector;

/// Pass an instance of this type to a training algorithm to optimize for C=Error^2
///
/// Optimizing a `model::Constant` for `LeastSquares` should yield the mean value
pub struct LeastSquares;

impl Cost<f64> for LeastSquares {
    fn outer_derivative(&self, prediction: &f64, truth: f64) -> f64 {
        let error = prediction - truth;
        2.0 * error
    }

    fn cost(&self, prediction: f64, truth: f64) -> f64 {
        (prediction - truth).powi(2)
    }
}

/// Pass an instance of this type to a training algorithm to optimize for C=|Error|
///
/// Optimizing a `model::Constant` for `LeastAbsoluteDeviation` should yield the median.
/// Gradient for error == 0 is set to 0
pub struct LeastAbsoluteDeviation;

impl Cost<f64> for LeastAbsoluteDeviation {
    fn outer_derivative(&self, prediction: &f64, truth: f64) -> f64 {
        let error = prediction - truth;
        if error == 0.0 {
            0.0
        } else {
            error.signum()
        }
    }
    fn cost(&self, prediction: f64, truth: f64) -> f64 {
        (prediction - truth).abs()
    }
}

/// Maximizes the likelihood function `L` by defining `C=-ln(L)`
///
/// You can use this function if your truth is a probability
/// (i.e., a value between 0 and 1). Maximizing the likelihood
/// function is equivalent to minimizing the least square error,
/// yet this cost function has shown itself to converge quicker
/// for some problems.
///
/// #Examples
///
/// ```
/// use vikos::{learn_history, Model, teacher, cost};
/// use vikos::model::Logistic;
/// use std::default::Default;
///
/// let history = [([2.7, 2.5], false),
///                ([1.4, 2.3], false),
///                ([3.3, 4.4], false),
///                ([1.3, 1.8], false),
///                ([3.0, 3.0], false),
///                ([7.6, 2.7], true),
///                ([5.3, 2.0], true),
///                ([6.9, 1.7], true),
///                ([8.6, -0.2], true),
///                ([7.6, 3.5], true)];
///
/// let mut model = Logistic::default();
/// let teacher = teacher::GradientDescent { learning_rate: 0.3 };
/// let cost = cost::MaxLikelihood {};
///
/// learn_history(&teacher,
///               &cost,
///               &mut model,
///               history.iter().cycle().take(20).cloned());
/// ```
pub struct MaxLikelihood;

impl Cost<f64> for MaxLikelihood {
    fn outer_derivative(&self, prediction: &f64, truth: f64) -> f64 {
        ((1.0 - truth) / (1.0 - prediction) - truth / prediction)
    }
    fn cost(&self, prediction: f64, truth: f64) -> f64 {
        -truth * prediction.ln() - (1.0 - truth) * (1.0 - prediction).ln()
    }
}

impl Cost<bool> for MaxLikelihood {
    fn outer_derivative(&self, prediction: &f64, truth: bool) -> f64 {
        1. / if truth { -prediction } else { 1.0 - prediction }
    }
    fn cost(&self, prediction: f64, truth: bool) -> f64 {
        -(if truth { prediction } else { 1.0 - prediction }).ln()
    }
}

impl<V> Cost<usize, V> for MaxLikelihood
    where V: Vector
{
    fn outer_derivative(&self, prediction: &V, truth: usize) -> V {
        let mut derivation = prediction.clone();
        for i in 0..prediction.dimension() {
            *derivation.mut_at(i) = self.outer_derivative(&prediction.at(i), truth == i);
        }
        derivation
    }
    fn cost(&self, prediction: V, truth: usize) -> f64 {
        (0..prediction.dimension()).fold(0.0, |s, i| s + self.cost(prediction.at(i), i == truth))
    }
}

#[cfg(test)]
mod test {

    use super::super::Cost;
    use super::{LeastSquares, LeastAbsoluteDeviation, MaxLikelihood};

    // Approximates the derivation of the cost function
    fn approx_derivate<T: Copy>(cost: &Cost<T>, prediction: f64, truth: T) -> f64 {
        let epsilon = 0.00001;
        let f_plus_epsilon = cost.cost(prediction + epsilon, truth);
        let f_minus_epsilon = cost.cost(prediction - epsilon, truth);
        println!("f_x_plus_epsilon: {}, f_x_minus_epsilon:: {}",
                 f_plus_epsilon,
                 f_minus_epsilon);
        (f_plus_epsilon - f_minus_epsilon) / (2.0 * epsilon)
    }

    // Returns absolute difference between derivate and approximation
    fn check_derivate<T: Copy>(cost: &Cost<T>, prediction: f64, truth: T) -> f64 {
        let derivate = cost.outer_derivative(&prediction, truth);
        let approx = approx_derivate(cost, prediction, truth);
        println!("derivation: {}, approximation: {}", derivate, approx);
        (derivate - approx).abs()
    }

    #[test]
    fn least_squares_derivation() {

        let cost = LeastSquares {};
        assert!(check_derivate(&cost, 10.0, 12.0) < 0.001);
    }

    #[test]
    fn least_absolute_derivation() {

        let cost = LeastAbsoluteDeviation {};
        assert!(check_derivate(&cost, 0.0, 0.0) < 0.001);
        assert!(check_derivate(&cost, 1.0, 0.0) < 0.001);
        assert!(check_derivate(&cost, -1.0, 0.0) < 0.001);
    }

    #[test]
    fn neg_log_likelihood_derivation() {

        let cost = MaxLikelihood {};
        assert!(check_derivate(&cost, 0.2, false) < 0.001);
        assert!(check_derivate(&cost, 0.8, true) < 0.001);
        assert!(check_derivate(&cost, 0.2, 0.0) < 0.001);
        assert!(check_derivate(&cost, 0.8, 1.0) < 0.001);
        assert_eq!(cost.outer_derivative(&0.2, false),
                   cost.outer_derivative(&0.2, 0.0));
        assert_eq!(cost.outer_derivative(&0.8, true),
                   cost.outer_derivative(&0.8, 1.0));
    }
}
<|endoftext|>


<commit_before>// To search for nibbles in a byte array.
// Requires two nibbles per byte.
// All values above 0x0F will be used as wildcard.
// Example: Use x or X as wildcard for a nibble.

pub trait FindOptSubset {
    fn find_subset(&self, subset: &[u8]) -> Option<usize>;
}

impl FindOptSubset for Vec<u8> {
    fn find_subset(&self, subset: &[u8]) -> Option<usize> {
        if subset.len() > 2 * self.len() {
            return None;
        }
        if subset.len() % 2 != 0 {
            // Must be dividable by two
            return None;
        }
        // Search in a for b
        for a in 0..self.len() - subset.len() / 2 + 1 {
            for b in 0..subset.len() / 2 {
                // if b is not a, skip searching at that position in a
                // Logic: both match, ...
                // or first nibble matches when second nibble is wildcard,
                // or second nibble matches when first nibble is wildcard.
                // or two wildcards at that position.
                if !(
                    ((subset[2*b  ] == self[a + b]>>4) && (subset[2*b+1] == self[a + b]%16)) ||
                    ((subset[2*b  ] == self[a + b]>>4) && (subset[2*b+1] >= 0x10)) ||
                    ((subset[2*b+1] == self[a + b]%16) && (subset[2*b  ] >= 0x10)) ||
                    ((subset[2*b+1] >= 0x10) && (subset[2*b  ] >= 0x10))
                   )
                {
                    break; // element does not match
                }
                // when all elements of b match in a, return position of a
                if b == subset.len() / 2 - 1 {
                    return Some(a);
                }
            }
        }
        None
    }
}

#[test]
fn find_subset_partial_at_start() {
    let buf = vec![0x01, 0x02, 0x03, 0x04, 0x05];
    let sub = vec![0x00, 0x01];
    assert_eq!(buf.find_subset(&sub), Some(0));
}
#[test]
fn find_subset_partial_at_middle() {
    let buf = vec![0x01, 0x02, 0x03, 0x04, 0x05];
    let sub = vec![0x00, 0x03, 0x00, 0x04];
    assert_eq!(buf.find_subset(&sub), Some(2));
}
#[test]
fn find_subset_partial_at_end() {
    let buf = vec![0x01, 0x02, 0x03, 0x04, 0x05];
    let sub = vec![0x00, 0x04, 0x00, 0x05];
    assert_eq!(buf.find_subset(&sub), Some(3));
}
#[test]
fn find_subset_partial_after_end() {
    let buf = vec![0x01, 0x02, 0x03, 0x04, 0x05];
    let sub = vec![0x00, 0x05, 0x00, 0x06];
    assert_eq!(buf.find_subset(&sub), None);
}
#[test]
fn find_subset_partial_before_start() {
    let buf = vec![0x01, 0x02, 0x03, 0x04, 0x05];
    let sub = vec![0x00, 0x00, 0x00, 0x01];
    assert_eq!(buf.find_subset(&sub), None);
}
#[test]
fn find_subset_short() {
    let buf = vec![0x01, 0x02, 0x03, 0x04, 0x05];
    let sub = vec![0x00, 0x02];
    assert_eq!(buf.find_subset(&sub), Some(1));
}
#[test]
fn find_subset_too_long() {
    let buf = vec![0x01, 0x02, 0x03, 0x04, 0x05];
    let sub = vec![
        0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06,
    ];
    assert_eq!(buf.find_subset(&sub), None);
}
#[test]
fn find_subset_full() {
    let buf = vec![0x01, 0x02, 0x03, 0x04, 0x05];
    let sub = vec![0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05];
    assert_eq!(buf.find_subset(&sub), Some(0));
}
#[test]
fn find_subset_swapped() {
    let buf = vec![0x01, 0x02, 0x03, 0x04, 0x05];
    let sub = vec![0x00, 0x05, 0x00, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01];
    assert_eq!(buf.find_subset(&sub), None);
}
#[test]
fn find_subset_higher_than_9() {
    let buf = vec![0x0A, 0x0C, 0x0D, 0x0E, 0x0F];
    let sub = vec![0x00, 0x0C, 0x00, 0x0D, 0x00, 0x0E];
    assert_eq!(buf.find_subset(&sub), Some(1));
}
#[test]
fn find_subset_higher_than_f() {
    let buf = vec![0x0A, 0x3C, 0x1D, 0xEE, 0x0F];
    let sub = vec![0x03, 0x0C, 0x01, 0x0D, 0x0E, 0x0E];
    assert_eq!(buf.find_subset(&sub), Some(1));
}
#[test]
fn find_with_single_wildcard_0x10() {
    let buf = vec![0x0A, 0x3C, 0x1D, 0xEE, 0x0F];
    let sub = vec![0x03, 0x0C, 0x01, 0x10, 0x0E, 0x0E];
    assert_eq!(buf.find_subset(&sub), Some(1));
}
#[test]
fn find_with_wildcard_0xf0() {
    let buf = vec![0x0A, 0x3C, 0x1D, 0xEE, 0x0F];
    let sub = vec![0x03, 0x0C, 0xF0, 0xF0, 0x0E, 0x0E];
    assert_eq!(buf.find_subset(&sub), Some(1));
}
#[test]
fn find_with_wildcard_xX() {
    let buf = vec![0x0A, 0x3C, 0x1D, 0xEE, 0x0F];
    let sub = vec![0x03, 0x0C, 'x' as u8, 'X' as u8, 0x0E, 0x0E];
    assert_eq!(buf.find_subset(&sub), Some(1));
}
#[test]
fn find_with_wildcards() {
    let buf = vec![0x0A, 0x3C, 0x1D, 0xEE, 0x0F];
    let sub = vec![0x10, 0x10, 0x10, 0x10, 0x10, 0x10];
    assert_eq!(buf.find_subset(&sub), Some(0));
}
#[test]
fn find_shifted() {
    let buf = vec![0x0A, 0x3C, 0x1D, 0xEE, 0x0F];
    let sub = vec![0x0A, 0x03];
    assert_eq!(buf.find_subset(&sub), None);
}
<commit_msg>Block rustfmt in find function<commit_after>// To search for nibbles in a byte array.
// Requires two nibbles per byte.
// All values above 0x0F will be used as wildcard.
// Example: Use x or X as wildcard for a nibble.

pub trait FindOptSubset {
    fn find_subset(&self, subset: &[u8]) -> Option<usize>;
}

impl FindOptSubset for Vec<u8> {
    fn find_subset(&self, subset: &[u8]) -> Option<usize> {
        if subset.len() > 2 * self.len() {
            return None;
        }
        if subset.len() % 2 != 0 {
            // Must be dividable by two
            return None;
        }
        // Search in a for b
        for a in 0..self.len() - subset.len() / 2 + 1 {
            for b in 0..subset.len() / 2 {
                // if b is not a, skip searching at that position in a
                // Logic: both match, ...
                // or first nibble matches when second nibble is wildcard,
                // or second nibble matches when first nibble is wildcard.
                // or two wildcards at that position.
                #[rustfmt_skip]
                if !(
                    ((subset[2*b  ] == self[a + b]>>4) && (subset[2*b+1] == self[a + b]%16)) ||
                    ((subset[2*b  ] == self[a + b]>>4) && (subset[2*b+1] >= 0x10)) ||
                    ((subset[2*b+1] == self[a + b]%16) && (subset[2*b  ] >= 0x10)) ||
                    ((subset[2*b+1] >= 0x10) && (subset[2*b  ] >= 0x10))
                   )
                {
                    break; // element does not match
                }
                // when all elements of b match in a, return position of a
                if b == subset.len() / 2 - 1 {
                    return Some(a);
                }
            }
        }
        None
    }
}

#[test]
fn find_subset_partial_at_start() {
    let buf = vec![0x01, 0x02, 0x03, 0x04, 0x05];
    let sub = vec![0x00, 0x01];
    assert_eq!(buf.find_subset(&sub), Some(0));
}
#[test]
fn find_subset_partial_at_middle() {
    let buf = vec![0x01, 0x02, 0x03, 0x04, 0x05];
    let sub = vec![0x00, 0x03, 0x00, 0x04];
    assert_eq!(buf.find_subset(&sub), Some(2));
}
#[test]
fn find_subset_partial_at_end() {
    let buf = vec![0x01, 0x02, 0x03, 0x04, 0x05];
    let sub = vec![0x00, 0x04, 0x00, 0x05];
    assert_eq!(buf.find_subset(&sub), Some(3));
}
#[test]
fn find_subset_partial_after_end() {
    let buf = vec![0x01, 0x02, 0x03, 0x04, 0x05];
    let sub = vec![0x00, 0x05, 0x00, 0x06];
    assert_eq!(buf.find_subset(&sub), None);
}
#[test]
fn find_subset_partial_before_start() {
    let buf = vec![0x01, 0x02, 0x03, 0x04, 0x05];
    let sub = vec![0x00, 0x00, 0x00, 0x01];
    assert_eq!(buf.find_subset(&sub), None);
}
#[test]
fn find_subset_short() {
    let buf = vec![0x01, 0x02, 0x03, 0x04, 0x05];
    let sub = vec![0x00, 0x02];
    assert_eq!(buf.find_subset(&sub), Some(1));
}
#[test]
fn find_subset_too_long() {
    let buf = vec![0x01, 0x02, 0x03, 0x04, 0x05];
    let sub = vec![
        0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06,
    ];
    assert_eq!(buf.find_subset(&sub), None);
}
#[test]
fn find_subset_full() {
    let buf = vec![0x01, 0x02, 0x03, 0x04, 0x05];
    let sub = vec![0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05];
    assert_eq!(buf.find_subset(&sub), Some(0));
}
#[test]
fn find_subset_swapped() {
    let buf = vec![0x01, 0x02, 0x03, 0x04, 0x05];
    let sub = vec![0x00, 0x05, 0x00, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01];
    assert_eq!(buf.find_subset(&sub), None);
}
#[test]
fn find_subset_higher_than_9() {
    let buf = vec![0x0A, 0x0C, 0x0D, 0x0E, 0x0F];
    let sub = vec![0x00, 0x0C, 0x00, 0x0D, 0x00, 0x0E];
    assert_eq!(buf.find_subset(&sub), Some(1));
}
#[test]
fn find_subset_higher_than_f() {
    let buf = vec![0x0A, 0x3C, 0x1D, 0xEE, 0x0F];
    let sub = vec![0x03, 0x0C, 0x01, 0x0D, 0x0E, 0x0E];
    assert_eq!(buf.find_subset(&sub), Some(1));
}
#[test]
fn find_with_single_wildcard_0x10() {
    let buf = vec![0x0A, 0x3C, 0x1D, 0xEE, 0x0F];
    let sub = vec![0x03, 0x0C, 0x01, 0x10, 0x0E, 0x0E];
    assert_eq!(buf.find_subset(&sub), Some(1));
}
#[test]
fn find_with_wildcard_0xf0() {
    let buf = vec![0x0A, 0x3C, 0x1D, 0xEE, 0x0F];
    let sub = vec![0x03, 0x0C, 0xF0, 0xF0, 0x0E, 0x0E];
    assert_eq!(buf.find_subset(&sub), Some(1));
}
#[test]
fn find_with_wildcard_xX() {
    let buf = vec![0x0A, 0x3C, 0x1D, 0xEE, 0x0F];
    let sub = vec![0x03, 0x0C, 'x' as u8, 'X' as u8, 0x0E, 0x0E];
    assert_eq!(buf.find_subset(&sub), Some(1));
}
#[test]
fn find_with_wildcards() {
    let buf = vec![0x0A, 0x3C, 0x1D, 0xEE, 0x0F];
    let sub = vec![0x10, 0x10, 0x10, 0x10, 0x10, 0x10];
    assert_eq!(buf.find_subset(&sub), Some(0));
}
#[test]
fn find_shifted() {
    let buf = vec![0x0A, 0x3C, 0x1D, 0xEE, 0x0F];
    let sub = vec![0x0A, 0x03];
    assert_eq!(buf.find_subset(&sub), None);
}
<|endoftext|>


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

use object::{Ability, Object, ObjectDetails};
use id::{Id, get_id};
use player::Player;
use timestamp::get_timestamp;
use zone::{Zone, ZoneDetails};

/// Represents the game's current phase
#[derive(Debug, Clone, PartialEq)]
pub enum GamePhase {
    Untap,
    Main,

    // TODO: Other game phases
}

impl GamePhase {
    /// Find the next phase for the game, if there is one.
    ///
    /// Returning `None` signifies that the turn should advance.
    pub fn next(&self) -> Option<GamePhase> {
        match *self {
            GamePhase::Untap => Some(GamePhase::Main),
            GamePhase::Main => None,
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum GameStatus {
    NeedsPlayerAction,

    // TODO: Represent winners and potential draw
    Ended,

    // TODO: Represent unrecoverable internal error?
}

/// Defines all of the actions that a player can take when they have
#[derive(Debug, Clone)]
pub enum PlayerAction {
    Concede,
    PassPriority,
    PlayLand {
        object_id: Id,
    },
    ActivateAbility {
        object_id: Id,
        ability_id: Id,
    },

    // TODO: Other possible player actions

    // Some potentially interesting actions:
    // * Flip a morph card (doesn't need priority)
}

/// Defines all of the issues we can run into when performing a player action
#[derive(Debug, Clone)]
pub enum PlayerActionError {
    /// Denotes anything that a player isn't allowed to do.
    ///
    /// TODO: Break this into more variants as needed
    NotAllowed(&'static str),
}

/// Will be used to define mutations to the game state. Mutations are defined as
/// objects so that effects can respond to and replace them.
#[derive(Debug, Clone)]
pub enum GameMutation {
}

/// Represents all of the important serializable information about a game.
///
/// `Game` cycles between two primary statuses:
/// * `GameStatus::Processing` -- the game is currently processing
/// * `GameStatus::NeedsPlayerAction` -- the game requires a response from the
///   player who has priority, defined by `priority_player`.
///
/// All mutation to the game will come from `PlayerAction` and `GameMutation`
/// objects, which will be filtered by effects created by the game's rules.
#[derive(Debug, Clone)]
pub struct Game {
    pub zones: HashMap<Id, Zone>,
    pub players: HashMap<Id, Player>,

    /// The base definition of each object in the game, before being modified by
    /// the currently active effects.
    pub objects: HashMap<Id, Object>,

    /// A simple representation of mana pools: the amount of green mana each
    /// player has. This will need to be expanded!
    pub mana_pools: HashMap<Id, usize>,

    /// The order that players have their turns in.
    pub player_turn_order: Vec<Id>,

    /// The player whose turn it is right now.
    ///
    /// I'm not sure if there's a game state in which there is no active player,
    /// but it simplifies initialization of `Game`!
    pub active_player: Option<Id>,

    /// The player who currently has priority.
    ///
    /// In certain parts of the game, like resolution of state-based-actions and
    /// the untap step, no players have priority.
    pub priority_player: Option<Id>,

    /// The current phase of the game, as defined in the game rules.
    pub current_phase: GamePhase,

    /// The current game status, defining the core interaction loop.
    pub current_status: GameStatus,

    // TODO: A reference to an object descriptor pool, like what cards are legal
    //       in this format.
    // TODO: The stack, a Vec<Object>?
    // TODO: A log of player actions
    // TODO: A list of currently active effects and their durations
}

impl Game {
    /// Checks that the given player has priority, and returns the appropriate
    /// `PlayerActionError` if they do not.
    fn check_priority(&self, acting_player_id: Id) -> Result<(), PlayerActionError> {
        match self.priority_player {
            Some(priority_id) => {
                if acting_player_id == priority_id {
                    Ok(())
                } else {
                    Err(PlayerActionError::NotAllowed("Player does not have priority"))
                }
            },
            None => Err(PlayerActionError::NotAllowed("No player has priority")),
        }
    }

    /// Process the given player action.
    pub fn do_player_action(&mut self, acting_player_id: Id, action: &PlayerAction) -> Result<(), PlayerActionError> {
        // Players can only take an action if the game can accept one!
        match self.current_status {
            GameStatus::NeedsPlayerAction => {},
            _ => return Err(PlayerActionError::NotAllowed("Game unable to accept actions at this time")),
        }

        // We'll break the actual action handling into a private routine
        // eventually
        match *action {
            PlayerAction::Concede => {
                self.current_status = GameStatus::Ended;

                Ok(())
            },
            PlayerAction::PassPriority => {
                self.check_priority(acting_player_id)?;

                let current_priority_index = self.player_turn_order
                    .iter()
                    .position(|&id| id == acting_player_id)
                    .expect("Player with priority is missing from player_turn_order!");

                let current_active_id = self.active_player.unwrap();
                let current_active_index = self.player_turn_order
                    .iter()
                    .position(|&id| id == current_active_id)
                    .expect("Player with priority is missing from player_turn_order!");

                let player_count = self.player_turn_order.len();

                let next_priority_index = (current_priority_index + 1) % player_count;
                let next_priority_id = self.player_turn_order[next_priority_index];

                // If priority would swing back around to the active player,
                // it's time to advance!
                if next_priority_id == current_active_id {
                    // TODO: Pop one item off the stack if not empty

                    // Are we at the end of the turn?
                    match self.current_phase.next() {
                        Some(next_phase) => {
                            // To the next phase!
                            self.current_phase = next_phase;
                            self.priority_player = self.active_player;

                            // TODO: Empty mana pools of all players
                        },
                        None => {
                            // We're out of phases, advance turns!
                            let next_active_index = (current_active_index + 1) % player_count;
                            let next_active_id = self.player_turn_order[next_active_index];

                            self.active_player = Some(next_active_id);
                            self.priority_player = Some(next_active_id);
                        },
                    }
                } else {
                    self.priority_player = Some(next_priority_id);
                }

                Ok(())
            },
            PlayerAction::PlayLand { object_id } => {
                // TODO: Players can only play lands when it's their turn
                // TODO: Players can only play lands during a main phase
                // TODO: Players can only play lands when the stack is empty

                self.check_priority(acting_player_id)?;

                let player_hand_id = self
                    .find_zone_id(|zone| {
                        match zone.details {
                            ZoneDetails::Hand { player_id } => player_id == acting_player_id,
                            _ => false,
                        }
                    })
                    .expect("Unable to locate player's hand!");

                let battlefield_id = self
                    .find_zone_id(|zone| {
                        match zone.details {
                            ZoneDetails::Battlefield => true,
                            _ => false,
                        }
                    })
                    .expect("Unable to locate battlefield!");

                // We need to make sure we have a land to play!
                match self.objects.get(&object_id) {
                    Some(object) => {
                        // Make sure it's in our player's hand
                        if object.zone != player_hand_id {
                            return Err(PlayerActionError::NotAllowed("Land not in player's hand"));
                        }

                        // Make sure it's a land
                        match object.details {
                            ObjectDetails::Forest { .. } => {},
                            // TODO: Other object details, when they're introduced
                        }
                    }
                    None => return Err(PlayerActionError::NotAllowed("Object not found")),
                }

                // We just checked to make sure this existed above!
                let object = self.objects.remove(&object_id).unwrap();

                // For now, let's just generate a new object and put it on the
                // battlefield.
                let new_object = Object {
                    id: get_id(),
                    zone: battlefield_id,
                    timestamp: get_timestamp(),
                    details: object.details,
                    abilities: object.abilities,
                };

                // TODO: Use GameMutation instead?
                self.objects.insert(new_object.id, new_object);

                Ok(())
            },
            PlayerAction::ActivateAbility { object_id, ability_id } => {
                // TODO: This function is definitely temporary, like the rest of
                //       the ability system.

                self.check_priority(acting_player_id)?;

                let mut object = match self.objects.get_mut(&object_id) {
                    Some(object) => object,
                    None => return Err(PlayerActionError::NotAllowed("Object not found")),
                };

                // TODO: Make sure the acting player controls this object!

                let ability = match object.abilities.get(&ability_id) {
                    Some(ability) => ability,
                    None => return Err(PlayerActionError::NotAllowed("Ability not found on object")),
                };

                //  such green
                //       so forest
                //    wow
                match *ability {
                    Ability::AddGreen => {
                        // Make sure we're on the battlefield! Abilities will
                        // have to specify when they are valid to activate.
                        match self.zones.get(&object.zone) {
                            Some(zone) => match zone.details {
                                ZoneDetails::Battlefield => {},
                                _ => return Err(PlayerActionError::NotAllowed("Object not on battlefield")),
                            },
                            None => return Err(PlayerActionError::NotAllowed("Could not find object's zone by ID")),
                        }

                        // Make sure our land is untapped
                        match object.details {
                            ObjectDetails::Forest { tapped } => {
                                if tapped {
                                    return Err(PlayerActionError::NotAllowed("Object already tapped"));
                                }

                                // Tap the land!
                                object.details = ObjectDetails::Forest {
                                    tapped: true
                                };
                            }
                        }

                        // Find our mana pool and increment it
                        // Eventually, mana will be more complex than a usize
                        let mana_value = *self.mana_pools.get(&acting_player_id)
                            .expect("Player was missing their mana pool!");

                        self.mana_pools.insert(acting_player_id, mana_value + 1);
                    },
                }

                Ok(())
            },
        }
    }

    /// Apply all state-based actions, like creatures dying due to damage.
    pub fn process_state_based_actions(&mut self) {
        // TODO: State based actions!
    }

    /// Finds the zone that passes the given condition, if it exists.
    pub fn find_zone_id<F>(&self, predicate: F) -> Option<Id>
    where
        F: Fn(&Zone) -> bool
    {
        self.zones.values()
            .find(|zone| predicate(zone))
            .and_then(|zone| Some(zone.id))
    }

    /// Create a version of `Game` as viewed by the given player. This
    /// should collapse hidden zones and unknown information. Hopefully, it's
    /// also cheap, since the most naive way to implement client communication
    /// would be to send a full state on every change!
    pub fn view_as_player(&self, _player_id: Id) -> Game {
        // TODO: Hide objects that player has no knowledge of, like face-down
        //       permanents.

        // TODO: Hide zones that player has no knowledge of, like libraries, and
        //       face-down exile zones created by cards like Bomat Courier.

        self.clone()
    }

    /// Queries an object in the game by ID.
    ///
    /// Object representation may be unintuitive -- the `Object` objects stored
    /// in the `Game` only contain their base state. When querying an
    /// object's current state, we need to traverse a list of effects currently
    /// modifying that object in layer order.
    ///
    /// As an example, consider a Mountain enchanted by Spreading Seas:
    ///
    /// The definition of Mountain says that it has type `Basic Land - Mountain`
    /// and thus has `{T}: Add {R} to your mana pool`.
    ///
    /// Spreading Seas, when on the battlefield, has a replacement effect for
    /// that removes its target's abilities and changes its type line to `Basic
    /// Land - Island`.
    ///
    /// The mountain's current state (post-effect) thus says that it has type
    /// `Basic Land - Island` and taps for blue mana only!
    ///
    /// If we wanted to return the Mountain object directly, we'd either have to
    /// modify the data whenever an effect enters/leaves the battlefield or just
    /// keep a list of active effects and calculate them on each observation.
    ///
    /// While the former technique is possible, I think that calculating effects
    /// on each individual observation event is simpler.
    pub fn view_object(&self, object_id: Id) -> Option<Object> {
        let base_object = self.objects.get(&object_id)?;

        // TODO: Enumerate the set of effects that could affect this object.

        Some(base_object.clone())
    }
}
<commit_msg>Add another TODO for land playing<commit_after>use std::collections::HashMap;

use object::{Ability, Object, ObjectDetails};
use id::{Id, get_id};
use player::Player;
use timestamp::get_timestamp;
use zone::{Zone, ZoneDetails};

/// Represents the game's current phase
#[derive(Debug, Clone, PartialEq)]
pub enum GamePhase {
    Untap,
    Main,

    // TODO: Other game phases
}

impl GamePhase {
    /// Find the next phase for the game, if there is one.
    ///
    /// Returning `None` signifies that the turn should advance.
    pub fn next(&self) -> Option<GamePhase> {
        match *self {
            GamePhase::Untap => Some(GamePhase::Main),
            GamePhase::Main => None,
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum GameStatus {
    NeedsPlayerAction,

    // TODO: Represent winners and potential draw
    Ended,

    // TODO: Represent unrecoverable internal error?
}

/// Defines all of the actions that a player can take when they have
#[derive(Debug, Clone)]
pub enum PlayerAction {
    Concede,
    PassPriority,
    PlayLand {
        object_id: Id,
    },
    ActivateAbility {
        object_id: Id,
        ability_id: Id,
    },

    // TODO: Other possible player actions

    // Some potentially interesting actions:
    // * Flip a morph card (doesn't need priority)
}

/// Defines all of the issues we can run into when performing a player action
#[derive(Debug, Clone)]
pub enum PlayerActionError {
    /// Denotes anything that a player isn't allowed to do.
    ///
    /// TODO: Break this into more variants as needed
    NotAllowed(&'static str),
}

/// Will be used to define mutations to the game state. Mutations are defined as
/// objects so that effects can respond to and replace them.
#[derive(Debug, Clone)]
pub enum GameMutation {
}

/// Represents all of the important serializable information about a game.
///
/// `Game` cycles between two primary statuses:
/// * `GameStatus::Processing` -- the game is currently processing
/// * `GameStatus::NeedsPlayerAction` -- the game requires a response from the
///   player who has priority, defined by `priority_player`.
///
/// All mutation to the game will come from `PlayerAction` and `GameMutation`
/// objects, which will be filtered by effects created by the game's rules.
#[derive(Debug, Clone)]
pub struct Game {
    pub zones: HashMap<Id, Zone>,
    pub players: HashMap<Id, Player>,

    /// The base definition of each object in the game, before being modified by
    /// the currently active effects.
    pub objects: HashMap<Id, Object>,

    /// A simple representation of mana pools: the amount of green mana each
    /// player has. This will need to be expanded!
    pub mana_pools: HashMap<Id, usize>,

    /// The order that players have their turns in.
    pub player_turn_order: Vec<Id>,

    /// The player whose turn it is right now.
    ///
    /// I'm not sure if there's a game state in which there is no active player,
    /// but it simplifies initialization of `Game`!
    pub active_player: Option<Id>,

    /// The player who currently has priority.
    ///
    /// In certain parts of the game, like resolution of state-based-actions and
    /// the untap step, no players have priority.
    pub priority_player: Option<Id>,

    /// The current phase of the game, as defined in the game rules.
    pub current_phase: GamePhase,

    /// The current game status, defining the core interaction loop.
    pub current_status: GameStatus,

    // TODO: A reference to an object descriptor pool, like what cards are legal
    //       in this format.
    // TODO: The stack, a Vec<Object>?
    // TODO: A log of player actions
    // TODO: A list of currently active effects and their durations
}

impl Game {
    /// Checks that the given player has priority, and returns the appropriate
    /// `PlayerActionError` if they do not.
    fn check_priority(&self, acting_player_id: Id) -> Result<(), PlayerActionError> {
        match self.priority_player {
            Some(priority_id) => {
                if acting_player_id == priority_id {
                    Ok(())
                } else {
                    Err(PlayerActionError::NotAllowed("Player does not have priority"))
                }
            },
            None => Err(PlayerActionError::NotAllowed("No player has priority")),
        }
    }

    /// Process the given player action.
    pub fn do_player_action(&mut self, acting_player_id: Id, action: &PlayerAction) -> Result<(), PlayerActionError> {
        // Players can only take an action if the game can accept one!
        match self.current_status {
            GameStatus::NeedsPlayerAction => {},
            _ => return Err(PlayerActionError::NotAllowed("Game unable to accept actions at this time")),
        }

        // We'll break the actual action handling into a private routine
        // eventually
        match *action {
            PlayerAction::Concede => {
                self.current_status = GameStatus::Ended;

                Ok(())
            },
            PlayerAction::PassPriority => {
                self.check_priority(acting_player_id)?;

                let current_priority_index = self.player_turn_order
                    .iter()
                    .position(|&id| id == acting_player_id)
                    .expect("Player with priority is missing from player_turn_order!");

                let current_active_id = self.active_player.unwrap();
                let current_active_index = self.player_turn_order
                    .iter()
                    .position(|&id| id == current_active_id)
                    .expect("Player with priority is missing from player_turn_order!");

                let player_count = self.player_turn_order.len();

                let next_priority_index = (current_priority_index + 1) % player_count;
                let next_priority_id = self.player_turn_order[next_priority_index];

                // If priority would swing back around to the active player,
                // it's time to advance!
                if next_priority_id == current_active_id {
                    // TODO: Pop one item off the stack if not empty

                    // Are we at the end of the turn?
                    match self.current_phase.next() {
                        Some(next_phase) => {
                            // To the next phase!
                            self.current_phase = next_phase;
                            self.priority_player = self.active_player;

                            // TODO: Empty mana pools of all players
                        },
                        None => {
                            // We're out of phases, advance turns!
                            let next_active_index = (current_active_index + 1) % player_count;
                            let next_active_id = self.player_turn_order[next_active_index];

                            self.active_player = Some(next_active_id);
                            self.priority_player = Some(next_active_id);
                        },
                    }
                } else {
                    self.priority_player = Some(next_priority_id);
                }

                Ok(())
            },
            PlayerAction::PlayLand { object_id } => {
                // TODO: Players can only play lands when it's their turn
                // TODO: Players can only play lands during a main phase
                // TODO: Players can only play lands when the stack is empty
                // TODO: Players can only play one land per turn

                self.check_priority(acting_player_id)?;

                let player_hand_id = self
                    .find_zone_id(|zone| {
                        match zone.details {
                            ZoneDetails::Hand { player_id } => player_id == acting_player_id,
                            _ => false,
                        }
                    })
                    .expect("Unable to locate player's hand!");

                let battlefield_id = self
                    .find_zone_id(|zone| {
                        match zone.details {
                            ZoneDetails::Battlefield => true,
                            _ => false,
                        }
                    })
                    .expect("Unable to locate battlefield!");

                // We need to make sure we have a land to play!
                match self.objects.get(&object_id) {
                    Some(object) => {
                        // Make sure it's in our player's hand
                        if object.zone != player_hand_id {
                            return Err(PlayerActionError::NotAllowed("Land not in player's hand"));
                        }

                        // Make sure it's a land
                        match object.details {
                            ObjectDetails::Forest { .. } => {},
                            // TODO: Other object details, when they're introduced
                        }
                    }
                    None => return Err(PlayerActionError::NotAllowed("Object not found")),
                }

                // We just checked to make sure this existed above!
                let object = self.objects.remove(&object_id).unwrap();

                // For now, let's just generate a new object and put it on the
                // battlefield.
                let new_object = Object {
                    id: get_id(),
                    zone: battlefield_id,
                    timestamp: get_timestamp(),
                    details: object.details,
                    abilities: object.abilities,
                };

                // TODO: Use GameMutation instead?
                self.objects.insert(new_object.id, new_object);

                Ok(())
            },
            PlayerAction::ActivateAbility { object_id, ability_id } => {
                // TODO: This function is definitely temporary, like the rest of
                //       the ability system.

                self.check_priority(acting_player_id)?;

                let mut object = match self.objects.get_mut(&object_id) {
                    Some(object) => object,
                    None => return Err(PlayerActionError::NotAllowed("Object not found")),
                };

                // TODO: Make sure the acting player controls this object!

                let ability = match object.abilities.get(&ability_id) {
                    Some(ability) => ability,
                    None => return Err(PlayerActionError::NotAllowed("Ability not found on object")),
                };

                //  such green
                //       so forest
                //    wow
                match *ability {
                    Ability::AddGreen => {
                        // Make sure we're on the battlefield! Abilities will
                        // have to specify when they are valid to activate.
                        match self.zones.get(&object.zone) {
                            Some(zone) => match zone.details {
                                ZoneDetails::Battlefield => {},
                                _ => return Err(PlayerActionError::NotAllowed("Object not on battlefield")),
                            },
                            None => return Err(PlayerActionError::NotAllowed("Could not find object's zone by ID")),
                        }

                        // Make sure our land is untapped
                        match object.details {
                            ObjectDetails::Forest { tapped } => {
                                if tapped {
                                    return Err(PlayerActionError::NotAllowed("Object already tapped"));
                                }

                                // Tap the land!
                                object.details = ObjectDetails::Forest {
                                    tapped: true
                                };
                            }
                        }

                        // Find our mana pool and increment it
                        // Eventually, mana will be more complex than a usize
                        let mana_value = *self.mana_pools.get(&acting_player_id)
                            .expect("Player was missing their mana pool!");

                        self.mana_pools.insert(acting_player_id, mana_value + 1);
                    },
                }

                Ok(())
            },
        }
    }

    /// Apply all state-based actions, like creatures dying due to damage.
    pub fn process_state_based_actions(&mut self) {
        // TODO: State based actions!
    }

    /// Finds the zone that passes the given condition, if it exists.
    pub fn find_zone_id<F>(&self, predicate: F) -> Option<Id>
    where
        F: Fn(&Zone) -> bool
    {
        self.zones.values()
            .find(|zone| predicate(zone))
            .and_then(|zone| Some(zone.id))
    }

    /// Create a version of `Game` as viewed by the given player. This
    /// should collapse hidden zones and unknown information. Hopefully, it's
    /// also cheap, since the most naive way to implement client communication
    /// would be to send a full state on every change!
    pub fn view_as_player(&self, _player_id: Id) -> Game {
        // TODO: Hide objects that player has no knowledge of, like face-down
        //       permanents.

        // TODO: Hide zones that player has no knowledge of, like libraries, and
        //       face-down exile zones created by cards like Bomat Courier.

        self.clone()
    }

    /// Queries an object in the game by ID.
    ///
    /// Object representation may be unintuitive -- the `Object` objects stored
    /// in the `Game` only contain their base state. When querying an
    /// object's current state, we need to traverse a list of effects currently
    /// modifying that object in layer order.
    ///
    /// As an example, consider a Mountain enchanted by Spreading Seas:
    ///
    /// The definition of Mountain says that it has type `Basic Land - Mountain`
    /// and thus has `{T}: Add {R} to your mana pool`.
    ///
    /// Spreading Seas, when on the battlefield, has a replacement effect for
    /// that removes its target's abilities and changes its type line to `Basic
    /// Land - Island`.
    ///
    /// The mountain's current state (post-effect) thus says that it has type
    /// `Basic Land - Island` and taps for blue mana only!
    ///
    /// If we wanted to return the Mountain object directly, we'd either have to
    /// modify the data whenever an effect enters/leaves the battlefield or just
    /// keep a list of active effects and calculate them on each observation.
    ///
    /// While the former technique is possible, I think that calculating effects
    /// on each individual observation event is simpler.
    pub fn view_object(&self, object_id: Id) -> Option<Object> {
        let base_object = self.objects.get(&object_id)?;

        // TODO: Enumerate the set of effects that could affect this object.

        Some(base_object.clone())
    }
}
<|endoftext|>


<commit_before>use schema::*;
use diesel::*;
use diesel::query_builder::update;

#[test]
fn test_updating_single_column() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    update(users).set(name.eq("Jim")).execute(&connection).unwrap();

    let expected_data = vec!["Jim".to_string(); 2];
    let data: Vec<String> = users.select(name).load(&connection).unwrap().collect();
    assert_eq!(expected_data, data);
}

#[test]
fn test_updating_single_column_of_single_row() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);

    update(users.filter(id.eq(sean.id))).set(name.eq("Jim"))
        .execute(&connection).unwrap();

    let expected_data = vec!["Tess".to_string(), "Jim".to_string()];
    let data: Vec<String> = users.select(name).load(&connection).unwrap().collect();
    assert_eq!(expected_data, data);
}

#[test]
fn test_updating_nullable_column() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);

    update(users.filter(id.eq(sean.id))).set(hair_color.eq(Some("black")))
        .execute(&connection).unwrap();

    let data: Option<String> = users.select(hair_color)
        .filter(id.eq(sean.id))
        .first(&connection)
        .unwrap();
    assert_eq!(Some("black".to_string()), data);

    update(users.filter(id.eq(sean.id))).set(hair_color.eq(None::<String>))
        .execute(&connection).unwrap();

    let data: QueryResult<Option<String>> = users.select(hair_color)
        .filter(id.eq(sean.id))
        .first(&connection);
    assert_eq!(Ok(None::<String>), data);
}

#[test]
fn test_updating_multiple_columns() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);

    update(users.filter(id.eq(sean.id))).set((
        name.eq("Jim"),
        hair_color.eq(Some("black")),
    )).execute(&connection).unwrap();

    let expected_user = User::with_hair_color(sean.id, "Jim", "black");
    let user = connection.find(users, sean.id);
    assert_eq!(Ok(expected_user), user);
}

#[test]
fn update_returning_struct() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let user = update(users.filter(id.eq(sean.id))).set(hair_color.eq("black"))
        .get_result(&connection);
    let expected_user = User::with_hair_color(sean.id, "Sean", "black");

    assert_eq!(Ok(expected_user), user);
}

#[test]
fn update_with_struct_as_changes() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let changes = NewUser::new("Jim", Some("blue"));

    let user = update(users.filter(id.eq(sean.id))).set(&changes)
        .get_result(&connection);
    let expected_user = User::with_hair_color(sean.id, "Jim", "blue");

    assert_eq!(Ok(expected_user), user);
}

#[test]
fn update_with_struct_does_not_set_primary_key() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let other_id = sean.id + 1;
    let changes = User::with_hair_color(other_id, "Jim", "blue");

    let user = update(users.filter(id.eq(sean.id))).set(&changes)
        .get_result(&connection);
    let expected_user = User::with_hair_color(sean.id, "Jim", "blue");

    assert_eq!(Ok(expected_user), user);
}

#[test]
fn save_on_struct_with_primary_key_changes_that_struct() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let user = User::with_hair_color(sean.id, "Jim", "blue").save_changes::<User>(&connection);

    let user_in_db = connection.find(users, sean.id);

    assert_eq!(user, user_in_db);
}

#[test]
fn option_fields_on_structs_are_not_assigned() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    update(users.filter(id.eq(sean.id)))
        .set(hair_color.eq("black"))
        .execute(&connection).unwrap();
    let user = User::new(sean.id, "Jim").save_changes(&connection);

    let expected_user = User::with_hair_color(sean.id, "Jim", "black");
    assert_eq!(Ok(expected_user), user);
}

#[test]
fn sql_syntax_is_correct_when_option_field_comes_before_non_option() {
    #[changeset_for(users)]
    struct Changes {
        hair_color: Option<String>,
        name: String,
    }

    let changes = Changes { hair_color: None, name: "Jim".into() };
    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let user = update(users::table.filter(users::id.eq(sean.id))).set(&changes)
        .get_result(&connection);

    let expected_user = User::new(sean.id, "Jim");
    assert_eq!(Ok(expected_user), user);
}

#[test]
fn sql_syntax_is_correct_when_option_field_comes_mixed_with_non_option() {
    #[changeset_for(posts)]
    struct Changes {
        user_id: i32,
        title: Option<String>,
        body: String,
    }

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let new_post = sean.new_post("Hello", Some("world"));
    insert(&new_post).into(posts::table).execute(&connection).unwrap();

    let changes = Changes { user_id: 1, title: None, body: "earth".into() };
    let post = update(posts::table)
        .set(&changes)
        .get_result::<Post>(&connection)
        .unwrap();

    let expected_post = Post::new(post.id, sean.id, "Hello".into(), Some("earth".into()));
    assert_eq!(expected_post, post);
}

#[test]
fn can_update_with_struct_containing_single_field() {
    #[changeset_for(posts)]
    struct SetBody {
        body: String,
    }

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let new_post = sean.new_post("Hello", Some("world"));
    insert(&new_post).into(posts::table).execute(&connection).unwrap();

    let changes = SetBody { body: "earth".into() };
    let post = update(posts::table)
        .set(&changes)
        .get_result::<Post>(&connection)
        .unwrap();

    let expected_post = Post::new(post.id, sean.id, "Hello".into(), Some("earth".into()));
    assert_eq!(expected_post, post);
}
<commit_msg>Fix intermittent test failure<commit_after>use schema::*;
use diesel::*;
use diesel::query_builder::update;

#[test]
fn test_updating_single_column() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    update(users).set(name.eq("Jim")).execute(&connection).unwrap();

    let expected_data = vec!["Jim".to_string(); 2];
    let data: Vec<String> = users.select(name).load(&connection).unwrap().collect();
    assert_eq!(expected_data, data);
}

#[test]
fn test_updating_single_column_of_single_row() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);

    update(users.filter(id.eq(sean.id))).set(name.eq("Jim"))
        .execute(&connection).unwrap();

    let expected_data = vec!["Jim".to_string(), "Tess".to_string()];
    let data: Vec<String> = users.select(name).order(id).load(&connection).unwrap().collect();
    assert_eq!(expected_data, data);
}

#[test]
fn test_updating_nullable_column() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);

    update(users.filter(id.eq(sean.id))).set(hair_color.eq(Some("black")))
        .execute(&connection).unwrap();

    let data: Option<String> = users.select(hair_color)
        .filter(id.eq(sean.id))
        .first(&connection)
        .unwrap();
    assert_eq!(Some("black".to_string()), data);

    update(users.filter(id.eq(sean.id))).set(hair_color.eq(None::<String>))
        .execute(&connection).unwrap();

    let data: QueryResult<Option<String>> = users.select(hair_color)
        .filter(id.eq(sean.id))
        .first(&connection);
    assert_eq!(Ok(None::<String>), data);
}

#[test]
fn test_updating_multiple_columns() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);

    update(users.filter(id.eq(sean.id))).set((
        name.eq("Jim"),
        hair_color.eq(Some("black")),
    )).execute(&connection).unwrap();

    let expected_user = User::with_hair_color(sean.id, "Jim", "black");
    let user = connection.find(users, sean.id);
    assert_eq!(Ok(expected_user), user);
}

#[test]
fn update_returning_struct() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let user = update(users.filter(id.eq(sean.id))).set(hair_color.eq("black"))
        .get_result(&connection);
    let expected_user = User::with_hair_color(sean.id, "Sean", "black");

    assert_eq!(Ok(expected_user), user);
}

#[test]
fn update_with_struct_as_changes() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let changes = NewUser::new("Jim", Some("blue"));

    let user = update(users.filter(id.eq(sean.id))).set(&changes)
        .get_result(&connection);
    let expected_user = User::with_hair_color(sean.id, "Jim", "blue");

    assert_eq!(Ok(expected_user), user);
}

#[test]
fn update_with_struct_does_not_set_primary_key() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let other_id = sean.id + 1;
    let changes = User::with_hair_color(other_id, "Jim", "blue");

    let user = update(users.filter(id.eq(sean.id))).set(&changes)
        .get_result(&connection);
    let expected_user = User::with_hair_color(sean.id, "Jim", "blue");

    assert_eq!(Ok(expected_user), user);
}

#[test]
fn save_on_struct_with_primary_key_changes_that_struct() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let user = User::with_hair_color(sean.id, "Jim", "blue").save_changes::<User>(&connection);

    let user_in_db = connection.find(users, sean.id);

    assert_eq!(user, user_in_db);
}

#[test]
fn option_fields_on_structs_are_not_assigned() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    update(users.filter(id.eq(sean.id)))
        .set(hair_color.eq("black"))
        .execute(&connection).unwrap();
    let user = User::new(sean.id, "Jim").save_changes(&connection);

    let expected_user = User::with_hair_color(sean.id, "Jim", "black");
    assert_eq!(Ok(expected_user), user);
}

#[test]
fn sql_syntax_is_correct_when_option_field_comes_before_non_option() {
    #[changeset_for(users)]
    struct Changes {
        hair_color: Option<String>,
        name: String,
    }

    let changes = Changes { hair_color: None, name: "Jim".into() };
    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let user = update(users::table.filter(users::id.eq(sean.id))).set(&changes)
        .get_result(&connection);

    let expected_user = User::new(sean.id, "Jim");
    assert_eq!(Ok(expected_user), user);
}

#[test]
fn sql_syntax_is_correct_when_option_field_comes_mixed_with_non_option() {
    #[changeset_for(posts)]
    struct Changes {
        user_id: i32,
        title: Option<String>,
        body: String,
    }

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let new_post = sean.new_post("Hello", Some("world"));
    insert(&new_post).into(posts::table).execute(&connection).unwrap();

    let changes = Changes { user_id: 1, title: None, body: "earth".into() };
    let post = update(posts::table)
        .set(&changes)
        .get_result::<Post>(&connection)
        .unwrap();

    let expected_post = Post::new(post.id, sean.id, "Hello".into(), Some("earth".into()));
    assert_eq!(expected_post, post);
}

#[test]
fn can_update_with_struct_containing_single_field() {
    #[changeset_for(posts)]
    struct SetBody {
        body: String,
    }

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = find_user_by_name("Sean", &connection);
    let new_post = sean.new_post("Hello", Some("world"));
    insert(&new_post).into(posts::table).execute(&connection).unwrap();

    let changes = SetBody { body: "earth".into() };
    let post = update(posts::table)
        .set(&changes)
        .get_result::<Post>(&connection)
        .unwrap();

    let expected_post = Post::new(post.id, sean.id, "Hello".into(), Some("earth".into()));
    assert_eq!(expected_post, post);
}
<|endoftext|>