<commit_before>extern crate core_foundation;
extern crate cgl;
extern crate gleam;

use view::DrawableGeometry;

use cocoa::appkit;
use cocoa::appkit::*;
use cocoa::foundation::*;
use cocoa::base::*;
use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel};
use self::cgl::{CGLEnable, kCGLCECrashOnRemovedFunctions};
use self::core_foundation::base::TCFType;
use self::core_foundation::string::CFString;
use self::core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
use std::os::raw::c_void;
use std::str::FromStr;
use view::{ElementState, MouseButton, ViewEvent, TouchPhase, MouseScrollDelta};
use super::utils;

pub fn register() {
    let superclass = Class::get("NSView").unwrap();
    let mut class = ClassDecl::new("NSServoView", superclass).unwrap();

    class.add_ivar::<*mut c_void>("event_queue");

    extern fn store_nsevent(this: &Object, _sel: Sel, nsevent: id) {
        let event = {
            unsafe {
                let event_type = nsevent.eventType();
                match event_type {
                    NSScrollWheel => {
                        // Stolen from winit
                        use self::MouseScrollDelta::{LineDelta, PixelDelta};
                        let nswindow: id = nsevent.window();
                        let hidpi_factor: CGFloat = msg_send![nswindow, backingScaleFactor];
                        let hidpi_factor = hidpi_factor as f32;
                        let delta = if nsevent.hasPreciseScrollingDeltas() == YES {
                            PixelDelta(hidpi_factor * nsevent.scrollingDeltaX() as f32,
                            hidpi_factor * nsevent.scrollingDeltaY() as f32)
                        } else {
                            LineDelta(hidpi_factor * nsevent.scrollingDeltaX() as f32,
                            hidpi_factor * nsevent.scrollingDeltaY() as f32)
                        };
                        let phase = match nsevent.phase() {
                            appkit::NSEventPhaseMayBegin | appkit::NSEventPhaseBegan => TouchPhase::Started,
                            appkit::NSEventPhaseEnded => TouchPhase::Ended,
                            _ => TouchPhase::Moved,
                        };
                        Some(ViewEvent::MouseWheel(delta, phase))
                    },
                    NSMouseMoved => {
                        let nswindow = nsevent.window();
                        let window_point = nsevent.locationInWindow();
                        let view_point: NSPoint = msg_send![this, convertPoint:window_point fromView:nil];
                        let frame: NSRect = msg_send![this, frame];
                        let hidpi_factor: CGFloat = msg_send![nswindow, backingScaleFactor];
                        let hidpi_factor = hidpi_factor as f32;
                        let x = (hidpi_factor * view_point.x as f32) as i32;
                        let y = (hidpi_factor * (frame.size.height - view_point.y) as f32) as i32;
                        Some(ViewEvent::MouseMoved(x, y))
                    }

                    NSLeftMouseDown => { Some(ViewEvent::MouseInput(ElementState::Pressed, MouseButton::Left)) },
                    NSLeftMouseUp => { Some(ViewEvent::MouseInput(ElementState::Released, MouseButton::Left)) },
                    NSRightMouseDown => { Some(ViewEvent::MouseInput(ElementState::Pressed, MouseButton::Right)) },
                    NSRightMouseUp => { Some(ViewEvent::MouseInput(ElementState::Released, MouseButton::Right)) },
                    NSOtherMouseDown => { Some(ViewEvent::MouseInput(ElementState::Pressed, MouseButton::Middle)) },
                    NSOtherMouseUp => { Some(ViewEvent::MouseInput(ElementState::Released, MouseButton::Middle)) },

                    _ => None
                }
            }

        };

        if let Some(event) = event {
            utils::get_event_queue(this).push(event);
        }
    }

    extern fn awake_from_nib(this: &mut Object, _sel: Sel) {
        // FIXME: is that the best way to create a raw pointer?
        let event_queue: Vec<ViewEvent> = Vec::new();
        let event_queue_ptr = Box::into_raw(Box::new(event_queue));
        unsafe {
            this.set_ivar("event_queue", event_queue_ptr as *mut c_void);
        }
    }

    extern fn accept_first_responder(_this: &Object, _sel: Sel) -> BOOL {
        YES
    }

    extern fn set_frame_size(this: &Object, _sel: Sel, size: NSSize) {
        unsafe {
            msg_send![super(this, Class::get("NSView").unwrap()), setFrameSize:size];
        }
        utils::get_event_queue(this).push(ViewEvent::GeometryDidChange);
    }

    unsafe {
        class.add_method(sel!(scrollWheel:), store_nsevent as extern fn(&Object, Sel, id));
        class.add_method(sel!(mouseDown:), store_nsevent as extern fn(&Object, Sel, id));
        class.add_method(sel!(mouseUp:), store_nsevent as extern fn(&Object, Sel, id));
        class.add_method(sel!(mouseMoved:), store_nsevent as extern fn(&Object, Sel, id));

        class.add_method(sel!(acceptsFirstResponder), accept_first_responder as extern fn(&Object, Sel) -> BOOL);

        class.add_method(sel!(setFrameSize:), set_frame_size as extern fn(&Object, Sel, NSSize));

        class.add_method(sel!(awakeFromNib), awake_from_nib as extern fn(&mut Object, Sel));
    }

    class.register();
}

pub struct View {
    nsview: id,
    context: id,
}

impl View {

    pub fn new(nsview: id) -> View {
        let context: id = View::init_gl(nsview);
        View {
            nsview: nsview,
            context: context
        }
    }

    pub fn swap_buffers(&self) {
        unsafe {
            msg_send![self.context, flushBuffer];
        }
    }

    pub fn update_drawable(&self) {
        unsafe {
            msg_send![self.context, update];
        }
    }

    pub fn get_geometry(&self) -> DrawableGeometry {
        unsafe {
            let nswindow: id = msg_send![self.nsview, window];
            let frame: NSRect = msg_send![self.nsview, frame];
            let hidpi_factor: CGFloat = msg_send![nswindow, backingScaleFactor];
            let visible_rect: NSRect = msg_send![nswindow, contentLayoutRect];

            // FIXME: coordinates are flipped
            let bottom = visible_rect.origin.y - frame.origin.y;
            let top = frame.size.height - bottom - visible_rect.size.height;
            let left = 0;
            let right = 0;

            DrawableGeometry {
                view_size: (frame.size.width as u32, frame.size.height as u32),
                margins: (0,0,0,0), //FIXME
                position: (0, 0),
                hidpi_factor: hidpi_factor as f32,
            }
        }
    }

    pub fn get_events(&self) -> Vec<ViewEvent> {
        let nsobject = unsafe { &*self.nsview};
        utils::get_event_queue(nsobject).drain(..).collect()
    }

    pub fn enter_fullscreen(&self) {
        unsafe {
            msg_send![self.nsview, enterFullScreenMode:nil withOptions:nil];
        }
    }

    pub fn exit_fullscreen(&self) {
        unsafe {
            msg_send![self.nsview, exitFullScreenModeWithOptions:nil];
        }
    }

    fn init_gl(nsview: id) -> id {
        let ctx = unsafe {
            nsview.setWantsBestResolutionOpenGLSurface_(YES);
            let attributes = vec![NSOpenGLPFADoubleBuffer as u32,
                NSOpenGLPFAClosestPolicy as u32,
                NSOpenGLPFAColorSize as u32,
                32,
                NSOpenGLPFAAlphaSize as u32,
                8,
                NSOpenGLPFADepthSize as u32,
                24,
                NSOpenGLPFAStencilSize as u32,
                8,
                NSOpenGLPFAOpenGLProfile as u32,
                NSOpenGLProfileVersion3_2Core as u32,
                0];

            let pixelformat = NSOpenGLPixelFormat::alloc(nil).initWithAttributes_(&attributes);
            let ctx: id = NSOpenGLContext::alloc(nil).initWithFormat_shareContext_(pixelformat, nil);
            msg_send![ctx, setView: nsview];
            let value = 1;
            ctx.setValues_forParameter_(&value, NSOpenGLContextParameter::NSOpenGLCPSwapInterval);
            CGLEnable(ctx.CGLContextObj() as *mut _, kCGLCECrashOnRemovedFunctions);
            ctx
        };

        unsafe {
            msg_send![ctx, update];
            msg_send![ctx, makeCurrentContext];
        };

        gleam::gl::load_with(|addr| {
            let symbol_name: CFString = FromStr::from_str(addr).unwrap();
            let framework_name: CFString = FromStr::from_str("com.apple.opengl").unwrap();
            let framework = unsafe {
                CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef())
            };
            let symbol = unsafe {
                CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef())
            };
            symbol as *const c_void
        });

        gleam::gl::clear_color(1.0, 1.0, 1.0, 1.0);
        gleam::gl::clear(gleam::gl::COLOR_BUFFER_BIT);
        gleam::gl::finish();

        ctx
    }
}

<commit_msg>fix margin calculation<commit_after>extern crate core_foundation;
extern crate cgl;
extern crate gleam;

use view::DrawableGeometry;

use cocoa::appkit;
use cocoa::appkit::*;
use cocoa::foundation::*;
use cocoa::base::*;
use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel};
use self::cgl::{CGLEnable, kCGLCECrashOnRemovedFunctions};
use self::core_foundation::base::TCFType;
use self::core_foundation::string::CFString;
use self::core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
use std::os::raw::c_void;
use std::str::FromStr;
use view::{ElementState, MouseButton, ViewEvent, TouchPhase, MouseScrollDelta};
use super::utils;

pub fn register() {
    let superclass = Class::get("NSView").unwrap();
    let mut class = ClassDecl::new("NSServoView", superclass).unwrap();

    class.add_ivar::<*mut c_void>("event_queue");

    extern fn store_nsevent(this: &Object, _sel: Sel, nsevent: id) {
        let event = {
            unsafe {
                let event_type = nsevent.eventType();
                match event_type {
                    NSScrollWheel => {
                        // Stolen from winit
                        use self::MouseScrollDelta::{LineDelta, PixelDelta};
                        let nswindow: id = nsevent.window();
                        let hidpi_factor: CGFloat = msg_send![nswindow, backingScaleFactor];
                        let hidpi_factor = hidpi_factor as f32;
                        let delta = if nsevent.hasPreciseScrollingDeltas() == YES {
                            PixelDelta(hidpi_factor * nsevent.scrollingDeltaX() as f32,
                            hidpi_factor * nsevent.scrollingDeltaY() as f32)
                        } else {
                            LineDelta(hidpi_factor * nsevent.scrollingDeltaX() as f32,
                            hidpi_factor * nsevent.scrollingDeltaY() as f32)
                        };
                        let phase = match nsevent.phase() {
                            appkit::NSEventPhaseMayBegin | appkit::NSEventPhaseBegan => TouchPhase::Started,
                            appkit::NSEventPhaseEnded => TouchPhase::Ended,
                            _ => TouchPhase::Moved,
                        };
                        Some(ViewEvent::MouseWheel(delta, phase))
                    },
                    NSMouseMoved => {
                        let nswindow = nsevent.window();
                        let window_point = nsevent.locationInWindow();
                        let view_point: NSPoint = msg_send![this, convertPoint:window_point fromView:nil];
                        let frame: NSRect = msg_send![this, frame];
                        let hidpi_factor: CGFloat = msg_send![nswindow, backingScaleFactor];
                        let hidpi_factor = hidpi_factor as f32;
                        let x = (hidpi_factor * view_point.x as f32) as i32;
                        let y = (hidpi_factor * (frame.size.height - view_point.y) as f32) as i32;
                        Some(ViewEvent::MouseMoved(x, y))
                    }

                    NSLeftMouseDown => { Some(ViewEvent::MouseInput(ElementState::Pressed, MouseButton::Left)) },
                    NSLeftMouseUp => { Some(ViewEvent::MouseInput(ElementState::Released, MouseButton::Left)) },
                    NSRightMouseDown => { Some(ViewEvent::MouseInput(ElementState::Pressed, MouseButton::Right)) },
                    NSRightMouseUp => { Some(ViewEvent::MouseInput(ElementState::Released, MouseButton::Right)) },
                    NSOtherMouseDown => { Some(ViewEvent::MouseInput(ElementState::Pressed, MouseButton::Middle)) },
                    NSOtherMouseUp => { Some(ViewEvent::MouseInput(ElementState::Released, MouseButton::Middle)) },

                    _ => None
                }
            }

        };

        if let Some(event) = event {
            utils::get_event_queue(this).push(event);
        }
    }

    extern fn awake_from_nib(this: &mut Object, _sel: Sel) {
        // FIXME: is that the best way to create a raw pointer?
        let event_queue: Vec<ViewEvent> = Vec::new();
        let event_queue_ptr = Box::into_raw(Box::new(event_queue));
        unsafe {
            this.set_ivar("event_queue", event_queue_ptr as *mut c_void);
        }
    }

    extern fn accept_first_responder(_this: &Object, _sel: Sel) -> BOOL {
        YES
    }

    extern fn set_frame_size(this: &Object, _sel: Sel, size: NSSize) {
        unsafe {
            msg_send![super(this, Class::get("NSView").unwrap()), setFrameSize:size];
        }
        utils::get_event_queue(this).push(ViewEvent::GeometryDidChange);
    }

    unsafe {
        class.add_method(sel!(scrollWheel:), store_nsevent as extern fn(&Object, Sel, id));
        class.add_method(sel!(mouseDown:), store_nsevent as extern fn(&Object, Sel, id));
        class.add_method(sel!(mouseUp:), store_nsevent as extern fn(&Object, Sel, id));
        class.add_method(sel!(mouseMoved:), store_nsevent as extern fn(&Object, Sel, id));

        class.add_method(sel!(acceptsFirstResponder), accept_first_responder as extern fn(&Object, Sel) -> BOOL);

        class.add_method(sel!(setFrameSize:), set_frame_size as extern fn(&Object, Sel, NSSize));

        class.add_method(sel!(awakeFromNib), awake_from_nib as extern fn(&mut Object, Sel));
    }

    class.register();
}

pub struct View {
    nsview: id,
    context: id,
}

impl View {

    pub fn new(nsview: id) -> View {
        let context: id = View::init_gl(nsview);
        View {
            nsview: nsview,
            context: context
        }
    }

    pub fn swap_buffers(&self) {
        unsafe {
            msg_send![self.context, flushBuffer];
        }
    }

    pub fn update_drawable(&self) {
        unsafe {
            msg_send![self.context, update];
        }
    }

    pub fn get_geometry(&self) -> DrawableGeometry {
        unsafe {
            let nswindow: id = msg_send![self.nsview, window];
            let content_view: id = msg_send![nswindow, contentView];

            let hidpi_factor: CGFloat = msg_send![nswindow, backingScaleFactor];

            let view_frame: NSRect = msg_send![self.nsview, frame];
            let content_frame: NSRect = msg_send![content_view, frame];
            let visible_rect: NSRect = msg_send![nswindow, contentLayoutRect];

            let bottom = 0;
            let top = (content_frame.size.height - visible_rect.size.height) as u32;
            let left = 0;
            let right = 0;

            DrawableGeometry {
                view_size: (view_frame.size.width as u32, view_frame.size.height as u32),
                margins: (top, right, bottom, left),
                position: (0, 0),
                hidpi_factor: hidpi_factor as f32,
            }
        }
    }

    pub fn get_events(&self) -> Vec<ViewEvent> {
        let nsobject = unsafe { &*self.nsview};
        utils::get_event_queue(nsobject).drain(..).collect()
    }

    pub fn enter_fullscreen(&self) {
        unsafe {
            msg_send![self.nsview, enterFullScreenMode:nil withOptions:nil];
        }
    }

    pub fn exit_fullscreen(&self) {
        unsafe {
            msg_send![self.nsview, exitFullScreenModeWithOptions:nil];
        }
    }

    fn init_gl(nsview: id) -> id {
        let ctx = unsafe {
            nsview.setWantsBestResolutionOpenGLSurface_(YES);
            let attributes = vec![NSOpenGLPFADoubleBuffer as u32,
                NSOpenGLPFAClosestPolicy as u32,
                NSOpenGLPFAColorSize as u32,
                32,
                NSOpenGLPFAAlphaSize as u32,
                8,
                NSOpenGLPFADepthSize as u32,
                24,
                NSOpenGLPFAStencilSize as u32,
                8,
                NSOpenGLPFAOpenGLProfile as u32,
                NSOpenGLProfileVersion3_2Core as u32,
                0];

            let pixelformat = NSOpenGLPixelFormat::alloc(nil).initWithAttributes_(&attributes);
            let ctx: id = NSOpenGLContext::alloc(nil).initWithFormat_shareContext_(pixelformat, nil);
            msg_send![ctx, setView: nsview];
            let value = 1;
            ctx.setValues_forParameter_(&value, NSOpenGLContextParameter::NSOpenGLCPSwapInterval);
            CGLEnable(ctx.CGLContextObj() as *mut _, kCGLCECrashOnRemovedFunctions);
            ctx
        };

        unsafe {
            msg_send![ctx, update];
            msg_send![ctx, makeCurrentContext];
        };

        gleam::gl::load_with(|addr| {
            let symbol_name: CFString = FromStr::from_str(addr).unwrap();
            let framework_name: CFString = FromStr::from_str("com.apple.opengl").unwrap();
            let framework = unsafe {
                CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef())
            };
            let symbol = unsafe {
                CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef())
            };
            symbol as *const c_void
        });

        gleam::gl::clear_color(1.0, 1.0, 1.0, 1.0);
        gleam::gl::clear(gleam::gl::COLOR_BUFFER_BIT);
        gleam::gl::finish();

        ctx
    }
}

<|endoftext|>


<commit_before>use basetypes::*;
use position::castling_rights::*;

/// Represents a move on the chessboard.
///
/// `Move` contains 3 types of information:
///
/// 1. Information about the played move itself.
///
/// 2. Information needed so as to be able to undo the move and
///    restore the board into the exact same state as before.
///
/// 3. The move score -- moves with higher score are tried
///    first. Ideally the best move should have the highest score.
///
/// `Move` is a 32-bit unsigned number. The lowest 16 bits contain the
/// whole needed information about the move itself (type 1). And is
/// laid out the following way:
///
///  ```text
///   15                                                           0
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
///  | Move  |    Origin square      |   Destination square  | Aux   |
///  | type  |       6 bits          |        6 bits         | data  |
///  | 2 bits|   |   |   |   |   |   |   |   |   |   |   |   | 2 bits|
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |       |
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  ```
///
/// There are 4 "move type"s: `0`) normal move; `1`) en-passant
/// capture; `2`) pawn promotion; `3`) castling. "Aux data" encodes
/// the type of the promoted piece if the move type is pawn promotion,
/// otherwise it encodes castling rights (see below).
///
/// The highest 16 bits contain the rest ot the info:
///
///  ```text
///   31                                                          16
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
///  |  Move score   |  Captured |  Played   | Cast- |   En-passant  |
///  |    4 bits     |  piece    |  piece    | ling  |      file     |
///  |   |   |   |   |  3 bits   |  3 bits   | 2 bits|     4 bits    |
///  |   |   |   |   |   |   |   |   |   |   |       |   |   |   |   |
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  ```
///
/// "En-passant file" tells on what vertical line (if any) on the board
/// there was a passing pawn before the move was played.
///
/// Castling rights are a bit complex. The castling rights for the side
/// that makes the move, before the move was made, are stored in the
/// "Aux data" field. This is OK, because promoting a pawn never
/// changes the moving player's castling rights. The castling rights
/// for the opposite side are stored in "Castling" field. (A move can
/// change the castling rights for the other side when a rook in the
/// corner is captured.)
///
/// When "Captured piece" is stored, its bits are inverted, so that
/// MVV-LVA (Most valuable victim -- least valuable aggressor) ordering
/// of the moves is preserved, even when the "Move score" field stays
/// the same.
#[derive(Debug)]
#[derive(Clone, Copy)]
#[derive(PartialOrd, Ord, PartialEq, Eq)]
pub struct Move(u32);

impl Move {
    /// Creates a new instance of `Move`.
    ///
    /// `us` is the side that makes the move. `promoted_piece_code` is
    /// used only when the `move_type` is pawn promotion, otherwise it
    /// is ignored.
    #[inline]
    pub fn new(us: Color,
               score: usize,
               move_type: MoveType,
               piece: PieceType,
               orig_square: Square,
               dest_square: Square,
               captured_piece: PieceType,
               en_passant_file: File,
               castling: CastlingRights,
               promoted_piece_code: usize)
               -> Move {
        assert!(us <= 1);
        assert!(score <= 0b1111);
        assert!(move_type <= 0x11);
        assert!(piece < NO_PIECE);
        assert!(orig_square <= 63);
        assert!(dest_square <= 63);
        assert!(captured_piece != KING && captured_piece <= NO_PIECE);
        assert!(en_passant_file <= 0b1000);
        assert!(promoted_piece_code <= 0b11);
        let aux_data = match move_type {
            MOVE_PROMOTION => promoted_piece_code,
            _ => castling.get_for(us),
        };
        Move((score << M_SHIFT_SCORE | (!captured_piece & 0b111) << M_SHIFT_CAPTURED_PIECE |
              piece << M_SHIFT_PIECE |
              castling.get_for(1 ^ us) << M_SHIFT_CASTLING_DATA |
              en_passant_file << M_SHIFT_ENPASSANT_FILE |
              move_type << M_SHIFT_MOVE_TYPE | orig_square << M_SHIFT_ORIG_SQUARE |
              dest_square << M_SHIFT_DEST_SQUARE |
              aux_data << M_SHIFT_AUX_DATA) as u32)
    }

    /// Sets the "move score" field to a particular value.
    #[inline]
    pub fn set_score(&mut self, score: usize) {
        assert!(score <= 0b1111);
        self.0 &= !M_MASK_SCORE;
        self.0 |= (score << M_SHIFT_SCORE) as u32;
    }

    /// Sets a particular bit in the "move score" field to `1`.
    #[inline]
    pub fn set_score_bit(&mut self, b: usize) {
        assert!(b <= 3);
        self.0 |= 1 << b << M_SHIFT_SCORE;
    }

    /// Sets a particular bit in the "move score" field to `0`.
    #[inline]
    pub fn clear_score_bit(&mut self, b: usize) {
        assert!(b <= 3);
        self.0 &= !(1 << b << M_SHIFT_SCORE);
    }

    #[inline]
    pub fn score(&self) -> usize {
        ((self.0 & M_MASK_SCORE) >> M_SHIFT_SCORE) as usize
    }

    #[inline]
    pub fn move_type(&self) -> MoveType {
        ((self.0 & M_MASK_MOVE_TYPE) >> M_SHIFT_MOVE_TYPE) as MoveType
    }

    #[inline]
    pub fn piece(&self) -> PieceType {
        ((self.0 & M_MASK_PIECE) >> M_SHIFT_PIECE) as PieceType
    }

    #[inline]
    pub fn orig_square(&self) -> Square {
        ((self.0 & M_MASK_ORIG_SQUARE) >> M_SHIFT_ORIG_SQUARE) as Square
    }

    #[inline]
    pub fn dest_square(&self) -> Square {
        ((self.0 & M_MASK_DEST_SQUARE) >> M_SHIFT_DEST_SQUARE) as Square
    }

    #[inline]
    pub fn captured_piece(&self) -> PieceType {
        ((!self.0 & M_MASK_CAPTURED_PIECE) >> M_SHIFT_CAPTURED_PIECE) as PieceType
    }

    #[inline]
    pub fn en_passant_file(&self) -> File {
        ((self.0 & M_MASK_ENPASSANT_FILE) >> M_SHIFT_ENPASSANT_FILE) as File
    }

    #[inline(always)]
    pub fn castling_data(&self) -> usize {
        ((self.0 & M_MASK_CASTLING_DATA) >> M_SHIFT_CASTLING_DATA) as usize
    }

    #[inline(always)]
    pub fn aux_data(&self) -> usize {
        ((self.0 & M_MASK_AUX_DATA) >> M_SHIFT_AUX_DATA) as usize
    }

    /// Gets the promoted piece type from the raw value of "aux data".
    ///
    /// When the "move type" is pawn promotion, "aux data" holds the
    /// promoted piece type encoded with a number from 0 to 3. This
    /// function decodes this number to a piece type.
    #[inline]
    pub fn piece_from_aux_data(pp_code: usize) -> PieceType {
        assert!(pp_code <= 3);
        match pp_code {
            0 => QUEEN,
            1 => ROOK,
            2 => BISHOP,
            _ => KNIGHT,
        }
    }
}

pub const NO_ENPASSANT_FILE: Rank = 8;  // "8" represents no en-passant file

// Field shifts
const M_SHIFT_SCORE: u32 = 28;
const M_SHIFT_CAPTURED_PIECE: u32 = 25;
const M_SHIFT_PIECE: u32 = 22;
const M_SHIFT_CASTLING_DATA: u32 = 20;
const M_SHIFT_ENPASSANT_FILE: u32 = 16;
const M_SHIFT_MOVE_TYPE: u32 = 14;
const M_SHIFT_ORIG_SQUARE: u32 = 8;
const M_SHIFT_DEST_SQUARE: u32 = 2;
const M_SHIFT_AUX_DATA: u32 = 0;

// Field masks
const M_MASK_SCORE: u32 = 0b1111 << M_SHIFT_SCORE;
const M_MASK_CAPTURED_PIECE: u32 = 0b111 << M_SHIFT_CAPTURED_PIECE;
const M_MASK_PIECE: u32 = 0b111 << M_SHIFT_PIECE;
const M_MASK_CASTLING_DATA: u32 = 0b11 << M_SHIFT_CASTLING_DATA;
const M_MASK_ENPASSANT_FILE: u32 = 0b1111 << M_SHIFT_ENPASSANT_FILE;
const M_MASK_MOVE_TYPE: u32 = 0b11 << M_SHIFT_MOVE_TYPE;
const M_MASK_ORIG_SQUARE: u32 = 0b111111 << M_SHIFT_ORIG_SQUARE;
const M_MASK_DEST_SQUARE: u32 = 0b111111 << M_SHIFT_DEST_SQUARE;
const M_MASK_AUX_DATA: u32 = 0b11 << M_SHIFT_AUX_DATA;

// TODO: Here does not seem to be the right place for
// "MoveStack". Find it other owner.
pub struct MoveStack {
    stack: [Move; MOVE_STACK_SIZE],
    next_index: usize,
}

impl MoveStack {
    pub fn new() -> MoveStack {
        use std::mem::uninitialized;
        unsafe {
            MoveStack {
                stack: uninitialized(),
                next_index: 0,
            }
        }
    }

    #[inline(always)]
    pub fn push(&mut self, m: Move) {
        self.stack[self.next_index] = m;
        self.next_index += 1;
    }

    #[inline(always)]
    pub fn pop(&mut self) -> Option<Move> {
        if self.next_index == 0 {
            None
        } else {
            self.next_index -= 1;
            Some(self.stack[self.next_index])
        }
    }

    #[inline(always)]
    pub fn remove_all(&mut self) -> usize {
        let count = self.count();
        self.next_index = 0;
        count
    }

    #[inline(always)]
    pub fn count(&self) -> usize {
        self.next_index
    }
}

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

    #[test]
    fn test_move() {
        use basetypes::*;

        let mut cr = CastlingRights::new();
        cr.set_for(WHITE, 0b10);
        cr.set_for(BLACK, 0b11);
        let mut m = Move::new(WHITE,
                              12,
                              MOVE_NORMAL,
                              PAWN,
                              E2,
                              E4,
                              NO_PIECE,
                              NO_ENPASSANT_FILE,
                              cr,
                              0);
        let n1 = Move::new(WHITE,
                           12,
                           MOVE_NORMAL,
                           PAWN,
                           F3,
                           E4,
                           KNIGHT,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n2 = Move::new(WHITE,
                           12,
                           MOVE_NORMAL,
                           KING,
                           F3,
                           E4,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n3 = Move::new(BLACK,
                           0,
                           MOVE_PROMOTION,
                           PAWN,
                           F2,
                           F1,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           1);
        assert!(n1 > m);
        assert!(n2 < m);
        assert_eq!(m.score(), 12);
        assert_eq!(m.piece(), PAWN);
        assert_eq!(m.captured_piece(), NO_PIECE);
        assert_eq!(m.orig_square(), E2);
        assert_eq!(m.dest_square(), E4);
        assert_eq!(m.en_passant_file(), 8);
        assert_eq!(m.aux_data(), 0b10);
        assert_eq!(m.castling_data(), 0b11);
        let m2 = m;
        assert_eq!(m, m2);
        m.set_score(13);
        assert_eq!(m.score(), 13);
        assert!(m > m2);
        m.clear_score_bit(0);
        assert_eq!(m, m2);
        m.set_score_bit(0);
        assert_eq!(m.score(), 13);
        m.set_score(0);
        assert_eq!(m.score(), 0);
        assert_eq!(n3.aux_data(), 1);
    }
}
<commit_msg>added doc string<commit_after>use basetypes::*;
use position::castling_rights::*;

/// Represents a move on the chessboard.
///
/// `Move` contains 3 types of information:
///
/// 1. Information about the played move itself.
///
/// 2. Information needed so as to be able to undo the move and
///    restore the board into the exact same state as before.
///
/// 3. The move score -- moves with higher score are tried
///    first. Ideally the best move should have the highest score.
///
/// `Move` is a 32-bit unsigned number. The lowest 16 bits contain the
/// whole needed information about the move itself (type 1). And is
/// laid out the following way:
///
///  ```text
///   15                                                           0
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
///  | Move  |    Origin square      |   Destination square  | Aux   |
///  | type  |       6 bits          |        6 bits         | data  |
///  | 2 bits|   |   |   |   |   |   |   |   |   |   |   |   | 2 bits|
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |       |
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  ```
///
/// There are 4 "move type"s: `0`) normal move; `1`) en-passant
/// capture; `2`) pawn promotion; `3`) castling. "Aux data" encodes
/// the type of the promoted piece if the move type is pawn promotion,
/// otherwise it encodes castling rights (see below).
///
/// The highest 16 bits contain the rest ot the info:
///
///  ```text
///   31                                                          16
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
///  |  Move score   |  Captured |  Played   | Cast- |   En-passant  |
///  |    4 bits     |  piece    |  piece    | ling  |      file     |
///  |   |   |   |   |  3 bits   |  3 bits   | 2 bits|     4 bits    |
///  |   |   |   |   |   |   |   |   |   |   |       |   |   |   |   |
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  ```
///
/// "En-passant file" tells on what vertical line (if any) on the board
/// there was a passing pawn before the move was played.
///
/// Castling rights are a bit complex. The castling rights for the side
/// that makes the move, before the move was made, are stored in the
/// "Aux data" field. This is OK, because promoting a pawn never
/// changes the moving player's castling rights. The castling rights
/// for the opposite side are stored in "Castling" field. (A move can
/// change the castling rights for the other side when a rook in the
/// corner is captured.)
///
/// When "Captured piece" is stored, its bits are inverted, so that
/// MVV-LVA (Most valuable victim -- least valuable aggressor) ordering
/// of the moves is preserved, even when the "Move score" field stays
/// the same.
#[derive(Debug)]
#[derive(Clone, Copy)]
#[derive(PartialOrd, Ord, PartialEq, Eq)]
pub struct Move(u32);

impl Move {
    /// Creates a new instance of `Move`.
    ///
    /// `us` is the side that makes the move. `promoted_piece_code` is
    /// used only when the `move_type` is pawn promotion, otherwise it
    /// is ignored.
    #[inline]
    pub fn new(us: Color,
               score: usize,
               move_type: MoveType,
               piece: PieceType,
               orig_square: Square,
               dest_square: Square,
               captured_piece: PieceType,
               en_passant_file: File,
               castling: CastlingRights,
               promoted_piece_code: usize)
               -> Move {
        assert!(us <= 1);
        assert!(score <= 0b1111);
        assert!(move_type <= 0x11);
        assert!(piece < NO_PIECE);
        assert!(orig_square <= 63);
        assert!(dest_square <= 63);
        assert!(captured_piece != KING && captured_piece <= NO_PIECE);
        assert!(en_passant_file <= 0b1000);
        assert!(promoted_piece_code <= 0b11);
        let aux_data = match move_type {
            MOVE_PROMOTION => promoted_piece_code,
            _ => castling.get_for(us),
        };
        Move((score << M_SHIFT_SCORE | (!captured_piece & 0b111) << M_SHIFT_CAPTURED_PIECE |
              piece << M_SHIFT_PIECE |
              castling.get_for(1 ^ us) << M_SHIFT_CASTLING_DATA |
              en_passant_file << M_SHIFT_ENPASSANT_FILE |
              move_type << M_SHIFT_MOVE_TYPE | orig_square << M_SHIFT_ORIG_SQUARE |
              dest_square << M_SHIFT_DEST_SQUARE |
              aux_data << M_SHIFT_AUX_DATA) as u32)
    }

    /// Sets the "move score" field to a particular value.
    #[inline]
    pub fn set_score(&mut self, score: usize) {
        assert!(score <= 0b1111);
        self.0 &= !M_MASK_SCORE;
        self.0 |= (score << M_SHIFT_SCORE) as u32;
    }

    /// Sets a particular bit in the "move score" field to `1`.
    #[inline]
    pub fn set_score_bit(&mut self, b: usize) {
        assert!(b <= 3);
        self.0 |= 1 << b << M_SHIFT_SCORE;
    }

    /// Sets a particular bit in the "move score" field to `0`.
    #[inline]
    pub fn clear_score_bit(&mut self, b: usize) {
        assert!(b <= 3);
        self.0 &= !(1 << b << M_SHIFT_SCORE);
    }

    #[inline]
    pub fn score(&self) -> usize {
        ((self.0 & M_MASK_SCORE) >> M_SHIFT_SCORE) as usize
    }

    #[inline]
    pub fn move_type(&self) -> MoveType {
        ((self.0 & M_MASK_MOVE_TYPE) >> M_SHIFT_MOVE_TYPE) as MoveType
    }

    #[inline]
    pub fn piece(&self) -> PieceType {
        ((self.0 & M_MASK_PIECE) >> M_SHIFT_PIECE) as PieceType
    }

    #[inline]
    pub fn orig_square(&self) -> Square {
        ((self.0 & M_MASK_ORIG_SQUARE) >> M_SHIFT_ORIG_SQUARE) as Square
    }

    #[inline]
    pub fn dest_square(&self) -> Square {
        ((self.0 & M_MASK_DEST_SQUARE) >> M_SHIFT_DEST_SQUARE) as Square
    }

    #[inline]
    pub fn captured_piece(&self) -> PieceType {
        ((!self.0 & M_MASK_CAPTURED_PIECE) >> M_SHIFT_CAPTURED_PIECE) as PieceType
    }

    #[inline]
    pub fn en_passant_file(&self) -> File {
        ((self.0 & M_MASK_ENPASSANT_FILE) >> M_SHIFT_ENPASSANT_FILE) as File
    }

    #[inline(always)]
    pub fn castling_data(&self) -> usize {
        ((self.0 & M_MASK_CASTLING_DATA) >> M_SHIFT_CASTLING_DATA) as usize
    }

    #[inline(always)]
    pub fn aux_data(&self) -> usize {
        ((self.0 & M_MASK_AUX_DATA) >> M_SHIFT_AUX_DATA) as usize
    }

    /// Gets the promoted piece type from the raw value of "aux data".
    ///
    /// When the "move type" is pawn promotion, "aux data" holds the
    /// promoted piece type encoded with a number from 0 to 3. This
    /// function decodes this number to a piece type.
    #[inline]
    pub fn piece_from_aux_data(pp_code: usize) -> PieceType {
        assert!(pp_code <= 3);
        match pp_code {
            0 => QUEEN,
            1 => ROOK,
            2 => BISHOP,
            _ => KNIGHT,
        }
    }
}

/// Represents no en-passant file.
pub const NO_ENPASSANT_FILE: Rank = 8;

// Field shifts
const M_SHIFT_SCORE: u32 = 28;
const M_SHIFT_CAPTURED_PIECE: u32 = 25;
const M_SHIFT_PIECE: u32 = 22;
const M_SHIFT_CASTLING_DATA: u32 = 20;
const M_SHIFT_ENPASSANT_FILE: u32 = 16;
const M_SHIFT_MOVE_TYPE: u32 = 14;
const M_SHIFT_ORIG_SQUARE: u32 = 8;
const M_SHIFT_DEST_SQUARE: u32 = 2;
const M_SHIFT_AUX_DATA: u32 = 0;

// Field masks
const M_MASK_SCORE: u32 = 0b1111 << M_SHIFT_SCORE;
const M_MASK_CAPTURED_PIECE: u32 = 0b111 << M_SHIFT_CAPTURED_PIECE;
const M_MASK_PIECE: u32 = 0b111 << M_SHIFT_PIECE;
const M_MASK_CASTLING_DATA: u32 = 0b11 << M_SHIFT_CASTLING_DATA;
const M_MASK_ENPASSANT_FILE: u32 = 0b1111 << M_SHIFT_ENPASSANT_FILE;
const M_MASK_MOVE_TYPE: u32 = 0b11 << M_SHIFT_MOVE_TYPE;
const M_MASK_ORIG_SQUARE: u32 = 0b111111 << M_SHIFT_ORIG_SQUARE;
const M_MASK_DEST_SQUARE: u32 = 0b111111 << M_SHIFT_DEST_SQUARE;
const M_MASK_AUX_DATA: u32 = 0b11 << M_SHIFT_AUX_DATA;

// TODO: Here does not seem to be the right place for
// "MoveStack". Find it other owner.
pub struct MoveStack {
    stack: [Move; MOVE_STACK_SIZE],
    next_index: usize,
}

impl MoveStack {
    pub fn new() -> MoveStack {
        use std::mem::uninitialized;
        unsafe {
            MoveStack {
                stack: uninitialized(),
                next_index: 0,
            }
        }
    }

    #[inline(always)]
    pub fn push(&mut self, m: Move) {
        self.stack[self.next_index] = m;
        self.next_index += 1;
    }

    #[inline(always)]
    pub fn pop(&mut self) -> Option<Move> {
        if self.next_index == 0 {
            None
        } else {
            self.next_index -= 1;
            Some(self.stack[self.next_index])
        }
    }

    #[inline(always)]
    pub fn remove_all(&mut self) -> usize {
        let count = self.count();
        self.next_index = 0;
        count
    }

    #[inline(always)]
    pub fn count(&self) -> usize {
        self.next_index
    }
}

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

    #[test]
    fn test_move() {
        use basetypes::*;

        let mut cr = CastlingRights::new();
        cr.set_for(WHITE, 0b10);
        cr.set_for(BLACK, 0b11);
        let mut m = Move::new(WHITE,
                              12,
                              MOVE_NORMAL,
                              PAWN,
                              E2,
                              E4,
                              NO_PIECE,
                              NO_ENPASSANT_FILE,
                              cr,
                              0);
        let n1 = Move::new(WHITE,
                           12,
                           MOVE_NORMAL,
                           PAWN,
                           F3,
                           E4,
                           KNIGHT,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n2 = Move::new(WHITE,
                           12,
                           MOVE_NORMAL,
                           KING,
                           F3,
                           E4,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n3 = Move::new(BLACK,
                           0,
                           MOVE_PROMOTION,
                           PAWN,
                           F2,
                           F1,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           1);
        assert!(n1 > m);
        assert!(n2 < m);
        assert_eq!(m.score(), 12);
        assert_eq!(m.piece(), PAWN);
        assert_eq!(m.captured_piece(), NO_PIECE);
        assert_eq!(m.orig_square(), E2);
        assert_eq!(m.dest_square(), E4);
        assert_eq!(m.en_passant_file(), 8);
        assert_eq!(m.aux_data(), 0b10);
        assert_eq!(m.castling_data(), 0b11);
        let m2 = m;
        assert_eq!(m, m2);
        m.set_score(13);
        assert_eq!(m.score(), 13);
        assert!(m > m2);
        m.clear_score_bit(0);
        assert_eq!(m, m2);
        m.set_score_bit(0);
        assert_eq!(m.score(), 13);
        m.set_score(0);
        assert_eq!(m.score(), 0);
        assert_eq!(n3.aux_data(), 1);
    }
}
<|endoftext|>


<commit_before>use super::start_server;
use graph;
use graph::*;
use server::schema::{MorpheusSchema, SchemaError};
use neb::ram::schema::Field;
use neb::ram::types::{TypeId, Value, Map};

#[test]
pub fn schemas() {
    let server = start_server(4001);
    let graph = &server.graph;
    let mut edge_schema = MorpheusSchema::new(
        "test_edge_schema",
        None,
        &vec![Field::new(&"test_field".to_string(), TypeId::U32 as u32, false, false, None)]
    );
    assert_eq!(edge_schema.id, 0);
    assert!(
    graph.new_edge_group(
        &mut edge_schema,
        graph::edge::EdgeAttributes::new
            (
                graph::edge::EdgeType::Directed,
                false
            )).is_err());
    graph.new_edge_group(
        &mut edge_schema,
        graph::edge::EdgeAttributes::new(graph::edge::EdgeType::Directed, true)).unwrap();
    let mut vertex_schema = edge_schema.clone();
    vertex_schema.name = "test_vertex_schema".to_string();
    graph.new_vertex_group(&mut vertex_schema).unwrap();
    assert!(edge_schema.id > 0);
    assert!(vertex_schema.id > 0);
    let mut test_data = Map::new();
    test_data.insert("test_field", Value::U32(1));
    graph.new_vertex(vertex_schema.id, test_data.clone()).unwrap();
    graph.new_vertex(edge_schema.id, test_data.clone()).unwrap();
}<commit_msg>fix a test caused by delayed autotest result<commit_after>use super::start_server;
use graph;
use graph::*;
use server::schema::{MorpheusSchema, SchemaError};
use neb::ram::schema::Field;
use neb::ram::types::{TypeId, Value, Map};

#[test]
pub fn schemas() {
    let server = start_server(4001);
    let graph = &server.graph;
    let mut edge_schema = MorpheusSchema::new(
        "test_edge_schema",
        None,
        &vec![Field::new(&"test_field".to_string(), TypeId::U32 as u32, false, false, None)]
    );
    assert_eq!(edge_schema.id, 0);
    assert!(
    graph.new_edge_group(
        &mut edge_schema,
        graph::edge::EdgeAttributes::new
            (
                graph::edge::EdgeType::Directed,
                false
            )).is_err());
    graph.new_edge_group(
        &mut edge_schema,
        graph::edge::EdgeAttributes::new(graph::edge::EdgeType::Directed, true)).unwrap();
    let mut vertex_schema = edge_schema.clone();
    vertex_schema.name = "test_vertex_schema".to_string();
    graph.new_vertex_group(&mut vertex_schema).unwrap();
    assert!(edge_schema.id > 0);
    assert!(vertex_schema.id > 0);
    let mut test_data = Map::new();
    test_data.insert("test_field", Value::U32(1));
    graph.new_vertex(vertex_schema.id, test_data.clone()).unwrap();
    graph.new_vertex(edge_schema.id, test_data.clone()).is_err();
}

<|endoftext|>


<commit_before><commit_msg>Removing redundant path<commit_after><|endoftext|>


<commit_before>use super::Vector;
use super::Vector2;

pub struct Vector2f {
    pub x: f32,
    pub y: f32,
}

impl Default for Vector2f {
    fn default() -> Vector2f {
        Vector2f {
            x: 0f32,
            y: 0f32,
        }
    }
}

impl Vector<Vector2f, f32> for Vector2f {
    fn add(&mut self, v: &Vector2f) -> &mut Self {
        self.x += v.x;
        self.y += v.y;
        self
    }

    fn add_into(&self, v: &Vector2f, dest: &mut Vector2f) {
        unimplemented!()
    }

    fn angle(&self, v: &Vector2f) -> f32 {
        unimplemented!()
    }

    fn angle_cos(&self, v: &Vector2f) -> f32 {
        unimplemented!()
    }

    fn distance(&self, v: &Vector2f) -> f32 {
        unimplemented!()
    }

    fn distance_squared(&self, v: &Vector2f) -> f32 {
        unimplemented!()
    }

    fn dot(&self, v: &Vector2f) -> f32 {
        unimplemented!()
    }

    fn fma_scalar(&mut self, a: f32, b: &Vector2f) -> &mut Self {
        unimplemented!()
    }

    fn fma_scalar_into(&self, a: f32, b: &Vector2f, dest: &mut Vector2f) {
        unimplemented!()
    }

    fn fma_vector(&mut self, a: &Vector2f, b: &Vector2f) -> &mut Self {
        unimplemented!()
    }

    fn fma_vector_into(&self, a: &Vector2f, b: &Vector2f, dest: &mut Vector2f) {
        unimplemented!()
    }

    fn length(&self) -> f32 {
        unimplemented!()
    }

    fn length_squared(&self) -> f32 {
        unimplemented!()
    }

    fn lerp(&mut self, other: &Vector2f, t: f32) -> &mut Self {
        unimplemented!()
    }

    fn lerp_into(&self, other: &Vector2f, t: f32, dest: &mut Vector2f) {
        unimplemented!()
    }

    fn mul_scalar(&mut self, s: f32) -> &mut Self {
        unimplemented!()
    }

    fn mul_scalar_into(&self, s: f32, dest: &mut Vector2f) {
        unimplemented!()
    }

    fn mul_vector(&mut self, v: &Vector2f) -> &mut Self {
        unimplemented!()
    }

    fn mul_vector_into(&self, v: &Vector2f, dest: &mut Vector2f) {
        unimplemented!()
    }

    fn negate(&mut self) -> &mut Self {
        unimplemented!()
    }

    fn negate_into(&self, dest: &mut Vector2f) {
        unimplemented!()
    }

    fn normalize(&mut self) -> &mut Self {
        unimplemented!()
    }

    fn normalize_into(&self, dest: &mut Vector2f) {
        unimplemented!()
    }

    fn set(&mut self, v: &Vector2f) -> &mut Self {
        unimplemented!()
    }

    fn sub(&mut self, v: &Vector2f) -> &mut Self {
        unimplemented!()
    }

    fn sub_into(&self, v: &Vector2f, dest: &mut Vector2f) {
        unimplemented!()
    }

    fn zero(&mut self) -> &mut Self {
        unimplemented!()
    }
}

impl Vector2<Vector2f, f32> for Vector2f {
    fn new(x: f32, y: f32) -> Self {
        Vector2f {
            x: x,
            y: y,
        }
    }

    fn add_components(&mut self, x: f32, y: f32) -> &mut Self {
        unimplemented!()
    }

    fn add_components_into(&self, x: f32, y: f32, dest: &mut Vector2f) {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    use super::super::Vector;
    use super::super::Vector2;
    use super::Vector2f;

    #[test]
    fn test_new() {
        let a = Vector2f::new(1f32, 2f32);

        assert_eq!(a.x, 1f32);
        assert_eq!(a.y, 2f32);
    }

    #[test]
    fn test_add() {
        let mut a = Vector2f::default();
        let b = Vector2f::new(1f32, 2f32);

        a.add(&b);

        assert_eq!(a.x, 1f32);
        assert_eq!(a.y, 2f32);

        assert_eq!(b.x, 1f32);
        assert_eq!(b.y, 2f32);
    }
}
<commit_msg>add add_into<commit_after>use super::Vector;
use super::Vector2;

pub struct Vector2f {
    pub x: f32,
    pub y: f32,
}

impl Default for Vector2f {
    fn default() -> Vector2f {
        Vector2f {
            x: 0f32,
            y: 0f32,
        }
    }
}

impl Vector<Vector2f, f32> for Vector2f {
    fn add(&mut self, v: &Vector2f) -> &mut Self {
        self.x += v.x;
        self.y += v.y;
        self
    }

    fn add_into(&self, v: &Vector2f, dest: &mut Vector2f) {
        dest.x = self.x + v.x;
        dest.y = self.y + v.y;
    }

    fn angle(&self, v: &Vector2f) -> f32 {
        unimplemented!()
    }

    fn angle_cos(&self, v: &Vector2f) -> f32 {
        unimplemented!()
    }

    fn distance(&self, v: &Vector2f) -> f32 {
        unimplemented!()
    }

    fn distance_squared(&self, v: &Vector2f) -> f32 {
        unimplemented!()
    }

    fn dot(&self, v: &Vector2f) -> f32 {
        unimplemented!()
    }

    fn fma_scalar(&mut self, a: f32, b: &Vector2f) -> &mut Self {
        unimplemented!()
    }

    fn fma_scalar_into(&self, a: f32, b: &Vector2f, dest: &mut Vector2f) {
        unimplemented!()
    }

    fn fma_vector(&mut self, a: &Vector2f, b: &Vector2f) -> &mut Self {
        unimplemented!()
    }

    fn fma_vector_into(&self, a: &Vector2f, b: &Vector2f, dest: &mut Vector2f) {
        unimplemented!()
    }

    fn length(&self) -> f32 {
        unimplemented!()
    }

    fn length_squared(&self) -> f32 {
        unimplemented!()
    }

    fn lerp(&mut self, other: &Vector2f, t: f32) -> &mut Self {
        unimplemented!()
    }

    fn lerp_into(&self, other: &Vector2f, t: f32, dest: &mut Vector2f) {
        unimplemented!()
    }

    fn mul_scalar(&mut self, s: f32) -> &mut Self {
        unimplemented!()
    }

    fn mul_scalar_into(&self, s: f32, dest: &mut Vector2f) {
        unimplemented!()
    }

    fn mul_vector(&mut self, v: &Vector2f) -> &mut Self {
        unimplemented!()
    }

    fn mul_vector_into(&self, v: &Vector2f, dest: &mut Vector2f) {
        unimplemented!()
    }

    fn negate(&mut self) -> &mut Self {
        unimplemented!()
    }

    fn negate_into(&self, dest: &mut Vector2f) {
        unimplemented!()
    }

    fn normalize(&mut self) -> &mut Self {
        unimplemented!()
    }

    fn normalize_into(&self, dest: &mut Vector2f) {
        unimplemented!()
    }

    fn set(&mut self, v: &Vector2f) -> &mut Self {
        unimplemented!()
    }

    fn sub(&mut self, v: &Vector2f) -> &mut Self {
        unimplemented!()
    }

    fn sub_into(&self, v: &Vector2f, dest: &mut Vector2f) {
        unimplemented!()
    }

    fn zero(&mut self) -> &mut Self {
        unimplemented!()
    }
}

impl Vector2<Vector2f, f32> for Vector2f {
    fn new(x: f32, y: f32) -> Self {
        Vector2f {
            x: x,
            y: y,
        }
    }

    fn add_components(&mut self, x: f32, y: f32) -> &mut Self {
        unimplemented!()
    }

    fn add_components_into(&self, x: f32, y: f32, dest: &mut Vector2f) {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    use super::super::Vector;
    use super::super::Vector2;
    use super::Vector2f;

    #[test]
    fn test_new() {
        let a = Vector2f::new(1f32, 2f32);

        assert_eq!(a.x, 1f32);
        assert_eq!(a.y, 2f32);
    }

    #[test]
    fn test_add() {
        let mut a = Vector2f::default();
        let b = Vector2f::new(1f32, 2f32);

        a.add(&b);

        assert_eq!(a.x, 1f32);
        assert_eq!(a.y, 2f32);

        assert_eq!(b.x, 1f32);
        assert_eq!(b.y, 2f32);
    }

    #[test]
    fn test_add_into() {
        let a = Vector2f::new(1f32, 1f32);
        let b = Vector2f::new(1f32, 2f32);
        let mut c = Vector2f::default();

        a.add_into(&b, &mut c);

        assert_eq!(a.x, 1f32);
        assert_eq!(a.y, 1f32);

        assert_eq!(b.x, 1f32);
        assert_eq!(b.y, 2f32);

        assert_eq!(c.x, 2f32);
        assert_eq!(c.y, 3f32);
    }
}
<|endoftext|>


<commit_before>use std::error::Error;

use handlebars::Handlebars;

#[macro_use]
extern crate serde_json;

#[cfg(feature = "script_helper")]
fn main() -> Result<(), Box<dyn Error>> {
    let mut handlebars = Handlebars::new();

    handlebars.register_template_file("tpl", "./examples/script/template.hbs")?;
    handlebars.register_script_helper_file("score", "./examples/script/goals.rhai")?;

    let data = json! {[
        [{
            "name": "Dortmund",
            "goals": ["Haaland", "Guerreiro", "Hazard", "Guerreiro"]
        }, {
            "name": "Schalke",
            "goals": []
        }],
        [{
            "name": "RB Leipzig",
            "goals": ["Poulsen"]
        }, {
            "name": "SC Feriburg",
            "goals": ["Gulde"]
        }]
    ]};
    println!("{}", handlebars.render("tpl", &data)?);
    Ok(())
}

#[cfg(not(feature = "script_helper"))]
fn main() {
    println!("Please enable feature flag script_helper for this example");
}
<commit_msg>(fix) remove warnings on example<commit_after>#[cfg(feature = "script_helper")]
fn main() -> Result<(), Box<dyn Error>> {
    use handlebars::Handlebars;
    use std::error::Error;
    #[macro_use]
    extern crate serde_json;

    let mut handlebars = Handlebars::new();

    handlebars.register_template_file("tpl", "./examples/script/template.hbs")?;
    handlebars.register_script_helper_file("score", "./examples/script/goals.rhai")?;

    let data = json! {[
        [{
            "name": "Dortmund",
            "goals": ["Haaland", "Guerreiro", "Hazard", "Guerreiro"]
        }, {
            "name": "Schalke",
            "goals": []
        }],
        [{
            "name": "RB Leipzig",
            "goals": ["Poulsen"]
        }, {
            "name": "SC Feriburg",
            "goals": ["Gulde"]
        }]
    ]};
    println!("{}", handlebars.render("tpl", &data)?);
    Ok(())
}

#[cfg(not(feature = "script_helper"))]
fn main() {
    println!("Please enable feature flag script_helper for this example");
}
<|endoftext|>


<commit_before>extern crate cursive;

use cursive::prelude::*;

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

    // Let's add a simple slider in a dialog.
    // Moving the slider will update the dialog's title.
    // And pressing "Enter" will show a new dialog.
    siv.add_layer(Dialog::new(SliderView::horizontal(15)
            .value(7)
            .on_change(|s, v| {
                let title = format!("[ {} ]", v);
                s.find_id::<Dialog>("dialog").unwrap().set_title(title);
            })
            .on_enter(|s, v| {
                s.pop_layer();
                s.add_layer(Dialog::text(format!("Lucky number {}!", v))
                    .button("Ok", Cursive::quit));
            }))
        .with_id("dialog"));

    siv.run();
}
<commit_msg>Slider example: initialize title<commit_after>extern crate cursive;

use cursive::prelude::*;

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

    // Let's add a simple slider in a dialog.
    // Moving the slider will update the dialog's title.
    // And pressing "Enter" will show a new dialog.
    siv.add_layer(Dialog::new(SliderView::horizontal(15)
            .value(7)
            .on_change(|s, v| {
                let title = format!("[ {} ]", v);
                s.find_id::<Dialog>("dialog").unwrap().set_title(title);
            })
            .on_enter(|s, v| {
                s.pop_layer();
                s.add_layer(Dialog::text(format!("Lucky number {}!", v))
                    .button("Ok", Cursive::quit));
            }))
        .title("[ 7 ]")
        .with_id("dialog"));

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


<commit_before>//use std::collections::LinkedList;
use token::Token;
use std::mem::replace;

// test case: x=0;y=g=1;alert(eval("while(x)break\n/y/g.exec('y')"))
//       see: https://groups.google.com/d/msg/mozilla.dev.tech.js-engine.internals/2JLH5jRcr7E/Mxc7ZKc5r6sJ

pub struct Buffer {
    //tokens: LinkedList<Token>
    token: Option<Token>
}

impl Buffer {
    pub fn new() -> Buffer {
        Buffer {
            token: None
            //tokens: LinkedList::new()
        }
    }

    pub fn is_empty(&mut self) -> bool {
        //self.tokens.len() == 0
        self.token.is_none()
    }

    pub fn push_token(&mut self, token: Token) {
        //assert!(self.tokens.len() == 0);
        //self.tokens.push_back(token);
        debug_assert!(self.token.is_none());
        self.token = Some(token)
    }

    pub fn read_token(&mut self) -> Token {
        //assert!(self.tokens.len() > 0);
        //self.tokens.pop_front().unwrap()
        debug_assert!(self.token.is_some());
        replace(&mut self.token, None).unwrap()
    }

    pub fn peek_token(&mut self) -> &Token {
        //assert!(self.tokens.len() > 0);
        //self.tokens.front().unwrap()
        debug_assert!(self.token.is_some());
        self.token.as_ref().unwrap()
    }

    pub fn unread_token(&mut self, token: Token) {
        //assert!(self.tokens.len() < 3);
        //self.tokens.push_front(token);
        debug_assert!(self.token.is_none());
        self.token = Some(token);
    }
}
<commit_msg>Use immutable borrows for lookahead.<commit_after>//use std::collections::LinkedList;
use token::Token;

// test case: x=0;y=g=1;alert(eval("while(x)break\n/y/g.exec('y')"))
//       see: https://groups.google.com/d/msg/mozilla.dev.tech.js-engine.internals/2JLH5jRcr7E/Mxc7ZKc5r6sJ

pub struct Buffer {
    //tokens: LinkedList<Token>
    token: Option<Token>
}

impl Buffer {
    pub fn new() -> Buffer {
        Buffer {
            token: None
            //tokens: LinkedList::new()
        }
    }

    pub fn is_empty(&self) -> bool {
        //self.tokens.len() == 0
        self.token.is_none()
    }

    pub fn push_token(&mut self, token: Token) {
        //assert!(self.tokens.len() == 0);
        //self.tokens.push_back(token);
        debug_assert!(self.token.is_none());
        self.token = Some(token)
    }

    pub fn read_token(&mut self) -> Token {
        //assert!(self.tokens.len() > 0);
        //self.tokens.pop_front().unwrap()
        debug_assert!(self.token.is_some());
        self.token.take().unwrap()
    }

    pub fn peek_token(&self) -> &Token {
        //assert!(self.tokens.len() > 0);
        //self.tokens.front().unwrap()
        debug_assert!(self.token.is_some());
        self.token.as_ref().unwrap()
    }

    pub fn unread_token(&mut self, token: Token) {
        //assert!(self.tokens.len() < 3);
        //self.tokens.push_front(token);
        debug_assert!(self.token.is_none());
        self.token = Some(token);
    }
}
<|endoftext|>


<commit_before>use rusqlite::Connection;

#[derive(Debug)]
pub struct FsFile {
    pub id: i32,
    pub fk_fs_dir: i32,
    pub name: String,
}

pub fn table_create_fs_file(conn: &Connection) -> &Connection {
    conn.execute(
        "CREATE TABLE FS_FILE (
                  id                INTEGER PRIMARY KEY ASC,
                  fk_fs_dir         INTEGER NOT NULL,
                  name              TEXT NOT NULL UNIQUE
                  )",
        &[],
    ).unwrap();
    return conn;
}

pub fn insert_fs_file(
    conn: &Connection,
    fk_fs_dir: i32,
    name: String,
) -> Result<i32, &'static str> {
    let me = FsFile {
        id: 0,
        name: name,
        fk_fs_dir: fk_fs_dir,
    };
    let variable_pair_instance = conn.execute(
        "INSERT INTO FS_FILE (name, fk_fs_dir)
                  VALUES (?1, ?2)",
        &[&me.name, &me.fk_fs_dir],
    );
    if variable_pair_instance.is_err() {
        return Err("Insert failed");
    }
    variable_pair_instance.unwrap();
    return Ok(0);
}

pub fn list_fs_file(conn: &Connection) -> Vec<FsFile> {
    let mut stmt = conn
        .prepare("SELECT id, fk_fs_dir,name  FROM FS_FILE")
        .unwrap();
    let fs_file_iter =
        stmt.query_map(&[], |row| FsFile {
            id: row.get(0),
            fk_fs_dir: row.get(1),
            name: row.get(2),
        }).unwrap();
    let mut items = Vec::<FsFile>::new();
    for person in fs_file_iter {
        items.push(person.unwrap());
    }
    return items;
}

pub fn pk_fs_file_by_name(conn: &Connection, name: String, pk: &mut i32) {
    let mut stmt = conn
        .prepare("SELECT id, fk_fs_dir,name  FROM FS_FILE WHERE name =?1")
        .unwrap();
    let fs_file_iter =
        stmt.query_map(&[&name], |row| FsFile {
            id: row.get(0),
            fk_fs_dir: row.get(1),
            name: row.get(2),
        }).unwrap();
    for person in fs_file_iter {
        let bill = person.unwrap();
        *pk = bill.id;
        return;
    }
}

pub fn list_fs_file_type(conn: &Connection, fk_fs_type: &i32) -> Vec<FsFile> {
    let mut stmt =
        conn.prepare(
            "SELECT FS_FILE.id, FS_FILE.name, FS_FILE.fk_fs_dir FROM FS_FILE
        INNER JOIN FS_DIR
        on FS_FILE.fk_fs_dir = FS_DIR.id
        INNER JOIN FS_DIR_TYPE
        on FS_DIR.fk_type = FS_DIR_TYPE.id
        WHERE FS_DIR_TYPE.id =?1
        ",
        ).unwrap();
    let fs_file_iter =
        stmt.query_map(&[fk_fs_type], |row| FsFile {
            id: row.get(0),
            fk_fs_dir: row.get(2),
            name: row.get(1),
        }).unwrap();
    let mut items = Vec::<FsFile>::new();
    for person in fs_file_iter {
        items.push(person.unwrap());
    }
    return items;
}

#[cfg(test)]
mod tests {
    #[test]
    fn insert_fs_file() {
        use db;
        use db_fs_dir;
        use db::fs_dir_type;
        let conn = db::connect();
        db::create_tables(&conn);
        let str_job_files_list = String::from("job_files");
        let _ = db::fs_dir_type::insert_fs_dir_type(&conn, &str_job_files_list);
        let vec_dir_type = db::fs_dir_type::list_fs_dir_type(&conn);
        let mut pk_dir_type = 0;
        let mut counter = 0;
        for dir_type in vec_dir_type {
            counter += 1;
            pk_dir_type = dir_type.id;
        }
        assert!(counter == 1);
        assert!(pk_dir_type == 1);
        let str_directory_path = String::from("directory_path");
        let insert_fs_dir_result =
            db_fs_dir::insert_fs_dir(&conn, &pk_dir_type, &str_directory_path);
        let fs_dir_result = insert_fs_dir_result.unwrap();
        assert!(fs_dir_result == 0);
        let list_fs_dir_result =
            db_fs_dir::list_fs_dir_by_all(&conn, &pk_dir_type, &str_directory_path);
        let vec_dir = list_fs_dir_result.unwrap();
        counter = 0;
        let mut pk_dir = 0;
        for dir in vec_dir {
            counter += 1;
            pk_dir = dir.id;
        }
        assert!(counter == 1);
        assert!(pk_dir == 1);
    }
}
<commit_msg>src/rust/src/db_fs_file.rs fixup<commit_after>use rusqlite::Connection;

#[derive(Debug)]
pub struct FsFile {
    pub id: i32,
    pub fk_fs_dir: i32,
    pub name: String,
}

pub fn table_create_fs_file(conn: &Connection) -> &Connection {
    conn.execute(
        "CREATE TABLE FS_FILE (
                  id                INTEGER PRIMARY KEY ASC,
                  fk_fs_dir         INTEGER NOT NULL,
                  name              TEXT NOT NULL UNIQUE
                  )",
        &[],
    ).unwrap();
    return conn;
}

pub fn insert_fs_file(
    conn: &Connection,
    fk_fs_dir: i32,
    name: String,
) -> Result<i32, &'static str> {
    let me = FsFile {
        id: 0,
        name: name,
        fk_fs_dir: fk_fs_dir,
    };
    let variable_pair_instance = conn.execute(
        "INSERT INTO FS_FILE (name, fk_fs_dir)
                  VALUES (?1, ?2)",
        &[&me.name, &me.fk_fs_dir],
    );
    if variable_pair_instance.is_err() {
        return Err("Insert failed");
    }
    variable_pair_instance.unwrap();
    return Ok(0);
}

pub fn list_fs_file(conn: &Connection) -> Vec<FsFile> {
    let mut stmt = conn
        .prepare("SELECT id, fk_fs_dir,name  FROM FS_FILE")
        .unwrap();
    let fs_file_iter =
        stmt.query_map(&[], |row| FsFile {
            id: row.get(0),
            fk_fs_dir: row.get(1),
            name: row.get(2),
        }).unwrap();
    let mut items = Vec::<FsFile>::new();
    for person in fs_file_iter {
        items.push(person.unwrap());
    }
    return items;
}

pub fn pk_fs_file_by_name(conn: &Connection, name: String, pk: &mut i32) {
    let mut stmt = conn
        .prepare("SELECT id, fk_fs_dir,name  FROM FS_FILE WHERE name =?1")
        .unwrap();
    let fs_file_iter =
        stmt.query_map(&[&name], |row| FsFile {
            id: row.get(0),
            fk_fs_dir: row.get(1),
            name: row.get(2),
        }).unwrap();
    for person in fs_file_iter {
        let bill = person.unwrap();
        *pk = bill.id;
        return;
    }
}

pub fn list_fs_file_type(conn: &Connection, fk_fs_type: &i32) -> Vec<FsFile> {
    let mut stmt =
        conn.prepare(
            "SELECT FS_FILE.id, FS_FILE.name, FS_FILE.fk_fs_dir FROM FS_FILE
        INNER JOIN FS_DIR
        on FS_FILE.fk_fs_dir = FS_DIR.id
        INNER JOIN FS_DIR_TYPE
        on FS_DIR.fk_type = FS_DIR_TYPE.id
        WHERE FS_DIR_TYPE.id =?1
        ",
        ).unwrap();
    let fs_file_iter =
        stmt.query_map(&[fk_fs_type], |row| FsFile {
            id: row.get(0),
            fk_fs_dir: row.get(2),
            name: row.get(1),
        }).unwrap();
    let mut items = Vec::<FsFile>::new();
    for person in fs_file_iter {
        items.push(person.unwrap());
    }
    return items;
}

#[cfg(test)]
mod tests {
    #[test]
    fn insert_fs_file() {
        use db;
        use db::fs_dir_type;
        use db_fs_dir;
        let conn = db::connect();
        db::create_tables(&conn);
        let str_job_files_list = String::from("job_files");
        let _ = db::fs_dir_type::insert_fs_dir_type(&conn, &str_job_files_list);
        let vec_dir_type = db::fs_dir_type::list_fs_dir_type(&conn);
        let mut pk_dir_type = 0;
        let mut counter = 0;
        for dir_type in vec_dir_type {
            counter += 1;
            pk_dir_type = dir_type.id;
        }
        assert!(counter == 1);
        assert!(pk_dir_type == 1);
        let str_directory_path = String::from("directory_path");
        let insert_fs_dir_result =
            db_fs_dir::insert_fs_dir(&conn, &pk_dir_type, &str_directory_path);
        let fs_dir_result = insert_fs_dir_result.unwrap();
        assert!(fs_dir_result == 0);
        let list_fs_dir_result =
            db_fs_dir::list_fs_dir_by_all(&conn, &pk_dir_type, &str_directory_path);
        let vec_dir = list_fs_dir_result.unwrap();
        counter = 0;
        let mut pk_dir = 0;
        for dir in vec_dir {
            counter += 1;
            pk_dir = dir.id;
        }
        assert!(counter == 1);
        assert!(pk_dir == 1);
    }
}
<|endoftext|>


<commit_before>use kiss3d::scene::SceneNode;
use na::{Isometry3, Point3};
use nphysics3d::object::ColliderHandle;
use nphysics3d::world::World;
use objects::ball::Ball;
use objects::box_node::Box;
use objects::cone::Cone;
use objects::convex::Convex;
use objects::cylinder::Cylinder;
use objects::mesh::Mesh;
use objects::plane::Plane;

pub enum Node {
    Plane(Plane),
    Ball(Ball),
    Box(Box),
    Cylinder(Cylinder),
    Cone(Cone),
    Mesh(Mesh),
    Convex(Convex),
}

impl Node {
    pub fn select(&mut self) {
        match *self {
            Node::Plane(ref mut n) => n.select(),
            Node::Ball(ref mut n) => n.select(),
            Node::Box(ref mut n) => n.select(),
            Node::Cylinder(ref mut n) => n.select(),
            Node::Cone(ref mut n) => n.select(),
            Node::Mesh(ref mut n) => n.select(),
            Node::Convex(ref mut n) => n.select(),
        }
    }

    pub fn unselect(&mut self) {
        match *self {
            Node::Plane(ref mut n) => n.unselect(),
            Node::Ball(ref mut n) => n.unselect(),
            Node::Box(ref mut n) => n.unselect(),
            Node::Cylinder(ref mut n) => n.unselect(),
            Node::Cone(ref mut n) => n.unselect(),
            Node::Mesh(ref mut n) => n.unselect(),
            Node::Convex(ref mut n) => n.unselect(),
        }
    }

    pub fn update(&mut self, world: &World<f32>) {
        match *self {
            Node::Plane(ref mut n) => n.update(world),
            Node::Ball(ref mut n) => n.update(world),
            Node::Box(ref mut n) => n.update(world),
            Node::Cylinder(ref mut n) => n.update(world),
            Node::Cone(ref mut n) => n.update(world),
            Node::Mesh(ref mut n) => n.update(world),
            Node::Convex(ref mut n) => n.update(world),
        }
    }

    pub fn scene_node(&self) -> &SceneNode {
        match *self {
            Node::Plane(ref n) => n.scene_node(),
            Node::Ball(ref n) => n.scene_node(),
            Node::Box(ref n) => n.scene_node(),
            Node::Cylinder(ref n) => n.scene_node(),
            Node::Cone(ref n) => n.scene_node(),
            Node::Mesh(ref n) => n.scene_node(),
            Node::Convex(ref n) => n.scene_node(),
        }
    }

    pub fn scene_node_mut(&mut self) -> &mut SceneNode {
        match *self {
            Node::Plane(ref mut n) => n.scene_node_mut(),
            Node::Ball(ref mut n) => n.scene_node_mut(),
            Node::Box(ref mut n) => n.scene_node_mut(),
            Node::Cylinder(ref mut n) => n.scene_node_mut(),
            Node::Cone(ref mut n) => n.scene_node_mut(),
            Node::Mesh(ref mut n) => n.scene_node_mut(),
            Node::Convex(ref mut n) => n.scene_node_mut(),
        }
    }

    pub fn collider(&self) -> ColliderHandle {
        match *self {
            Node::Plane(ref n) => n.object(),
            Node::Ball(ref n) => n.object(),
            Node::Box(ref n) => n.object(),
            Node::Cylinder(ref n) => n.object(),
            Node::Cone(ref n) => n.object(),
            Node::Mesh(ref n) => n.object(),
            Node::Convex(ref n) => n.object(),
        }
    }

    pub fn set_color(&mut self, color: Point3<f32>) {
        match *self {
            Node::Plane(ref mut n) => n.set_color(color),
            Node::Ball(ref mut n) => n.set_color(color),
            Node::Box(ref mut n) => n.set_color(color),
            Node::Cylinder(ref mut n) => n.set_color(color),
            Node::Cone(ref mut n) => n.set_color(color),
            Node::Mesh(ref mut n) => n.set_color(color),
            Node::Convex(ref mut n) => n.set_color(color),
        }
    }
}

pub fn update_scene_node(
    node: &mut SceneNode,
    world: &World<f32>,
    coll: ColliderHandle,
    color: &Point3<f32>,
    delta: &Isometry3<f32>,
) {
    let co = world.collider(coll).unwrap();
    // let active = world.body(co.data().body()).is_active();

    if true {
        // active {
        node.set_local_transformation(co.position() * delta);
        node.set_color(color.x, color.y, color.z);
    } else {
        node.set_color(color.x * 0.25, color.y * 0.25, color.z * 0.25);
    }
}
<commit_msg>Fix crash after removing a collider<commit_after>use kiss3d::scene::SceneNode;
use na::{Isometry3, Point3};
use nphysics3d::object::ColliderHandle;
use nphysics3d::world::World;
use objects::ball::Ball;
use objects::box_node::Box;
use objects::cone::Cone;
use objects::convex::Convex;
use objects::cylinder::Cylinder;
use objects::mesh::Mesh;
use objects::plane::Plane;

pub enum Node {
    Plane(Plane),
    Ball(Ball),
    Box(Box),
    Cylinder(Cylinder),
    Cone(Cone),
    Mesh(Mesh),
    Convex(Convex),
}

impl Node {
    pub fn select(&mut self) {
        match *self {
            Node::Plane(ref mut n) => n.select(),
            Node::Ball(ref mut n) => n.select(),
            Node::Box(ref mut n) => n.select(),
            Node::Cylinder(ref mut n) => n.select(),
            Node::Cone(ref mut n) => n.select(),
            Node::Mesh(ref mut n) => n.select(),
            Node::Convex(ref mut n) => n.select(),
        }
    }

    pub fn unselect(&mut self) {
        match *self {
            Node::Plane(ref mut n) => n.unselect(),
            Node::Ball(ref mut n) => n.unselect(),
            Node::Box(ref mut n) => n.unselect(),
            Node::Cylinder(ref mut n) => n.unselect(),
            Node::Cone(ref mut n) => n.unselect(),
            Node::Mesh(ref mut n) => n.unselect(),
            Node::Convex(ref mut n) => n.unselect(),
        }
    }

    pub fn update(&mut self, world: &World<f32>) {
        match *self {
            Node::Plane(ref mut n) => n.update(world),
            Node::Ball(ref mut n) => n.update(world),
            Node::Box(ref mut n) => n.update(world),
            Node::Cylinder(ref mut n) => n.update(world),
            Node::Cone(ref mut n) => n.update(world),
            Node::Mesh(ref mut n) => n.update(world),
            Node::Convex(ref mut n) => n.update(world),
        }
    }

    pub fn scene_node(&self) -> &SceneNode {
        match *self {
            Node::Plane(ref n) => n.scene_node(),
            Node::Ball(ref n) => n.scene_node(),
            Node::Box(ref n) => n.scene_node(),
            Node::Cylinder(ref n) => n.scene_node(),
            Node::Cone(ref n) => n.scene_node(),
            Node::Mesh(ref n) => n.scene_node(),
            Node::Convex(ref n) => n.scene_node(),
        }
    }

    pub fn scene_node_mut(&mut self) -> &mut SceneNode {
        match *self {
            Node::Plane(ref mut n) => n.scene_node_mut(),
            Node::Ball(ref mut n) => n.scene_node_mut(),
            Node::Box(ref mut n) => n.scene_node_mut(),
            Node::Cylinder(ref mut n) => n.scene_node_mut(),
            Node::Cone(ref mut n) => n.scene_node_mut(),
            Node::Mesh(ref mut n) => n.scene_node_mut(),
            Node::Convex(ref mut n) => n.scene_node_mut(),
        }
    }

    pub fn collider(&self) -> ColliderHandle {
        match *self {
            Node::Plane(ref n) => n.object(),
            Node::Ball(ref n) => n.object(),
            Node::Box(ref n) => n.object(),
            Node::Cylinder(ref n) => n.object(),
            Node::Cone(ref n) => n.object(),
            Node::Mesh(ref n) => n.object(),
            Node::Convex(ref n) => n.object(),
        }
    }

    pub fn set_color(&mut self, color: Point3<f32>) {
        match *self {
            Node::Plane(ref mut n) => n.set_color(color),
            Node::Ball(ref mut n) => n.set_color(color),
            Node::Box(ref mut n) => n.set_color(color),
            Node::Cylinder(ref mut n) => n.set_color(color),
            Node::Cone(ref mut n) => n.set_color(color),
            Node::Mesh(ref mut n) => n.set_color(color),
            Node::Convex(ref mut n) => n.set_color(color),
        }
    }
}

pub fn update_scene_node(
    node: &mut SceneNode,
    world: &World<f32>,
    coll: ColliderHandle,
    color: &Point3<f32>,
    delta: &Isometry3<f32>,
) {
    if let Some(co) = world.collider(coll) {
        node.set_local_transformation(co.position() * delta);
        node.set_color(color.x, color.y, color.z);
    } else {
        node.set_color(color.x * 0.25, color.y * 0.25, color.z * 0.25);
    }
}
<|endoftext|>


<commit_before>use cookie_factory::*;
use elements::{Info, Seek, SeekHead, SegmentElement};
use super::ebml::{vint_size, gen_vint, gen_vid, gen_uint};
use serializer::ebml::{gen_u64,gen_f64_ref};

pub fn seek_size(s: &Seek) -> u8 {
    // byte size of id (vid+size)+ data and position vid+size+int
    // FIXME: arbitrarily bad value
    vint_size(vint_size((s.id.len() + 10) as u64) as u64)
}

pub fn gen_segment<'a>(input: (&'a mut [u8], usize),
                       s: &SegmentElement)
                       -> Result<(&'a mut [u8], usize), GenError> {
    unimplemented!();
    /*do_gen!(input,
    gen_call!(gen_vid, 0x18538067) >>
    gen_call!(gen_vint, 4)
  )*/
}

pub fn gen_seek<'a>(input: (&'a mut [u8], usize),
                    s: &Seek)
                    -> Result<(&'a mut [u8], usize), GenError> {
    let capacity = 8 + 2 + vint_size(s.id.len() as u64) as u64 + s.id.len() as u64;

    gen_ebml_master!(input,
    0x4DBB, vint_size(capacity),
    gen_ebml_binary!(0x53AB, s.id) >>
    gen_ebml_uint!(0x53AC, s.position, vint_size(s.position))
  )
}

pub fn gen_seek_head<'a>(input: (&'a mut [u8], usize),
                         s: &SeekHead)
                         -> Result<(&'a mut [u8], usize), GenError> {
    let capacity = s.positions.iter().fold(0u64, |acc, seek| {
        acc + 4 + 8 + 2 + vint_size(seek.id.len() as u64) as u64 + seek.id.len() as u64
    });
    println!("gen_seek_head: calculated capacity: {} -> {} bytes", capacity, vint_size(capacity));

    let byte_capacity = vint_size(capacity as u64);
    gen_ebml_master!(input,
    0x114D9B74, byte_capacity,
    gen_many_ref!(&s.positions, gen_seek)
  )
}

//trace_macros!(true);
pub fn gen_info<'a>(input: (&'a mut [u8], usize),
                         i: &Info)
                         -> Result<(&'a mut [u8], usize), GenError> {
    //FIXME: probably not large enough
    let capacity = 2 + i.segment_uid.as_ref().map(|s| s.len()).unwrap_or(0)
      + 2 + i.segment_filename.as_ref().map(|s| s.len()).unwrap_or(0)
      + 3 + i.prev_uid.as_ref().map(|s| s.len()).unwrap_or(0)
      + 3 + i.prev_filename.as_ref().map(|s| s.len()).unwrap_or(0)
      + 3 + i.next_uid.as_ref().map(|s| s.len()).unwrap_or(0)
      + 3 + i.next_filename.as_ref().map(|s| s.len()).unwrap_or(0)
      + 2 + i.segment_family.as_ref().map(|s| s.len()).unwrap_or(0)
      //FIXME;
      // chapter translate
      + 8
      + 8
      + 2 + i.date_utc.as_ref().map(|s| s.len()).unwrap_or(0)
      + 2 + i.title.as_ref().map(|s| s.len()).unwrap_or(0)
      + 2 + i.muxing_app.len()
      + 2 + i.writing_app.len();

    let byte_capacity = vint_size(capacity as u64);
    gen_ebml_master!(input,
      0x1549A966, byte_capacity,
      do_gen!(
           gen_opt!( i.segment_uid, gen_ebml_binary!(0x73A4) )
        >> gen_opt!( i.segment_filename, gen_ebml_str!(0x7384) )
        >> gen_opt!( i.prev_uid, gen_ebml_binary!(0x3CB923) )
        >> gen_opt!( i.prev_filename, gen_ebml_str!(0x3C83AB) )
        >> gen_opt!( i.next_uid, gen_ebml_binary!(0x3EB923) )
        >> gen_opt!( i.next_filename, gen_ebml_str!(0x3E83BB) )
        >> gen_opt!( i.segment_family, gen_ebml_binary!(0x4444) )
        //>> gen_opt!( i.chapter_translate, gen_chapter_translate )
        >> gen_call!(gen_u64, 0x2AD7B1, i.timecode_scale)
        >> gen_opt!( i.duration, gen_call!(gen_f64_ref, 0x4489) )
        >> gen_opt!( i.date_utc, gen_ebml_binary!(0x4461) )
        >> gen_opt!( i.title, gen_ebml_str!(0x7BA9) )
        >> gen_ebml_str!(0x4D80, i.muxing_app)
        >> gen_ebml_str!(0x5741, i.writing_app)
      )
    )
}
trace_macros!(false);

#[cfg(test)]
mod tests {
    use super::*;
    use nom::*;
    use std::iter::repeat;

    fn test_seek_head_serializer(mut seeks: Vec<(u64, Vec<u8>)>) -> bool {
        println!("testing for {:?}", seeks);

        let mut should_fail = false;
        if seeks.len() == 0 {
            should_fail = true;
        }

        for &(_, ref id) in seeks.iter() {
            println!("id: {}", id.to_hex(16));
            if id.len() == 0 {
                println!("id is empty, returning");
                return true;
                //should_fail = true;
            }
        }

        if should_fail {
            println!("the parser should fail");
        }

        let capacity = seeks.iter().fold(0, |acc, &(_, ref v)| acc + 8 + v.len() + 100);
        println!("defining capacity as {}", capacity);

        let mut data = Vec::with_capacity(capacity);
        data.extend(repeat(0).take(capacity));

        let seek_head = SeekHead {
            positions: seeks.iter()
                .cloned()
                .map(|(position, id)| {
                    Seek {
                        id: id,
                        position: position,
                    }
                })
                .collect(),
        };

        let ser_res = {
            let gen_res = gen_seek_head((&mut data[..], 0), &seek_head);
            println!("gen_res: {:?}", gen_res);
            if let Err(e) = gen_res {
                println!("gen_res is error: {:?}", e);
                println!("should fail: {:?}", should_fail);
                return should_fail;
                /*if should_fail {
          println!("should fail");
          return true;
        }*/
            }
        };

        println!("ser_res: {:?}", ser_res);

        let parse_res = ::elements::segment_element(&data[..]);
        println!("parse_res: {:?}", parse_res);
        match parse_res {
            Ok((rest, SegmentElement::SeekHead(o))) => {
                if should_fail {
                    println!("parser should have failed on input for {:?}", seek_head);
                    println!("{}", (&data[..]).to_hex(16));
                    return false;
                }

                assert_eq!(seek_head, o);
                return true;
            }
            e => {
                if should_fail {
                    return true;
                }

                panic!(format!("parse error: {:?} for input: {:?}", e, seeks))
            }
        }

        false
    }

    quickcheck! {
    fn test_seek_head(seeks: Vec<(u64, Vec<u8>)>) -> bool {
      test_seek_head_serializer(seeks)
    }
  }
}
<commit_msg>generate a partial cluster<commit_after>use cookie_factory::*;
use elements::{Info, Seek, SeekHead, SegmentElement, Cluster};
use super::ebml::{vint_size, gen_vint, gen_vid, gen_uint};
use serializer::ebml::{gen_u64,gen_f64_ref};

pub fn seek_size(s: &Seek) -> u8 {
    // byte size of id (vid+size)+ data and position vid+size+int
    // FIXME: arbitrarily bad value
    vint_size(vint_size((s.id.len() + 10) as u64) as u64)
}

pub fn gen_segment<'a>(input: (&'a mut [u8], usize),
                       s: &SegmentElement)
                       -> Result<(&'a mut [u8], usize), GenError> {
    unimplemented!();
    /*do_gen!(input,
    gen_call!(gen_vid, 0x18538067) >>
    gen_call!(gen_vint, 4)
  )*/
}

pub fn gen_seek<'a>(input: (&'a mut [u8], usize),
                    s: &Seek)
                    -> Result<(&'a mut [u8], usize), GenError> {
    let capacity = 8 + 2 + vint_size(s.id.len() as u64) as u64 + s.id.len() as u64;

    gen_ebml_master!(input,
    0x4DBB, vint_size(capacity),
    gen_ebml_binary!(0x53AB, s.id) >>
    gen_ebml_uint!(0x53AC, s.position, vint_size(s.position))
  )
}

pub fn gen_seek_head<'a>(input: (&'a mut [u8], usize),
                         s: &SeekHead)
                         -> Result<(&'a mut [u8], usize), GenError> {
    let capacity = s.positions.iter().fold(0u64, |acc, seek| {
        acc + 4 + 8 + 2 + vint_size(seek.id.len() as u64) as u64 + seek.id.len() as u64
    });
    println!("gen_seek_head: calculated capacity: {} -> {} bytes", capacity, vint_size(capacity));

    let byte_capacity = vint_size(capacity as u64);
    gen_ebml_master!(input,
    0x114D9B74, byte_capacity,
    gen_many_ref!(&s.positions, gen_seek)
  )
}

pub fn gen_info<'a>(input: (&'a mut [u8], usize),
                         i: &Info)
                         -> Result<(&'a mut [u8], usize), GenError> {
    //FIXME: probably not large enough
    let capacity = 2 + i.segment_uid.as_ref().map(|s| s.len()).unwrap_or(0)
      + 2 + i.segment_filename.as_ref().map(|s| s.len()).unwrap_or(0)
      + 3 + i.prev_uid.as_ref().map(|s| s.len()).unwrap_or(0)
      + 3 + i.prev_filename.as_ref().map(|s| s.len()).unwrap_or(0)
      + 3 + i.next_uid.as_ref().map(|s| s.len()).unwrap_or(0)
      + 3 + i.next_filename.as_ref().map(|s| s.len()).unwrap_or(0)
      + 2 + i.segment_family.as_ref().map(|s| s.len()).unwrap_or(0)
      //FIXME;
      // chapter translate
      + 8
      + 8
      + 2 + i.date_utc.as_ref().map(|s| s.len()).unwrap_or(0)
      + 2 + i.title.as_ref().map(|s| s.len()).unwrap_or(0)
      + 2 + i.muxing_app.len()
      + 2 + i.writing_app.len();

    let byte_capacity = vint_size(capacity as u64);
    gen_ebml_master!(input,
      0x1549A966, byte_capacity,
      do_gen!(
           gen_opt!( i.segment_uid, gen_ebml_binary!(0x73A4) )
        >> gen_opt!( i.segment_filename, gen_ebml_str!(0x7384) )
        >> gen_opt!( i.prev_uid, gen_ebml_binary!(0x3CB923) )
        >> gen_opt!( i.prev_filename, gen_ebml_str!(0x3C83AB) )
        >> gen_opt!( i.next_uid, gen_ebml_binary!(0x3EB923) )
        >> gen_opt!( i.next_filename, gen_ebml_str!(0x3E83BB) )
        >> gen_opt!( i.segment_family, gen_ebml_binary!(0x4444) )
        //>> gen_opt!( i.chapter_translate, gen_chapter_translate )
        >> gen_call!(gen_u64, 0x2AD7B1, i.timecode_scale)
        >> gen_opt!( i.duration, gen_call!(gen_f64_ref, 0x4489) )
        >> gen_opt!( i.date_utc, gen_ebml_binary!(0x4461) )
        >> gen_opt!( i.title, gen_ebml_str!(0x7BA9) )
        >> gen_ebml_str!(0x4D80, i.muxing_app)
        >> gen_ebml_str!(0x5741, i.writing_app)
      )
    )
}

#[macro_export]
macro_rules! my_gen_many (
    (($i:expr, $idx:expr), $l:expr, $f:ident) => (
        $l.into_iter().fold(
            Ok(($i,$idx)),
            |r,v| {
                match r {
                    Err(e) => Err(e),
                    Ok(x) => { $f(x, v) },
                }
            }
        )
    );
    (($i:expr, $idx:expr), $l:expr, $f:ident!( $($args:tt)* )) => (
        $l.into_iter().fold(
            Ok(($i,$idx)),
            |r,v| {
                match r {
                    Err(e) => Err(e),
                    Ok(x) => {
                      let (i, idx) = x;
                      $f!((i, idx), $($args)*, v)
                    },
                }
            }
        )
    );
);

pub fn gen_cluster<'a>(input: (&'a mut [u8], usize),
                         c: &Cluster)
                         -> Result<(&'a mut [u8], usize), GenError> {
    let capacity = 2 + 8
      // FIXME: serialize SilentTracks
      + 2 + 8
      + 2 + 8
      + 2 + c.simple_block.iter().fold(0, |acc, data| acc+ data.len())
      // FIXME serialize BlockGRoups
      // FIXME: serialize encrypted block
      ;

    let byte_capacity = vint_size(capacity as u64);
    gen_ebml_master!(input,
      0x1F43B675, byte_capacity,
      do_gen!(
           gen_ebml_uint!(0xE7, c.timecode)
        //>> gen_opt!( c.position, gen_ebml_uint!(0xA7) )
        //>> gen_opt!( c.prev_size, gen_ebml_uint!(0xAB) )
        >> my_gen_many!( &c.simple_block, gen_ebml_binary!( 0xA3 ) )
      )
    )
}

#[cfg(test)]
mod tests {
    use super::*;
    use nom::*;
    use std::iter::repeat;

    fn test_seek_head_serializer(mut seeks: Vec<(u64, Vec<u8>)>) -> bool {
        println!("testing for {:?}", seeks);

        let mut should_fail = false;
        if seeks.len() == 0 {
            should_fail = true;
        }

        for &(_, ref id) in seeks.iter() {
            println!("id: {}", id.to_hex(16));
            if id.len() == 0 {
                println!("id is empty, returning");
                return true;
                //should_fail = true;
            }
        }

        if should_fail {
            println!("the parser should fail");
        }

        let capacity = seeks.iter().fold(0, |acc, &(_, ref v)| acc + 8 + v.len() + 100);
        println!("defining capacity as {}", capacity);

        let mut data = Vec::with_capacity(capacity);
        data.extend(repeat(0).take(capacity));

        let seek_head = SeekHead {
            positions: seeks.iter()
                .cloned()
                .map(|(position, id)| {
                    Seek {
                        id: id,
                        position: position,
                    }
                })
                .collect(),
        };

        let ser_res = {
            let gen_res = gen_seek_head((&mut data[..], 0), &seek_head);
            println!("gen_res: {:?}", gen_res);
            if let Err(e) = gen_res {
                println!("gen_res is error: {:?}", e);
                println!("should fail: {:?}", should_fail);
                return should_fail;
                /*if should_fail {
          println!("should fail");
          return true;
        }*/
            }
        };

        println!("ser_res: {:?}", ser_res);

        let parse_res = ::elements::segment_element(&data[..]);
        println!("parse_res: {:?}", parse_res);
        match parse_res {
            Ok((rest, SegmentElement::SeekHead(o))) => {
                if should_fail {
                    println!("parser should have failed on input for {:?}", seek_head);
                    println!("{}", (&data[..]).to_hex(16));
                    return false;
                }

                assert_eq!(seek_head, o);
                return true;
            }
            e => {
                if should_fail {
                    return true;
                }

                panic!(format!("parse error: {:?} for input: {:?}", e, seeks))
            }
        }

        false
    }

    quickcheck! {
    fn test_seek_head(seeks: Vec<(u64, Vec<u8>)>) -> bool {
      test_seek_head_serializer(seeks)
    }
  }
}
<|endoftext|>


<commit_before>use card_strategy::CardStrategy;

use card::Card;
use game_status::GameStatus;
use player::PlayerName;

use std::collections::BTreeMap;

#[derive(Debug)]
pub struct DefensiveCardStrategy;

/*
    Play 2 of clubs if in hand.
    If going to win a deal, do so with highest ranking card.
*/
impl DefensiveCardStrategy {
    fn score_card<'a>(card: &'a Card, game_status: &'a GameStatus) -> (i32, i32, i32, i32) {
        let card_penalty_to_me = Self::card_penalty_to_me(card, game_status);
        let card_penalty = 0 - Self::card_penalty(card, game_status);
        let trouble = Self::trouble_score(card, game_status);
        let card_rank = 0 - (u32::from(card.rank) as i32);
        (card_penalty_to_me, card_penalty, trouble, card_rank)
    }

    fn card_penalty(card: &Card, game_status: &GameStatus) -> i32 {
        game_status.round_parameters.card_points.get(card)
            .map(|penalty| *penalty)
            .unwrap_or_default()
    }

    fn card_penalty_to_me(card: &Card, game_status: &GameStatus) -> i32 {
        if Self::will_win_deal(card, game_status) {
            Self::card_penalty(card, game_status)
        } else {
            0
        }
    }

    fn trouble_score(card: &Card, game_status: &GameStatus) -> i32 {
        if Self::will_win_deal(card, game_status) {
            let trouble = u32::from(card.rank) as i32;
            if Self::card_penalty_to_me(card, game_status) < 0 {
                0 - trouble
            } else {
                trouble
            }
        } else {
            0
        }
    }

    fn will_win_deal(card: &Card, game_status: &GameStatus) -> bool {
        game_status.my_in_progress_deal.as_ref().and_then(|deal|
            deal.suit.and_then(|suit|
                deal.deal_cards.iter()
                    .map(|deal_card| deal_card.card)
                    .filter(|card| card.suit == suit)
                    .max()
                    .map(|winning_card| card.suit == suit && card.rank > winning_card.rank))).unwrap_or(true)
    }
}

impl CardStrategy for DefensiveCardStrategy {

    fn pass_cards<'a>(&mut self, game_status: &'a GameStatus) -> Vec<&'a Card> {
        // Need to order cards by potential to win lowest penalty hands
        // make sure high risk cards are passed, including those that will win high risk cards (Queen of Spades)
        let mut initial_hand = game_status.my_initial_hand.iter().collect::<Vec<&Card>>();
        initial_hand.reverse();
        initial_hand.into_iter().take(3).collect()
    }

    fn play_card<'a>(&mut self, game_status: &'a GameStatus, player_name: &PlayerName) -> &'a Card {
        let current_suit = game_status.my_in_progress_deal.as_ref().and_then(|deal| deal.suit);
        let mut valid_cards = game_status.my_current_hand.iter()
            .filter(|card| Some(card.suit) == current_suit)
            .collect::<Vec<&Card>>();

        if valid_cards.is_empty() {
            valid_cards.extend(&game_status.my_current_hand);
        }

        valid_cards.into_iter()
            .map(|card| ((Self::score_card(card, game_status), card), card))
            .collect::<BTreeMap<((i32, i32, i32, i32), &Card), &Card>>()
            .values()
            .next()
            .expect("No valid cards to play!")
    }

}

#[cfg(test)]
mod tests {
    use super::*;
    use player::PlayerName;
    use card::Card;
    use card::Rank::*;
    use card::Suit::*;
    use game_status::GameStatus;
    use game_status::dto::GameStatusDto;
    use card_strategy::CardStrategy;

    use try_from::TryFrom;
    use error::Error;

    extern crate serde;
    extern crate serde_json;

    use std::fs::File;
    use std::io::Read;

    fn open_scenario(name: &str) -> GameStatus {
        let file_name = format!("samples/scenarios/{}.json", name);
        let mut game_status_file = File::open(file_name).unwrap();
        let mut game_status_string = String::new();
        game_status_file.read_to_string(&mut game_status_string).unwrap();
        let game_status_dto: GameStatusDto = serde_json::from_str(&game_status_string).map_err(Error::from).unwrap();
        GameStatus::try_from(game_status_dto).unwrap()
    }

    fn should_play(name: &str, expected_card: Card) {
        let player_name = PlayerName::new("Derek Williams");
        let game_status = open_scenario(name);
        let card = DefensiveCardStrategy.play_card(&game_status, &player_name).clone();
        assert_eq!(expected_card, card);
    }

    #[test]
    fn normal_1() {
        should_play("normal 1", Jack.of(Diamond));
    }

    #[test]
    fn normal_2() {
        should_play("normal 2", King.of(Club));
    }

    #[test]
    fn normal_3() {
        should_play("normal 3", Six.of(Spade));
    }

    #[test]
    fn should_play_heart() {
        should_play("should play heart", Seven.of(Heart));
    }

    #[test]
    fn should_play_high_rank_1() {
        should_play("should play high rank 1", King.of(Diamond));
    }

    #[test]
    fn should_play_high_rank_2() {
        should_play("should play high rank 2", Jack.of(Spade));
    }

}<commit_msg>add strategy justification<commit_after>use card_strategy::CardStrategy;

use card::Card;
use game_status::GameStatus;
use player::PlayerName;

use std::collections::BTreeMap;

#[derive(Debug)]
pub struct DefensiveCardStrategy;

/*
    Play 2 of clubs if in hand.
    If going to win a deal, do so with highest ranking card.
*/
impl DefensiveCardStrategy {
    fn score_card<'a>(card: &'a Card, game_status: &'a GameStatus) -> (i32, i32, i32, i32) {
        let card_penalty_to_me = Self::card_penalty_to_me(card, game_status);
        let card_penalty = 0 - Self::card_penalty(card, game_status);
        let trouble = Self::trouble_score(card, game_status);
        let card_rank = 0 - (u32::from(card.rank) as i32);
        (card_penalty_to_me, card_penalty, trouble, card_rank)
    }

    fn card_penalty(card: &Card, game_status: &GameStatus) -> i32 {
        game_status.round_parameters.card_points.get(card)
            .map(|penalty| *penalty)
            .unwrap_or_default()
    }

    fn card_penalty_to_me(card: &Card, game_status: &GameStatus) -> i32 {
        if Self::will_win_deal(card, game_status) {
            Self::card_penalty(card, game_status)
        } else {
            0
        }
    }

    fn trouble_score(card: &Card, game_status: &GameStatus) -> i32 {
        if Self::will_win_deal(card, game_status) {
            let trouble = u32::from(card.rank) as i32;
            if Self::card_penalty_to_me(card, game_status) < 0 {
                0 - trouble
            } else {
                trouble
            }
        } else {
            0
        }
    }

    fn will_win_deal(card: &Card, game_status: &GameStatus) -> bool {
        game_status.my_in_progress_deal.as_ref().and_then(|deal|
            deal.suit.and_then(|suit|
                deal.deal_cards.iter()
                    .map(|deal_card| deal_card.card)
                    .filter(|card| card.suit == suit)
                    .max()
                    .map(|winning_card| card.suit == suit && card.rank > winning_card.rank))).unwrap_or(true)
    }
}

impl CardStrategy for DefensiveCardStrategy {

    fn pass_cards<'a>(&mut self, game_status: &'a GameStatus) -> Vec<&'a Card> {
        // Need to order cards by potential to win lowest penalty hands
        // make sure high risk cards are passed, including those that will win high risk cards (Queen of Spades)
        let mut initial_hand = game_status.my_initial_hand.iter().collect::<Vec<&Card>>();
        initial_hand.reverse();
        initial_hand.into_iter().take(3).collect()
    }

    fn play_card<'a>(&mut self, game_status: &'a GameStatus, player_name: &PlayerName) -> &'a Card {
        let current_suit = game_status.my_in_progress_deal.as_ref().and_then(|deal| deal.suit);
        let mut valid_cards = game_status.my_current_hand.iter()
            .filter(|card| Some(card.suit) == current_suit)
            .collect::<Vec<&Card>>();

        if valid_cards.is_empty() {
            valid_cards.extend(&game_status.my_current_hand);
        }

        valid_cards.into_iter()
            .map(|card| ((Self::score_card(card, game_status), card), card))
            .collect::<BTreeMap<((i32, i32, i32, i32), &Card), &Card>>()
            .values()
            .next()
            .expect("No valid cards to play!")
    }

}

#[cfg(test)]
mod tests {
    use super::*;
    use player::PlayerName;
    use card::Card;
    use card::Rank::*;
    use card::Suit::*;
    use game_status::GameStatus;
    use game_status::dto::GameStatusDto;
    use card_strategy::CardStrategy;

    use try_from::TryFrom;
    use error::Error;

    extern crate serde;
    extern crate serde_json;

    use std::fs::File;
    use std::io::Read;

    fn open_scenario(name: &str) -> GameStatus {
        let file_name = format!("samples/scenarios/{}.json", name);
        let mut game_status_file = File::open(file_name).unwrap();
        let mut game_status_string = String::new();
        game_status_file.read_to_string(&mut game_status_string).unwrap();
        let game_status_dto: GameStatusDto = serde_json::from_str(&game_status_string).map_err(Error::from).unwrap();
        GameStatus::try_from(game_status_dto).unwrap()
    }

    fn should_play(name: &str, expected_card: Card) {
        let player_name = PlayerName::new("Derek Williams");
        let game_status = open_scenario(name);
        let card = DefensiveCardStrategy.play_card(&game_status, &player_name).clone();
        assert_eq!(expected_card, card);
    }

    #[test]
    fn normal_1() {
        should_play("normal 1", Jack.of(Diamond));
    }

    #[test]
    fn normal_2() {
        should_play("normal 2", King.of(Club));
    }

    #[test]
    fn normal_3() {
        should_play("normal 3", Six.of(Spade));
    }

    #[test]
    fn should_play_heart() { // Opening card should not try to win
        should_play("should play heart", Seven.of(Heart));
    }

    #[test]
    fn should_play_high_rank_1() { // Should get rid of high rank
        should_play("should play high rank 1", King.of(Diamond));
    }

    #[test]
    fn should_play_high_rank_2() { // Should get rid of high risk high rank
        should_play("should play high rank 2", Ace.of(Spade));
    }

}<|endoftext|>