<commit_before>use std::{thread, time};
use std::env;
use std::io::prelude::*;
use std::fs::File;

/// Chipate Module
/// Rust emulation of the Chip-8
/// http://www.multigesturearticles/how-to-write-an-emulator-chip-8-interpreter/
#[allow(dead_code)]
pub struct Chipate {
    // Opcodes
    opcode: u16,

    // 4K Memory
    memory: [u8; 4096],
    // The systems memory map:
    // 0x000-0x1FF - Chip 8 interpreter (contains font set in emu)
    // 0x050-0x0A0 - Used for the built in 4x5 pixel font set (0-F)
    // 0x200-0xFFF - Program ROM and work RAM

    // Registers
    v: [u8; 16],

    // Index
    i: u16,

    // Program Counter
    pc: u16,

    gfx: [u8; 64 * 32],

    // Timers
    delay_timer: u8,
    sound_timer: u8,

    // Stack
    stack: [u8; 16],
    sp: u8,

    // Keypad
    key: [u8; 16],

    program: &'static str,
}

impl Chipate {
    pub fn init(&mut self) {
        debug!("Initialize Chip");
        // pc     = 0x200;  // Program counter starts at 0x200
        self.pc = 0x200;
        // opcode = 0;      // Reset current opcode
        self.opcode = 0x0;
        // I      = 0;      // Reset index register
        self.i = 0x0;
        // sp     = 0;      // Reset stack pointer
        self.sp = 0x0;

        // // Clear display
        // // Clear stack
        // // Clear registers V0-VF
        // // Clear memory

        // // Load fontset
        // for(int i = 0; i < 80; ++i)
        //     memory[i] = chip8_fontset[i];

        // // Reset timers
    }

    pub fn load_program(&mut self, program: &str) {
        debug!("Loading program {}", program);

        // We assume that we are in a valid directory.
        let mut p = env::current_dir().unwrap();
        p.push("programs");
        p.push(program);

        let mut f = File::open(p).expect("Unable to open file");
        let mut b = Vec::new();

        f.read_to_end(&mut b).expect("Unable to read file");

        for i in 0..b.len() {
            self.memory[i + 512] = b[i];
        }

    }

    pub fn emulate_cycle(&mut self) {
        debug!("Cycle Begin");

        self.fetch_opcode();
        self.decode_opcode();

        let one_second = time::Duration::from_millis(15);
        thread::sleep(one_second);

        debug!("Cycle End");
    }

    pub fn draw_screen(&mut self) {
        debug!("Drawing to Screen")
    }

    pub fn set_keys(&mut self) {
        debug!("Saving Key State")
    }

    // pub fn setup_testing_memory(&mut self) {
    //     debug!("Setting test memory");

    //     self.memory[self.pc as usize] = 0xA2;
    //     self.memory[(self.pc + 1) as usize] = 0xF0;

    //     debug!("Location: 0x{:X} data: 0x{:X}",
    //            self.pc,
    //            self.memory[self.pc as usize]);
    //     debug!("Location: 0x{:X} data: 0x{:X}",
    //            self.pc + 1,
    //            self.memory[(self.pc + 1) as usize]);
    // }

    pub fn fetch_opcode(&mut self) {
        let op_a = self.memory[self.pc as usize];
        self.opcode = op_a as u16;
        self.opcode = self.opcode << 8;
        // debug!("location: 0x{:X} data: 0x{:X}", self.pc, self.opcode);

        let op_b = self.memory[(self.pc + 1) as usize] as u16;
        // debug!("location: 0x{:X} data: 0x{:X}", self.pc, op_b);

        self.opcode = self.opcode | op_b;
        debug!("Opcode: 0x{:X}", self.opcode);
    }

    pub fn decode_opcode(&mut self) {
        let op = self.opcode & 0xF000;
        debug!("Decode: 0x{:X}", op);

        match op {
            0x2000 => self._2nnn_opcode(),
            0x6000 => self._6xnn_opcode(),
            0x7000 => self._7xnn_opcode(),
            0xA000 => self._annn_opcode(),
            _ => {
                // Using the catch all as a NOOP
                info!("Catch all: 0x{:X}", self.opcode);
                self.increase_pc();
            }
        }
    }

    pub fn increase_pc(&mut self) {
        self.pc += 2;
        debug!("Program Counter: 0x{:X}", self.pc);
    }

    /// 2NNN 	Flow 	*(0xNNN)() 	Calls subroutine at NNN.
    pub fn _2nnn_opcode(&mut self) {
        info!("2NNN: 0x{:X}", self.opcode);
        self.stack[self.sp as usize];
        self.sp += 1;
        self.pc = self.opcode & 0x0FFF;
    }

    /// 6XNN 	Const 	Vx = NN 	Sets VX to NN.
    pub fn _6xnn_opcode(&mut self) {
        info!("6XNN: 0x{:X}", self.opcode);
        let mut reg = self.opcode & 0x0F00;
        reg = reg >> 12;
        let data = self.opcode & 0x00FF;
        self.v[reg as usize] = data as u8;
        self.increase_pc();
    }

    /// 7XNN 	Const 	Vx += NN 	Adds NN to VX.
    pub fn _7xnn_opcode(&mut self) {
        info!("7XNN: 0x{:X}", self.opcode);
        let mut reg = self.opcode & 0x0F00;
        reg = reg >> 12;
        self.v[reg as usize] = (self.opcode & 0x00FF) as u8 + self.v[reg as usize] as u8;
    }

    /// ANNN 	MEM 	I = NNN 	Sets I to the address NNN.
    pub fn _annn_opcode(&mut self) {
        info!("ANNN: 0x{:X}", self.opcode);
        self.i = self.opcode & 0x0FFF;
        self.increase_pc();
    }

    /// FX07 	Timer 	Vx = get_delay() 	Sets VX to the value of the delay timer.
    pub fn _fx07_opcode(&mut self) {
        info!("FX07: 0x{:X}", self.opcode);

        let mut reg = self.opcode & 0x0F00;
        reg = reg >> 12;
        self.v[reg as usize] = self.delay_timer;

        self.increase_pc();
    }

    /// FX0A 	KeyOp 	Vx = get_key() 	A key press is awaited, and then stored in VX. (Blocking Operation. All instruction halted until next key event)
    pub fn _fx0a_opcode(&mut self) {
        info!("FX0A: 0x{:X}", self.opcode);
        self.increase_pc();
    }

    /// FX15 	Timer 	delay_timer(Vx) 	Sets the delay timer to VX.
    pub fn _fx15_opcode(&mut self) {
        info!("FX15: 0x{:X}", self.opcode);

        let mut reg = self.opcode & 0x0F00;
        reg = reg >> 12;
        self.delay_timer = self.v[reg as usize];

        self.increase_pc();
    }

    /// FX18 	Sound 	sound_timer(Vx) 	Sets the sound timer to VX.
    pub fn _fx18_opcode(&mut self) {
        info!("FX18: 0x{:X}", self.opcode);

        let mut reg = self.opcode & 0x0F00;
        reg = reg >> 12;
        self.sound_timer = self.v[reg as usize];

        self.increase_pc();
    }

    /// FX1E 	MEM 	I +=Vx 	Adds VX to I.[3]
    pub fn _fx1e_opcode(&mut self) {
        info!("FX1E: 0x{:X}", self.opcode);
        self.increase_pc();
    }

    /// FX29 	MEM 	I=sprite_addr[Vx] 	Sets I to the location of the sprite for the character in VX. Characters 0-F (in hexadecimal) are represented by a 4x5 font.
    pub fn _fx29_opcode(&mut self) {
        info!("FX29: 0x{:X}", self.opcode);
        self.increase_pc();
    }

    /// FX33 	BCD 	....  Stores the binary-coded decimal representation of VX, with the most significant of three digits at the address in I, the middle digit at I plus 1, and the least significant digit at I plus 2. (In other words, take the decimal representation of VX, place the hundreds digit in memory at location in I, the tens digit at location I+1, and the ones digit at location I+2.)
    pub fn _fx33_opcode(&mut self) {
        info!("FX33: 0x{:X}", self.opcode);
        self.increase_pc();
    }

    /// FX55 	MEM 	reg_dump(Vx,&I) 	Stores V0 to VX (including VX) in memory starting at address I.[4]
    pub fn _fx55_opcode(&mut self) {
        info!("FX55: 0x{:X}", self.opcode);
        self.increase_pc();
    }

    /// FX65 	MEM 	reg_load(Vx,&I) 	Fills V0 to VX (including VX) with values from memory starting at address I.[4]
    pub fn _fx65_opcode(&mut self) {
        info!("FX65: 0x{:X}", self.opcode);
        self.increase_pc();
    }

    pub fn _f_opcodes(&mut self) {
        let sub_op = self.opcode & 0x00FF;
        debug!("Decode: 0x{:X}", sub_op);

        match sub_op{
            0x0007 => self._fx07_opcode(),
            _ => {
                // Using the catch all as a NOOP
                info!("Catch all 0xFxxx: 0x{:X}", self.opcode);
                self.increase_pc();
            }
        }
    }

    pub fn new() -> Chipate {
        debug!("Creating New Chip");

        let chip = Chipate {
            opcode: 0,
            memory: [0; 4096],
            v: [0; 16],
            i: 0,
            pc: 0,
            gfx: [0; 64 * 32],
            delay_timer: 0,
            sound_timer: 0,
            stack: [0; 16],
            sp: 0,
            key: [0; 16],
            program: "",
        };

        return chip;
    }
}
<commit_msg>Added F opcodes to the cycle emulation...<commit_after>use std::{thread, time};
use std::env;
use std::io::prelude::*;
use std::fs::File;

/// Chipate Module
/// Rust emulation of the Chip-8
/// http://www.multigesturearticles/how-to-write-an-emulator-chip-8-interpreter/
#[allow(dead_code)]
pub struct Chipate {
    // Opcodes
    opcode: u16,

    // 4K Memory
    memory: [u8; 4096],
    // The systems memory map:
    // 0x000-0x1FF - Chip 8 interpreter (contains font set in emu)
    // 0x050-0x0A0 - Used for the built in 4x5 pixel font set (0-F)
    // 0x200-0xFFF - Program ROM and work RAM

    // Registers
    v: [u8; 16],

    // Index
    i: u16,

    // Program Counter
    pc: u16,

    gfx: [u8; 64 * 32],

    // Timers
    delay_timer: u8,
    sound_timer: u8,

    // Stack
    stack: [u8; 16],
    sp: u8,

    // Keypad
    key: [u8; 16],

    program: &'static str,
}

impl Chipate {
    pub fn init(&mut self) {
        debug!("Initialize Chip");
        // pc     = 0x200;  // Program counter starts at 0x200
        self.pc = 0x200;
        // opcode = 0;      // Reset current opcode
        self.opcode = 0x0;
        // I      = 0;      // Reset index register
        self.i = 0x0;
        // sp     = 0;      // Reset stack pointer
        self.sp = 0x0;

        // // Clear display
        // // Clear stack
        // // Clear registers V0-VF
        // // Clear memory

        // // Load fontset
        // for(int i = 0; i < 80; ++i)
        //     memory[i] = chip8_fontset[i];

        // // Reset timers
    }

    pub fn load_program(&mut self, program: &str) {
        debug!("Loading program {}", program);

        // We assume that we are in a valid directory.
        let mut p = env::current_dir().unwrap();
        p.push("programs");
        p.push(program);

        let mut f = File::open(p).expect("Unable to open file");
        let mut b = Vec::new();

        f.read_to_end(&mut b).expect("Unable to read file");

        for i in 0..b.len() {
            self.memory[i + 512] = b[i];
        }

    }

    pub fn emulate_cycle(&mut self) {
        debug!("Cycle Begin");

        self.fetch_opcode();
        self.decode_opcode();

        let one_second = time::Duration::from_millis(1000);
        thread::sleep(one_second);

        debug!("Cycle End");
    }

    pub fn draw_screen(&mut self) {
        debug!("Drawing to Screen")
    }

    pub fn set_keys(&mut self) {
        debug!("Saving Key State")
    }

    // pub fn setup_testing_memory(&mut self) {
    //     debug!("Setting test memory");

    //     self.memory[self.pc as usize] = 0xA2;
    //     self.memory[(self.pc + 1) as usize] = 0xF0;

    //     debug!("Location: 0x{:X} data: 0x{:X}",
    //            self.pc,
    //            self.memory[self.pc as usize]);
    //     debug!("Location: 0x{:X} data: 0x{:X}",
    //            self.pc + 1,
    //            self.memory[(self.pc + 1) as usize]);
    // }

    pub fn fetch_opcode(&mut self) {
        let op_a = self.memory[self.pc as usize];
        self.opcode = op_a as u16;
        self.opcode = self.opcode << 8;
        // debug!("location: 0x{:X} data: 0x{:X}", self.pc, self.opcode);

        let op_b = self.memory[(self.pc + 1) as usize] as u16;
        // debug!("location: 0x{:X} data: 0x{:X}", self.pc, op_b);

        self.opcode = self.opcode | op_b;
        debug!("Opcode: 0x{:X}", self.opcode);
    }

    pub fn decode_opcode(&mut self) {
        let op = self.opcode & 0xF000;
        debug!("Decode: 0x{:X}", op);

        match op {
            0x2000 => self._2nnn_opcode(),
            0x6000 => self._6xnn_opcode(),
            0x7000 => self._7xnn_opcode(),
            0xA000 => self._annn_opcode(),
            0xF000 => self._f_opcodes(),
            _ => {
                // Using the catch all as a NOOP
                info!("Catch all: 0x{:X}", self.opcode);
                self.increase_pc();
            }
        }
    }

    pub fn increase_pc(&mut self) {
        self.pc += 2;
        debug!("Program Counter: 0x{:X}", self.pc);
    }

    /// 2NNN 	Flow 	*(0xNNN)() 	Calls subroutine at NNN.
    pub fn _2nnn_opcode(&mut self) {
        info!("2NNN: 0x{:X}", self.opcode);
        self.stack[self.sp as usize];
        self.sp += 1;
        self.pc = self.opcode & 0x0FFF;
        self.increase_pc();
    }

    /// 6XNN 	Const 	Vx = NN 	Sets VX to NN.
    pub fn _6xnn_opcode(&mut self) {
        info!("6XNN: 0x{:X}", self.opcode);
        let mut reg = self.opcode & 0x0F00;
        reg = reg >> 12;
        let data = self.opcode & 0x00FF;
        self.v[reg as usize] = data as u8;
        self.increase_pc();
    }

    /// 7XNN 	Const 	Vx += NN 	Adds NN to VX.
    pub fn _7xnn_opcode(&mut self) {
        info!("7XNN: 0x{:X}", self.opcode);
        let mut reg = self.opcode & 0x0F00;
        reg = reg >> 12;
        self.v[reg as usize] = (self.opcode & 0x00FF) as u8 + self.v[reg as usize] as u8;
        self.increase_pc();
    }

    /// ANNN 	MEM 	I = NNN 	Sets I to the address NNN.
    pub fn _annn_opcode(&mut self) {
        info!("ANNN: 0x{:X}", self.opcode);
        self.i = self.opcode & 0x0FFF;
        self.increase_pc();
    }

    /// FX07 	Timer 	Vx = get_delay() 	Sets VX to the value of the delay timer.
    pub fn _fx07_opcode(&mut self) {
        info!("FX07: 0x{:X}", self.opcode);

        let mut reg = self.opcode & 0x0F00;
        reg = reg >> 12;
        self.v[reg as usize] = self.delay_timer;

        self.increase_pc();
    }

    /// FX0A 	KeyOp 	Vx = get_key() 	A key press is awaited, and then stored in VX. (Blocking Operation. All instruction halted until next key event)
    pub fn _fx0a_opcode(&mut self) {
        info!("FX0A: 0x{:X}", self.opcode);
        self.increase_pc();
    }

    /// FX15 	Timer 	delay_timer(Vx) 	Sets the delay timer to VX.
    pub fn _fx15_opcode(&mut self) {
        info!("FX15: 0x{:X}", self.opcode);

        let mut reg = self.opcode & 0x0F00;
        reg = reg >> 12;
        self.delay_timer = self.v[reg as usize];

        self.increase_pc();
    }

    /// FX18 	Sound 	sound_timer(Vx) 	Sets the sound timer to VX.
    pub fn _fx18_opcode(&mut self) {
        info!("FX18: 0x{:X}", self.opcode);

        let mut reg = self.opcode & 0x0F00;
        reg = reg >> 12;
        self.sound_timer = self.v[reg as usize];

        self.increase_pc();
    }

    /// FX1E 	MEM 	I +=Vx 	Adds VX to I.[3]
    pub fn _fx1e_opcode(&mut self) {
        info!("FX1E: 0x{:X}", self.opcode);
        self.increase_pc();
    }

    /// FX29 	MEM 	I=sprite_addr[Vx] 	Sets I to the location of the sprite for the character in VX. Characters 0-F (in hexadecimal) are represented by a 4x5 font.
    pub fn _fx29_opcode(&mut self) {
        info!("FX29: 0x{:X}", self.opcode);
        self.increase_pc();
    }

    /// FX33 	BCD 	....  Stores the binary-coded decimal representation of VX, with the most significant of three digits at the address in I, the middle digit at I plus 1, and the least significant digit at I plus 2. (In other words, take the decimal representation of VX, place the hundreds digit in memory at location in I, the tens digit at location I+1, and the ones digit at location I+2.)
    pub fn _fx33_opcode(&mut self) {
        info!("FX33: 0x{:X}", self.opcode);

        let mut reg = self.opcode & 0x0F00;
        reg = reg >> 12;
        let v = self.v[reg as usize];

        debug!("FX33: {}", v);
        self.increase_pc();
    }

    /// FX55 	MEM 	reg_dump(Vx,&I) 	Stores V0 to VX (including VX) in memory starting at address I.[4]
    pub fn _fx55_opcode(&mut self) {
        info!("FX55: 0x{:X}", self.opcode);
        self.increase_pc();
    }

    /// FX65 	MEM 	reg_load(Vx,&I) 	Fills V0 to VX (including VX) with values from memory starting at address I.[4]
    pub fn _fx65_opcode(&mut self) {
        info!("FX65: 0x{:X}", self.opcode);
        self.increase_pc();
    }

    pub fn _f_opcodes(&mut self) {
        let sub_op = self.opcode & 0x00FF;
        debug!("Decode: 0x{:X}", sub_op);

        match sub_op{
            0x0007 => self._fx07_opcode(),
            0x000a => self._fx0a_opcode(),
            0x0015 => self._fx15_opcode(),
            0x0018 => self._fx18_opcode(),
            0x001e => self._fx1e_opcode(),
            0x0029 => self._fx29_opcode(),
            0x0033 => self._fx33_opcode(),
            0x0055 => self._fx55_opcode(),
            0x0065 => self._fx65_opcode(),
            _ => {
                // Using the catch all as a NOOP
                info!("Catch all 0xFxxx: 0x{:X}", self.opcode);
                self.increase_pc();
            }
        }
    }

    pub fn new() -> Chipate {
        debug!("Creating New Chip");

        let chip = Chipate {
            opcode: 0,
            memory: [0; 4096],
            v: [0; 16],
            i: 0,
            pc: 0,
            gfx: [0; 64 * 32],
            delay_timer: 0,
            sound_timer: 0,
            stack: [0; 16],
            sp: 0,
            key: [0; 16],
            program: "",
        };

        return chip;
    }
}
<|endoftext|>


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

#[macro_use]
extern crate gfx;
extern crate gfx_window_glutin;
extern crate glutin;

extern crate image;

use std::io::Cursor;
use gfx::traits::{Factory, Stream, FactoryExt};

gfx_vertex!( Vertex {
    a_Pos@ pos: [f32; 2],
    a_Uv@ uv: [f32; 2],
});

impl Vertex {
    fn new(p: [f32; 2], u: [f32; 2]) -> Vertex {
        Vertex {
            pos: p,
            uv: u,
        }
    }
}

gfx_parameters!( Params {
    t_Color@ color: gfx::shade::TextureParam<R>,
    t_Flow@ flow: gfx::shade::TextureParam<R>,
    t_Noise@ noise: gfx::shade::TextureParam<R>,
    f_Offset0@ offset0: f32,
    f_Offset1@ offset1: f32,
});

fn load_texture<R, F>(factory: &mut F, data: &[u8]) -> Result<gfx::handle::Texture<R>, String>
        where R: gfx::Resources, F: gfx::device::Factory<R> {
    let img = image::load(Cursor::new(data), image::PNG).unwrap();

    let img = match img {
        image::DynamicImage::ImageRgba8(img) => img,
        img => img.to_rgba()
    };
    let (width, height) = img.dimensions();
    let tex_info = gfx::tex::TextureInfo {
        width: width as u16,
        height: height as u16,
        depth: 1,
        levels: 1,
        kind: gfx::tex::Kind::D2,
        format: gfx::tex::RGBA8
    };

    Ok(factory.create_texture_static(tex_info, &img).unwrap())
}

pub fn main() {
    let (mut stream, mut device, mut factory) = gfx_window_glutin::init(
        glutin::WindowBuilder::new()
            .with_title("Flowmap example".to_string())
            .with_dimensions(800, 600).build().unwrap()
    );

    let vertex_data = [
        Vertex::new([-1.0, -1.0], [0.0, 0.0]),
        Vertex::new([ 1.0, -1.0], [1.0, 0.0]),
        Vertex::new([ 1.0,  1.0], [1.0, 1.0]),

        Vertex::new([-1.0, -1.0], [0.0, 0.0]),
        Vertex::new([ 1.0,  1.0], [1.0, 1.0]),
        Vertex::new([-1.0,  1.0], [0.0, 1.0]),
    ];

    let mesh = factory.create_mesh(&vertex_data);

    let water_texture = load_texture(&mut factory, &include_bytes!("image/water.png")[..]).unwrap();
    let flow_texture  = load_texture(&mut factory, &include_bytes!("image/flow.png")[..]).unwrap();
    let noise_texture = load_texture(&mut factory, &include_bytes!("image/noise.png")[..]).unwrap();

    let program = {
        let vs = gfx::ShaderSource {
            glsl_120: Some(include_bytes!("shader/flowmap_120.glslv")),
            glsl_150: Some(include_bytes!("shader/flowmap_150.glslv")),
            .. gfx::ShaderSource::empty()
        };
        let fs = gfx::ShaderSource {
            glsl_120: Some(include_bytes!("shader/flowmap_120.glslf")),
            glsl_150: Some(include_bytes!("shader/flowmap_150.glslf")),
            .. gfx::ShaderSource::empty()
        };
        factory.link_program_source(vs, fs).unwrap()
    };

    let uniforms = Params {
        color: (water_texture, None),
        flow: (flow_texture, None),
        noise: (noise_texture, None),
        offset0: 0f32,
        offset1: 0.5f32,
        _r: std::marker::PhantomData,
    };
    let mut batch = gfx::batch::Full::new(mesh, program, uniforms).unwrap();

    let mut cycle0 = 0.0f32;
    let mut cycle1 = 0.5f32;

    'main: loop {
        // quit when Esc is pressed.
        for event in stream.out.window.poll_events() {
            match event {
                glutin::Event::KeyboardInput(_, _, Some(glutin::VirtualKeyCode::Escape)) => break 'main,
                glutin::Event::Closed => break 'main,
                _ => {},
            }
        }

        // since we sample our diffuse texture twice we need to lerp between
        // them to get a smooth transition (shouldn't even be noticable).

        // they start half a cycle apart (0.5) and is later used to calculate
        // the interpolation amount via `2.0 * abs(cycle0 - .5f)`
        cycle0 += 0.0025f32;
        if cycle0 > 1f32 {
            cycle0 -= 1f32;
        }

        cycle1 += 0.0025f32;
        if cycle1 > 1f32 {
            cycle1 -= 1f32;
        }

        batch.params.offset0 = cycle0;
        batch.params.offset1 = cycle1;

        stream.clear(gfx::ClearData {
            color: [0.3, 0.3, 0.3, 1.0],
            depth: 1.0,
            stencil: 0,
        });

        stream.draw(&batch).unwrap();
        stream.present(&mut device);
    }
}
<commit_msg>Add delta time integration to flowmap example<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate time;

#[macro_use]
extern crate gfx;
extern crate gfx_window_glutin;
extern crate glutin;

extern crate image;

use std::io::Cursor;
use gfx::traits::{Factory, Stream, FactoryExt};

gfx_vertex!( Vertex {
    a_Pos@ pos: [f32; 2],
    a_Uv@ uv: [f32; 2],
});

impl Vertex {
    fn new(p: [f32; 2], u: [f32; 2]) -> Vertex {
        Vertex {
            pos: p,
            uv: u,
        }
    }
}

gfx_parameters!( Params {
    t_Color@ color: gfx::shade::TextureParam<R>,
    t_Flow@ flow: gfx::shade::TextureParam<R>,
    t_Noise@ noise: gfx::shade::TextureParam<R>,
    f_Offset0@ offset0: f32,
    f_Offset1@ offset1: f32,
});

fn load_texture<R, F>(factory: &mut F, data: &[u8]) -> Result<gfx::handle::Texture<R>, String>
        where R: gfx::Resources, F: gfx::device::Factory<R> {
    let img = image::load(Cursor::new(data), image::PNG).unwrap();

    let img = match img {
        image::DynamicImage::ImageRgba8(img) => img,
        img => img.to_rgba()
    };
    let (width, height) = img.dimensions();
    let tex_info = gfx::tex::TextureInfo {
        width: width as u16,
        height: height as u16,
        depth: 1,
        levels: 1,
        kind: gfx::tex::Kind::D2,
        format: gfx::tex::RGBA8
    };

    Ok(factory.create_texture_static(tex_info, &img).unwrap())
}

pub fn main() {
    use time::precise_time_s;

    let (mut stream, mut device, mut factory) = gfx_window_glutin::init(
        glutin::WindowBuilder::new()
            .with_title("Flowmap example".to_string())
            .with_dimensions(800, 600).build().unwrap()
    );

    let vertex_data = [
        Vertex::new([-1.0, -1.0], [0.0, 0.0]),
        Vertex::new([ 1.0, -1.0], [1.0, 0.0]),
        Vertex::new([ 1.0,  1.0], [1.0, 1.0]),

        Vertex::new([-1.0, -1.0], [0.0, 0.0]),
        Vertex::new([ 1.0,  1.0], [1.0, 1.0]),
        Vertex::new([-1.0,  1.0], [0.0, 1.0]),
    ];

    let mesh = factory.create_mesh(&vertex_data);

    let water_texture = load_texture(&mut factory, &include_bytes!("image/water.png")[..]).unwrap();
    let flow_texture  = load_texture(&mut factory, &include_bytes!("image/flow.png")[..]).unwrap();
    let noise_texture = load_texture(&mut factory, &include_bytes!("image/noise.png")[..]).unwrap();

    let program = {
        let vs = gfx::ShaderSource {
            glsl_120: Some(include_bytes!("shader/flowmap_120.glslv")),
            glsl_150: Some(include_bytes!("shader/flowmap_150.glslv")),
            .. gfx::ShaderSource::empty()
        };
        let fs = gfx::ShaderSource {
            glsl_120: Some(include_bytes!("shader/flowmap_120.glslf")),
            glsl_150: Some(include_bytes!("shader/flowmap_150.glslf")),
            .. gfx::ShaderSource::empty()
        };
        factory.link_program_source(vs, fs).unwrap()
    };

    let uniforms = Params {
        color: (water_texture, None),
        flow: (flow_texture, None),
        noise: (noise_texture, None),
        offset0: 0f32,
        offset1: 0.5f32,
        _r: std::marker::PhantomData,
    };
    let mut batch = gfx::batch::Full::new(mesh, program, uniforms).unwrap();

    let mut cycle0 = 0.0f32;
    let mut cycle1 = 0.5f32;

    let mut time_start = precise_time_s();
    let mut time_end;
    'main: loop {
        time_end = time_start;
        time_start = precise_time_s();

        let delta = (time_start - time_end) as f32;

        // quit when Esc is pressed.
        for event in stream.out.window.poll_events() {
            match event {
                glutin::Event::KeyboardInput(_, _, Some(glutin::VirtualKeyCode::Escape)) => break 'main,
                glutin::Event::Closed => break 'main,
                _ => {},
            }
        }

        // since we sample our diffuse texture twice we need to lerp between
        // them to get a smooth transition (shouldn't even be noticable).

        // they start half a cycle apart (0.5) and is later used to calculate
        // the interpolation amount via `2.0 * abs(cycle0 - .5f)`
        cycle0 += 0.25f32 * delta;
        if cycle0 > 1f32 {
            cycle0 -= 1f32;
        }

        cycle1 += 0.25f32 * delta;
        if cycle1 > 1f32 {
            cycle1 -= 1f32;
        }

        batch.params.offset0 = cycle0;
        batch.params.offset1 = cycle1;

        stream.clear(gfx::ClearData {
            color: [0.3, 0.3, 0.3, 1.0],
            depth: 1.0,
            stencil: 0,
        });

        stream.draw(&batch).unwrap();
        stream.present(&mut device);
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;

use state::State;
use super::{Action, config, Conditions, Message, TimerEvent};

use action::ActionCommand;
use self::linear::LinearContext;
use self::map::MapContext;

#[derive(Debug)]
pub struct BaseContext {
    conditions: Conditions,
    actions: Vec<Action>
}

impl BaseContext {
    pub fn new(conditions: Conditions) -> BaseContext {
        BaseContext {
            conditions: conditions,
            actions: Vec::new()
        }
    }

    pub fn actions(&self) -> &[Action] {
        &self.actions
    }

    pub fn on_timer(&self, event: &TimerEvent, state: &mut State) -> Option<Vec<ActionCommand>> {
        self.conditions.on_timer(event, state, self)
    }

    pub fn on_message(&self, event: Rc<Message>, state: &mut State) -> Option<Vec<ActionCommand>> {
        self.conditions.on_message(event, state, self)
    }
}

impl From<config::Context> for BaseContext {
    fn from(config: config::Context) -> BaseContext {
        let config::Context{conditions, actions} = config;
        BaseContext {
            conditions: conditions,
            actions: actions
        }
    }
}

#[derive(Debug)]
pub enum Context {
    Linear(LinearContext),
    Map(MapContext)
}

impl Context {
    pub fn on_timer(&mut self, event: &TimerEvent) -> Option<Vec<ActionCommand>> {
        match *self {
            Context::Linear(ref mut context) => context.on_timer(event),
            Context::Map(ref mut context) => context.on_timer(event),
        }
    }

    pub fn on_message(&mut self, event: Rc<Message>) -> Option<Vec<ActionCommand>> {
        match *self {
            Context::Linear(ref mut context) => context.on_message(event),
            Context::Map(ref mut context) => context.on_message(event),
        }
    }

    pub fn is_open(&mut self) -> bool {
        match *self {
            Context::Linear(ref context) => context.is_open(),
            Context::Map(ref mut context) => context.is_open(),
        }
    }

    pub fn new_linear(conditions: Conditions) -> Context {
        Context::Linear(
            LinearContext::new(conditions)
        )
    }

    pub fn new_map(conditions: Conditions) -> Context {
        Context::Map(
            MapContext::new(conditions)
        )
    }
}

impl From<config::Context> for Context {
    fn from(config: config::Context) -> Context {
        Context::Linear(LinearContext::from(config))
    }
}

mod linear {
    use std::rc::Rc;

    use action::ActionCommand;
    use config;
    use Conditions;
    use Message;
    use state::State;
    use TimerEvent;
    use super::BaseContext;

    #[derive(Debug)]
    pub struct LinearContext {
        base: BaseContext,
        state: State
    }

    impl LinearContext {
        pub fn new(conditions: Conditions) -> LinearContext {
            LinearContext {
                base: BaseContext::new(conditions),
                state: State::new()
            }
        }

        pub fn on_timer(&mut self, event: &TimerEvent) -> Option<Vec<ActionCommand>> {
            self.base.on_timer(event, &mut self.state)
        }

        pub fn on_message(&mut self, event: Rc<Message>) -> Option<Vec<ActionCommand>> {
            self.base.on_message(event, &mut self.state)
        }

        pub fn is_open(&self) -> bool {
            self.state.is_open()
        }
    }

    impl From<config::Context> for LinearContext {
        fn from(config: config::Context) -> LinearContext {
            LinearContext {
                base: BaseContext::from(config),
                state: State::new()
            }
        }
    }
}

mod map {
    use std::collections::BTreeMap;
    use std::fmt::Write;
    use std::rc::Rc;

    use action::ActionCommand;
    use Conditions;
    use Message;
    use state::State;
    use TimerEvent;
    use super::BaseContext;

    #[derive(Debug)]
    pub struct MapContext {
        base: BaseContext,
        map: BTreeMap<String, State>,
        format_buffer: String
    }

    impl MapContext {
        pub fn new(conditions: Conditions) -> MapContext {
            MapContext {
                base: BaseContext::new(conditions),
                map: BTreeMap::new(),
                format_buffer: String::new()
            }
        }

        pub fn on_timer(&mut self, event: &TimerEvent) -> Option<Vec<ActionCommand>> {
            let mut result: Vec<ActionCommand> = Vec::new();

            for (_, mut state) in self.map.iter_mut() {
                if let Some(commands) = self.base.on_timer(event, &mut state) {
                    for i in commands.into_iter() {
                        result.push(i);
                    }
                }
            }

            if result.is_empty() {
                None
            } else {
                self.remove_closed_states();
                Some(result)
            }
        }

        fn get_closed_state_ids(&self) -> Vec<String> {
            self.map.iter().filter_map(|(id, state)| {
                if !state.is_open() {
                    Some(id.clone())
                } else {
                    None
                }
            }).collect::<Vec<String>>()
        }

        fn remove_closed_states(&mut self) {
            for id in self.get_closed_state_ids() {
                let state = self.map.remove(&id);
            }
        }

        pub fn on_message(&mut self, event: Rc<Message>) -> Option<Vec<ActionCommand>> {
            self.format_context_id(&event);
            let result = self.update_state(event);
            self.format_buffer.clear();
            self.remove_closed_states();
            result
        }

        fn update_state(&mut self, event: Rc<Message>) -> Option<Vec<ActionCommand>> {
            let id = self.format_buffer.clone();
            let state = self.map.entry(self.format_buffer.clone()).or_insert(State::new());
            self.base.on_message(event, state)
        }

        pub fn is_open(&mut self) -> bool {
            !self.map.is_empty()
        }

        fn format_context_id(&mut self, message: &Message) {
            let empty = String::new();
            let _ = self.format_buffer.write_str(message.get("HOST").unwrap_or(&empty));
            let _ = self.format_buffer.write_str(":");
            let _ = self.format_buffer.write_str(message.get("PROGRAM").unwrap_or(&empty));
            let _ = self.format_buffer.write_str(":");
            let _ = self.format_buffer.write_str(message.get("PID").unwrap_or(&empty));
        }
    }

    #[cfg(test)]
    mod test {
        use conditions::Builder;
        use Context;
        use TimerEvent;
        use message;

        use std::rc::Rc;

        #[test]
        fn test_given_map_context_when_messages_have_the_same_kvpairs_then_they_go_to_the_same_context() {
            let delta = 10;
            let timeout = 30;
            let event = TimerEvent(delta);
            let patterns: Vec<String> = vec!["1".to_string(), "2".to_string(), "3".to_string()];
            let mut context = Context::new_map(Builder::new(timeout).patterns(patterns).build());
            let msg1 = message::Builder::new("1".to_string())
                                        .pair("HOST".to_string(), "host".to_string())
                                        .pair("PROGRAM".to_string(), "program".to_string())
                                        .pair("PID".to_string(), "pid".to_string())
                                        .build();
            let msg2 = message::Builder::new("2".to_string())
                                        .pair("HOST".to_string(), "host2".to_string())
                                        .pair("PROGRAM".to_string(), "program2".to_string())
                                        .pair("PID".to_string(), "pid2".to_string())
                                        .build();
            let msg3 = message::Builder::new("3".to_string())
                                        .pair("HOST".to_string(), "host".to_string())
                                        .pair("PROGRAM".to_string(), "program".to_string())
                                        .pair("PID".to_string(), "pid".to_string())
                                        .build();

            assert_false!(context.is_open());
            context.on_message(Rc::new(msg1));
            assert_true!(context.is_open());
            context.on_timer(&event);
            context.on_message(Rc::new(msg2));
            context.on_message(Rc::new(msg3));
            context.on_timer(&event);
            context.on_timer(&event);
            assert_true!(context.is_open());
            context.on_timer(&event);
            assert_false!(context.is_open());
        }
    }
}

#[cfg(test)]
mod test {
    use std::rc::Rc;

    use message;
    use TimerEvent;
    use super::Context;
    use conditions::Builder;

    #[test]
    fn test_given_close_condition_with_timeout_when_the_timeout_expires_then_the_condition_is_met() {
        let timeout = 100;
        let msg_id = "1".to_string();
        let mut context = Context::new_linear(Builder::new(timeout).patterns(vec![msg_id.clone()]).build());
        let msg1 = message::Builder::new(msg_id.clone()).build();
        let event = Rc::new(msg1);
        println!("{:?}", &context);
        assert_false!(context.is_open());
        context.on_message(event);
        assert_true!(context.is_open());
        context.on_timer(&mut TimerEvent(50));
        assert_true!(context.is_open());
        context.on_timer(&mut TimerEvent(49));
        assert_true!(context.is_open());
        context.on_timer(&mut TimerEvent(1));
        assert_false!(context.is_open());
    }

    #[test]
    fn test_given_close_condition_with_max_size_when_the_max_size_reached_then_the_condition_is_met() {
        let timeout = 100;
        let max_size = 3;
        let msg_id = "1".to_string();
        let mut context = Context::new_linear(Builder::new(timeout).max_size(max_size).patterns(vec![msg_id.clone()]).build());
        let msg1 = message::Builder::new(msg_id.clone()).build();
        let event = Rc::new(msg1);
        println!("{:?}", &context);
        context.on_message(event.clone());
        assert_true!(context.is_open());
        context.on_message(event.clone());
        assert_true!(context.is_open());
        context.on_message(event.clone());
        println!("{:?}", &context);
        assert_false!(context.is_open());
    }

    #[test]
    fn test_given_close_condition_with_renew_timeout_when_the_timeout_expires_without_renewing_messages_then_the_condition_is_met() {
        let timeout = 100;
        let renew_timeout = 10;
        let msg_id = "1".to_string();
        let mut context = Context::new_linear(Builder::new(timeout).renew_timeout(renew_timeout).patterns(vec![msg_id.clone()]).build());
        let msg1 = message::Builder::new(msg_id.clone()).build();
        let event = Rc::new(msg1);
        context.on_message(event.clone());
        assert_true!(context.is_open());
        context.on_timer(&mut TimerEvent(8));
        assert_true!(context.is_open());
        context.on_timer(&mut TimerEvent(1));
        assert_true!(context.is_open());
        context.on_timer(&mut TimerEvent(1));
        assert_false!(context.is_open());
    }

    #[test]
    fn test_given_close_condition_with_renew_timeout_when_the_timeout_expires_with_renewing_messages_then_the_context_is_not_closed() {
        let timeout = 100;
        let renew_timeout = 10;
        let msg_id = "1".to_string();
        let mut context = Context::new_linear(Builder::new(timeout).renew_timeout(renew_timeout).patterns(vec![msg_id.clone()]).build());
        let msg1 = message::Builder::new(msg_id.clone()).build();
        let event = Rc::new(msg1);
        assert_false!(context.is_open());
        context.on_message(event.clone());
        assert_true!(context.is_open());
        context.on_timer(&mut TimerEvent(8));
        assert_true!(context.is_open());
        context.on_timer(&mut TimerEvent(1));
        assert_true!(context.is_open());
        context.on_message(event.clone());
        assert_true!(context.is_open());
        context.on_timer(&mut TimerEvent(1));
        assert_true!(context.is_open());
    }
}
<commit_msg>MapContext: always remove the closed states<commit_after>use std::rc::Rc;

use state::State;
use super::{Action, config, Conditions, Message, TimerEvent};

use action::ActionCommand;
use self::linear::LinearContext;
use self::map::MapContext;

#[derive(Debug)]
pub struct BaseContext {
    conditions: Conditions,
    actions: Vec<Action>
}

impl BaseContext {
    pub fn new(conditions: Conditions) -> BaseContext {
        BaseContext {
            conditions: conditions,
            actions: Vec::new()
        }
    }

    pub fn actions(&self) -> &[Action] {
        &self.actions
    }

    pub fn on_timer(&self, event: &TimerEvent, state: &mut State) -> Option<Vec<ActionCommand>> {
        self.conditions.on_timer(event, state, self)
    }

    pub fn on_message(&self, event: Rc<Message>, state: &mut State) -> Option<Vec<ActionCommand>> {
        self.conditions.on_message(event, state, self)
    }
}

impl From<config::Context> for BaseContext {
    fn from(config: config::Context) -> BaseContext {
        let config::Context{conditions, actions} = config;
        BaseContext {
            conditions: conditions,
            actions: actions
        }
    }
}

#[derive(Debug)]
pub enum Context {
    Linear(LinearContext),
    Map(MapContext)
}

impl Context {
    pub fn on_timer(&mut self, event: &TimerEvent) -> Option<Vec<ActionCommand>> {
        match *self {
            Context::Linear(ref mut context) => context.on_timer(event),
            Context::Map(ref mut context) => context.on_timer(event),
        }
    }

    pub fn on_message(&mut self, event: Rc<Message>) -> Option<Vec<ActionCommand>> {
        match *self {
            Context::Linear(ref mut context) => context.on_message(event),
            Context::Map(ref mut context) => context.on_message(event),
        }
    }

    pub fn is_open(&mut self) -> bool {
        match *self {
            Context::Linear(ref context) => context.is_open(),
            Context::Map(ref mut context) => context.is_open(),
        }
    }

    pub fn new_linear(conditions: Conditions) -> Context {
        Context::Linear(
            LinearContext::new(conditions)
        )
    }

    pub fn new_map(conditions: Conditions) -> Context {
        Context::Map(
            MapContext::new(conditions)
        )
    }
}

impl From<config::Context> for Context {
    fn from(config: config::Context) -> Context {
        Context::Linear(LinearContext::from(config))
    }
}

mod linear {
    use std::rc::Rc;

    use action::ActionCommand;
    use config;
    use Conditions;
    use Message;
    use state::State;
    use TimerEvent;
    use super::BaseContext;

    #[derive(Debug)]
    pub struct LinearContext {
        base: BaseContext,
        state: State
    }

    impl LinearContext {
        pub fn new(conditions: Conditions) -> LinearContext {
            LinearContext {
                base: BaseContext::new(conditions),
                state: State::new()
            }
        }

        pub fn on_timer(&mut self, event: &TimerEvent) -> Option<Vec<ActionCommand>> {
            self.base.on_timer(event, &mut self.state)
        }

        pub fn on_message(&mut self, event: Rc<Message>) -> Option<Vec<ActionCommand>> {
            self.base.on_message(event, &mut self.state)
        }

        pub fn is_open(&self) -> bool {
            self.state.is_open()
        }
    }

    impl From<config::Context> for LinearContext {
        fn from(config: config::Context) -> LinearContext {
            LinearContext {
                base: BaseContext::from(config),
                state: State::new()
            }
        }
    }
}

mod map {
    use std::collections::BTreeMap;
    use std::fmt::Write;
    use std::rc::Rc;

    use action::ActionCommand;
    use Conditions;
    use Message;
    use state::State;
    use TimerEvent;
    use super::BaseContext;

    #[derive(Debug)]
    pub struct MapContext {
        base: BaseContext,
        map: BTreeMap<String, State>,
        format_buffer: String
    }

    impl MapContext {
        pub fn new(conditions: Conditions) -> MapContext {
            MapContext {
                base: BaseContext::new(conditions),
                map: BTreeMap::new(),
                format_buffer: String::new()
            }
        }

        pub fn on_timer(&mut self, event: &TimerEvent) -> Option<Vec<ActionCommand>> {
            let mut result: Vec<ActionCommand> = Vec::new();

            for (_, mut state) in self.map.iter_mut() {
                if let Some(commands) = self.base.on_timer(event, &mut state) {
                    for i in commands.into_iter() {
                        result.push(i);
                    }
                }
            }

            self.remove_closed_states();
            if result.is_empty() {
                None
            } else {
                Some(result)
            }
        }

        fn get_closed_state_ids(&self) -> Vec<String> {
            self.map.iter().filter_map(|(id, state)| {
                if !state.is_open() {
                    Some(id.clone())
                } else {
                    None
                }
            }).collect::<Vec<String>>()
        }

        fn remove_closed_states(&mut self) {
            for id in self.get_closed_state_ids() {
                let state = self.map.remove(&id);
            }
        }

        pub fn on_message(&mut self, event: Rc<Message>) -> Option<Vec<ActionCommand>> {
            self.format_context_id(&event);
            let result = self.update_state(event);
            self.format_buffer.clear();
            self.remove_closed_states();
            result
        }

        fn update_state(&mut self, event: Rc<Message>) -> Option<Vec<ActionCommand>> {
            let id = self.format_buffer.clone();
            let state = self.map.entry(self.format_buffer.clone()).or_insert(State::new());
            self.base.on_message(event, state)
        }

        pub fn is_open(&mut self) -> bool {
            !self.map.is_empty()
        }

        fn format_context_id(&mut self, message: &Message) {
            let empty = String::new();
            let _ = self.format_buffer.write_str(message.get("HOST").unwrap_or(&empty));
            let _ = self.format_buffer.write_str(":");
            let _ = self.format_buffer.write_str(message.get("PROGRAM").unwrap_or(&empty));
            let _ = self.format_buffer.write_str(":");
            let _ = self.format_buffer.write_str(message.get("PID").unwrap_or(&empty));
        }
    }

    #[cfg(test)]
    mod test {
        use conditions::Builder;
        use Context;
        use TimerEvent;
        use message;

        use std::rc::Rc;

        #[test]
        fn test_given_map_context_when_messages_have_the_same_kvpairs_then_they_go_to_the_same_context() {
            let delta = 10;
            let timeout = 30;
            let event = TimerEvent(delta);
            let patterns: Vec<String> = vec!["1".to_string(), "2".to_string(), "3".to_string()];
            let mut context = Context::new_map(Builder::new(timeout).patterns(patterns).build());
            let msg1 = message::Builder::new("1".to_string())
                                        .pair("HOST".to_string(), "host".to_string())
                                        .pair("PROGRAM".to_string(), "program".to_string())
                                        .pair("PID".to_string(), "pid".to_string())
                                        .build();
            let msg2 = message::Builder::new("2".to_string())
                                        .pair("HOST".to_string(), "host2".to_string())
                                        .pair("PROGRAM".to_string(), "program2".to_string())
                                        .pair("PID".to_string(), "pid2".to_string())
                                        .build();
            let msg3 = message::Builder::new("3".to_string())
                                        .pair("HOST".to_string(), "host".to_string())
                                        .pair("PROGRAM".to_string(), "program".to_string())
                                        .pair("PID".to_string(), "pid".to_string())
                                        .build();

            assert_false!(context.is_open());
            context.on_message(Rc::new(msg1));
            assert_true!(context.is_open());
            context.on_timer(&event);
            context.on_message(Rc::new(msg2));
            context.on_message(Rc::new(msg3));
            context.on_timer(&event);
            context.on_timer(&event);
            assert_true!(context.is_open());
            context.on_timer(&event);
            assert_false!(context.is_open());
        }
    }
}

#[cfg(test)]
mod test {
    use std::rc::Rc;

    use message;
    use TimerEvent;
    use super::Context;
    use conditions::Builder;

    #[test]
    fn test_given_close_condition_with_timeout_when_the_timeout_expires_then_the_condition_is_met() {
        let timeout = 100;
        let msg_id = "1".to_string();
        let mut context = Context::new_linear(Builder::new(timeout).patterns(vec![msg_id.clone()]).build());
        let msg1 = message::Builder::new(msg_id.clone()).build();
        let event = Rc::new(msg1);
        println!("{:?}", &context);
        assert_false!(context.is_open());
        context.on_message(event);
        assert_true!(context.is_open());
        context.on_timer(&mut TimerEvent(50));
        assert_true!(context.is_open());
        context.on_timer(&mut TimerEvent(49));
        assert_true!(context.is_open());
        context.on_timer(&mut TimerEvent(1));
        assert_false!(context.is_open());
    }

    #[test]
    fn test_given_close_condition_with_max_size_when_the_max_size_reached_then_the_condition_is_met() {
        let timeout = 100;
        let max_size = 3;
        let msg_id = "1".to_string();
        let mut context = Context::new_linear(Builder::new(timeout).max_size(max_size).patterns(vec![msg_id.clone()]).build());
        let msg1 = message::Builder::new(msg_id.clone()).build();
        let event = Rc::new(msg1);
        println!("{:?}", &context);
        context.on_message(event.clone());
        assert_true!(context.is_open());
        context.on_message(event.clone());
        assert_true!(context.is_open());
        context.on_message(event.clone());
        println!("{:?}", &context);
        assert_false!(context.is_open());
    }

    #[test]
    fn test_given_close_condition_with_renew_timeout_when_the_timeout_expires_without_renewing_messages_then_the_condition_is_met() {
        let timeout = 100;
        let renew_timeout = 10;
        let msg_id = "1".to_string();
        let mut context = Context::new_linear(Builder::new(timeout).renew_timeout(renew_timeout).patterns(vec![msg_id.clone()]).build());
        let msg1 = message::Builder::new(msg_id.clone()).build();
        let event = Rc::new(msg1);
        context.on_message(event.clone());
        assert_true!(context.is_open());
        context.on_timer(&mut TimerEvent(8));
        assert_true!(context.is_open());
        context.on_timer(&mut TimerEvent(1));
        assert_true!(context.is_open());
        context.on_timer(&mut TimerEvent(1));
        assert_false!(context.is_open());
    }

    #[test]
    fn test_given_close_condition_with_renew_timeout_when_the_timeout_expires_with_renewing_messages_then_the_context_is_not_closed() {
        let timeout = 100;
        let renew_timeout = 10;
        let msg_id = "1".to_string();
        let mut context = Context::new_linear(Builder::new(timeout).renew_timeout(renew_timeout).patterns(vec![msg_id.clone()]).build());
        let msg1 = message::Builder::new(msg_id.clone()).build();
        let event = Rc::new(msg1);
        assert_false!(context.is_open());
        context.on_message(event.clone());
        assert_true!(context.is_open());
        context.on_timer(&mut TimerEvent(8));
        assert_true!(context.is_open());
        context.on_timer(&mut TimerEvent(1));
        assert_true!(context.is_open());
        context.on_message(event.clone());
        assert_true!(context.is_open());
        context.on_timer(&mut TimerEvent(1));
        assert_true!(context.is_open());
    }
}
<|endoftext|>


<commit_before>const INTERPRETER_START: u32 = 0x000;
const INTERPRETER_END: u32 = 0x1FF;
const INTERPRETER_LENGTH: u32 = INTERPRETER_END - INTERPRETER_START;

const FONT_SET_START: usize = 0x050;
const FONT_SET_END: usize = 0x0A0;
const FONT_SET_LENGTH: usize = FONT_SET_END - FONT_SET_START;

const DATA_START: usize = 0x200;
const DATA_END: usize = 0xFFF;
const DATA_LENGTH: usize = DATA_END - DATA_START;

const MEM_LENGTH: usize = 4096;
const STACK_LEVEL: usize = 16;
const REG_NUM: usize = 16;
pub const GFX_WIDTH: usize = 64;
pub const GFX_HEIGHT: usize = 32;

const FONTSET: [u8; 80] = [
    0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
    0x20, 0x60, 0x20, 0x20, 0x70, // 1
    0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
    0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
    0x90, 0x90, 0xF0, 0x10, 0x10, // 4
    0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
    0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
    0xF0, 0x10, 0x20, 0x40, 0x40, // 7
    0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
    0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
    0xF0, 0x90, 0xF0, 0x90, 0x90, // A
    0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
    0xF0, 0x80, 0x80, 0x80, 0xF0, // C
    0xE0, 0x90, 0x90, 0x90, 0xE0, // D
    0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
    0xF0, 0x80, 0xF0, 0x80, 0x80  // F
];

pub fn init() -> Cpu {
    let mut ret = Cpu {
        pc: 0x200,
        opcode: 0,
        memory: vec![0; MEM_LENGTH],
        reg: vec![0; REG_NUM],
        index: 0,
        sp: 0,
        stack: vec![0; STACK_LEVEL],
        // gfx: vec![vec![0; GFX_HEIGHT]; GFX_WIDTH],
        gfx: vec![0; GFX_WIDTH * GFX_HEIGHT],
        delay_timer: 0,
        sound_timer: 0,
        key: vec![0; STACK_LEVEL],
    };
    ret.load_fontset();
    ret
}

#[derive(Debug, Clone)]
pub struct Cpu {
    pc: usize,
    opcode: u16,
    memory: Vec<u8>,
    reg: Vec<u8>,
    index: usize,
    // gfx: Vec<Vec<u8>>,
    gfx: Vec<u8>,
    delay_timer: u8,
    sound_timer: u8,
    stack: Vec<usize>,
    sp: usize,
    key: Vec<u8>,
}

impl Cpu {
    fn load_fontset(&mut self) {
        for i in 0..FONT_SET_LENGTH {
            self.memory[FONT_SET_START + i] = FONTSET[i];
        }
    }

    pub fn load_rom(&mut self, rom: Box<[u8]>) {
        for i in 0..rom.len() {
            self.memory[DATA_START + i] = rom[i];
        }
    }

    pub fn curr_pc(&mut self) -> usize {
        self.pc
    }

    pub fn curr_index(&mut self) -> usize {
        self.index
    }

    pub fn curr_opcode(&mut self) -> u16 {
        self.opcode
    }

    pub fn curr_regs(&mut self) -> Vec<u8> {
        self.clone().reg
    }

    pub fn curr_stack(&mut self) -> Vec<usize> {
        self.clone().stack
    }

    pub fn curr_sp(&mut self) -> usize {
        self.sp
    }

    pub fn curr_gfx(&mut self) -> Vec<u8> {
        self.clone().gfx
    }

    pub fn emulate_cycle(&mut self) {
        self.opcode = (self.memory[self.pc] as u16) << 8 | (self.memory[self.pc+1] as u16);

        match self.opcode & 0xF000 {
            0x0000 => {
                match self.opcode & 0x0F00 {
                    0x0000 => {
                        match self.opcode & 0x00FF {
                            0x00EE => { // 00EE: return from subroutine
                                self.sp -= 1;
                                self.pc = self.stack[self.sp];
                            },
                            0x00E0 => { // 00E0: clear screen
                                self.gfx = vec![0; GFX_HEIGHT *  GFX_WIDTH];
                                self.pc += 2;
                            },
                            _ => panic!("Unknown opcode or not implemented yet: {:X}", self.opcode)
                        }
                    },
                    _ => panic!("Unknown opcode or not implemented yet: {:X}", self.opcode)
                }
            },
            0x1000 => { // 1NNN: jump to NNN
                let addr = self.opcode & 0x0FFF;
                self.pc = addr as usize;
            },
            0x2000 => { // 2NNN: Calls subroutine at NNN
                let addr = self.opcode & 0x0FFF;
                self.stack[self.sp] = self.pc;
                self.sp += 1;
                self.pc = addr as usize;
            },
            0x3000 => { // 3XNN: skip next if VX == NN
                let x = (self.opcode & 0x0F00) >> 8;
                let nn = self.opcode & 0x00FF;
                if self.reg[x as usize] == nn as u8 {
                    self.pc += 4;
                } else {
                    self.pc += 2;
                }
            },
            0x4000 => { // 4XNN: skip next if VX != NN
                let x = (self.opcode & 0x0F00) >> 8;
                let nn = self.opcode & 0x00FF;
                if self.reg[x as usize] != nn as u8 {
                    self.pc += 4;
                } else {
                    self.pc += 2;
                }
            },
            0x6000 => { // 6XNN: Sets VX to NN
                let index = (self.opcode & 0x0F00) >> 8;
                let val = self.opcode & 0x00FF;
                self.reg[index as usize] = val as u8;
                self.pc += 2;
            },
            0x7000 => { // 7XNN: Adds NN to VX
                let x = (self.opcode & 0x0F00) >> 8;
                let nn = self.opcode & 0x00FF;
                self.reg[x as usize] += nn as u8;
                self.pc += 2;
            },
            0x8000 => {
                match self.opcode & 0x000F {
                    0x0000 => { // 8XY0: set VX to VY
                        let x = (self.opcode & 0x0F00) >> 8;
                        let y = (self.opcode & 0x00F0) >> 4;
                        self.reg[x as usize] = self.reg[y as usize];
                        self.pc += 2;
                    },
                    0x0002 => { // 8XY2: set VX to VX & VY
                        let x = (self.opcode & 0x0F00) >> 8;
                        let y = (self.opcode & 0x00F0) >> 4;
                        self.reg[x as usize] = self.reg[x as usize] & self.reg[y as usize];
                        self.reg[0xF] = 0;
                        self.pc += 2;
                    },
                    0x0004 => { // 8XY4: add VY to VX
                        let x = (self.opcode & 0x0F00) >> 8;
                        let y = (self.opcode & 0x00F0) >> 4;
                        let tmp = (self.reg[x as usize] as u16) + (self.reg[y as usize] as u16);
                        if tmp > 0x00FF {
                            self.reg[0xF] = 1;
                        } else {
                            self.reg[0xF] = 0;
                        }
                        self.reg[x as usize] = tmp as u8;
                        self.pc += 2;
                    },
                    _ => panic!("Unknown opcode or not implemented yet: {:X}", self.opcode)
                }
            },
            0xA000 => { // ANNN: Sets I to the address NNN
                let val = self.opcode & 0x0FFF;
                self.index = val as usize;
                self.pc += 2;
            },
            0xD000 => { // DXYN: Draws sprite at cordinate VX, VY with height N
                let x = (self.opcode & 0x0F00) >> 8;
                let y = (self.opcode & 0x00F0) >> 4;
                let n = self.opcode & 0x000F;
                let mut pix: u8;

                let tmp = self.index as usize;
                let sprite = &self.memory[tmp..(tmp + (n as usize))];

                self.reg[0xF] = 0;
                for i in 0..n {
                    pix = (&sprite)[i as usize];
                    for j in 0..8 {
                        if (pix & (0x80 >> j)) != 0 {
                            if self.gfx[(x + j + ((y + i) * 64)) as usize] == 1 {
                                self.reg[0xF] = 1;
                            }
                            self.gfx[(x + j + ((y + i) * 64)) as usize] ^= 1;
                        }
                    }
                }
                self.pc += 2;
            },
            0xF000 => {
                match self.opcode & 0x00FF {
                    0x001E => { // FX1E: add VX to I
                        let x = (self.opcode & 0x0F00) >> 8;
                        self.index += x as usize;
                        self.pc += 2;
                    },
                    0x0029 => { // FX29: set I to character sprite in VX
                        let x = (self.opcode & 0x0F00) >> 8;
                        let tmp = FONT_SET_START + ((self.reg[x as usize] * 5) as usize);
                        self.index = self.memory[tmp] as usize;
                        self.pc += 2;
                    },
                    0x0033 => { // FX33: set memory at I:I+2 to VX
                        let x = (self.opcode & 0x0F00) >> 8;
                        let val = self.reg[x as usize];
                        self.memory[self.index] = val / 100;
                        self.memory[self.index + 1] = (val / 10) % 10;
                        self.memory[self.index + 2] = val % 10;
                        self.pc += 2;
                    },
                    0x0065 => { // FX65: fill V0 to VX with values at I:I+X
                        let x = (self.opcode & 0x0F00) >> 8;
                        for i in 0..x {
                            self.reg[i as usize] = self.memory[self.index + (i as usize)];
                        }
                        self.pc += 2;
                    },
                    _ => panic!("Unknown opcode or not implemented yet: {:X}", self.opcode)
                }
            },
            _ => panic!("Unknown opcode or not implemented yet: {:X}", self.opcode)
        }

        if self.delay_timer > 0 {
            self.delay_timer -= 1;
        }
        if self.sound_timer > 0 {
            if self.sound_timer == 1 {
                println!("BEEP!");
            }
            self.sound_timer -= 1;
        }
    }
}
<commit_msg>Add opcode FX55 (set I:I+X to values in V0 to VX)<commit_after>const INTERPRETER_START: u32 = 0x000;
const INTERPRETER_END: u32 = 0x1FF;
const INTERPRETER_LENGTH: u32 = INTERPRETER_END - INTERPRETER_START;

const FONT_SET_START: usize = 0x050;
const FONT_SET_END: usize = 0x0A0;
const FONT_SET_LENGTH: usize = FONT_SET_END - FONT_SET_START;

const DATA_START: usize = 0x200;
const DATA_END: usize = 0xFFF;
const DATA_LENGTH: usize = DATA_END - DATA_START;

const MEM_LENGTH: usize = 4096;
const STACK_LEVEL: usize = 16;
const REG_NUM: usize = 16;
pub const GFX_WIDTH: usize = 64;
pub const GFX_HEIGHT: usize = 32;

const FONTSET: [u8; 80] = [
    0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
    0x20, 0x60, 0x20, 0x20, 0x70, // 1
    0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
    0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
    0x90, 0x90, 0xF0, 0x10, 0x10, // 4
    0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
    0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
    0xF0, 0x10, 0x20, 0x40, 0x40, // 7
    0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
    0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
    0xF0, 0x90, 0xF0, 0x90, 0x90, // A
    0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
    0xF0, 0x80, 0x80, 0x80, 0xF0, // C
    0xE0, 0x90, 0x90, 0x90, 0xE0, // D
    0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
    0xF0, 0x80, 0xF0, 0x80, 0x80  // F
];

pub fn init() -> Cpu {
    let mut ret = Cpu {
        pc: 0x200,
        opcode: 0,
        memory: vec![0; MEM_LENGTH],
        reg: vec![0; REG_NUM],
        index: 0,
        sp: 0,
        stack: vec![0; STACK_LEVEL],
        // gfx: vec![vec![0; GFX_HEIGHT]; GFX_WIDTH],
        gfx: vec![0; GFX_WIDTH * GFX_HEIGHT],
        delay_timer: 0,
        sound_timer: 0,
        key: vec![0; STACK_LEVEL],
    };
    ret.load_fontset();
    ret
}

#[derive(Debug, Clone)]
pub struct Cpu {
    pc: usize,
    opcode: u16,
    memory: Vec<u8>,
    reg: Vec<u8>,
    index: usize,
    // gfx: Vec<Vec<u8>>,
    gfx: Vec<u8>,
    delay_timer: u8,
    sound_timer: u8,
    stack: Vec<usize>,
    sp: usize,
    key: Vec<u8>,
}

impl Cpu {
    fn load_fontset(&mut self) {
        for i in 0..FONT_SET_LENGTH {
            self.memory[FONT_SET_START + i] = FONTSET[i];
        }
    }

    pub fn load_rom(&mut self, rom: Box<[u8]>) {
        for i in 0..rom.len() {
            self.memory[DATA_START + i] = rom[i];
        }
    }

    pub fn curr_pc(&mut self) -> usize {
        self.pc
    }

    pub fn curr_index(&mut self) -> usize {
        self.index
    }

    pub fn curr_opcode(&mut self) -> u16 {
        self.opcode
    }

    pub fn curr_regs(&mut self) -> Vec<u8> {
        self.clone().reg
    }

    pub fn curr_stack(&mut self) -> Vec<usize> {
        self.clone().stack
    }

    pub fn curr_sp(&mut self) -> usize {
        self.sp
    }

    pub fn curr_gfx(&mut self) -> Vec<u8> {
        self.clone().gfx
    }

    pub fn emulate_cycle(&mut self) {
        self.opcode = (self.memory[self.pc] as u16) << 8 | (self.memory[self.pc+1] as u16);

        match self.opcode & 0xF000 {
            0x0000 => {
                match self.opcode & 0x0F00 {
                    0x0000 => {
                        match self.opcode & 0x00FF {
                            0x00EE => { // 00EE: return from subroutine
                                self.sp -= 1;
                                self.pc = self.stack[self.sp];
                            },
                            0x00E0 => { // 00E0: clear screen
                                self.gfx = vec![0; GFX_HEIGHT *  GFX_WIDTH];
                                self.pc += 2;
                            },
                            _ => panic!("Unknown opcode or not implemented yet: {:X}", self.opcode)
                        }
                    },
                    _ => panic!("Unknown opcode or not implemented yet: {:X}", self.opcode)
                }
            },
            0x1000 => { // 1NNN: jump to NNN
                let addr = self.opcode & 0x0FFF;
                self.pc = addr as usize;
            },
            0x2000 => { // 2NNN: Calls subroutine at NNN
                let addr = self.opcode & 0x0FFF;
                self.stack[self.sp] = self.pc;
                self.sp += 1;
                self.pc = addr as usize;
            },
            0x3000 => { // 3XNN: skip next if VX == NN
                let x = (self.opcode & 0x0F00) >> 8;
                let nn = self.opcode & 0x00FF;
                if self.reg[x as usize] == nn as u8 {
                    self.pc += 4;
                } else {
                    self.pc += 2;
                }
            },
            0x4000 => { // 4XNN: skip next if VX != NN
                let x = (self.opcode & 0x0F00) >> 8;
                let nn = self.opcode & 0x00FF;
                if self.reg[x as usize] != nn as u8 {
                    self.pc += 4;
                } else {
                    self.pc += 2;
                }
            },
            0x6000 => { // 6XNN: Sets VX to NN
                let index = (self.opcode & 0x0F00) >> 8;
                let val = self.opcode & 0x00FF;
                self.reg[index as usize] = val as u8;
                self.pc += 2;
            },
            0x7000 => { // 7XNN: Adds NN to VX
                let x = (self.opcode & 0x0F00) >> 8;
                let nn = self.opcode & 0x00FF;
                self.reg[x as usize] += nn as u8;
                self.pc += 2;
            },
            0x8000 => {
                match self.opcode & 0x000F {
                    0x0000 => { // 8XY0: set VX to VY
                        let x = (self.opcode & 0x0F00) >> 8;
                        let y = (self.opcode & 0x00F0) >> 4;
                        self.reg[x as usize] = self.reg[y as usize];
                        self.pc += 2;
                    },
                    0x0002 => { // 8XY2: set VX to VX & VY
                        let x = (self.opcode & 0x0F00) >> 8;
                        let y = (self.opcode & 0x00F0) >> 4;
                        self.reg[x as usize] = self.reg[x as usize] & self.reg[y as usize];
                        self.reg[0xF] = 0;
                        self.pc += 2;
                    },
                    0x0004 => { // 8XY4: add VY to VX
                        let x = (self.opcode & 0x0F00) >> 8;
                        let y = (self.opcode & 0x00F0) >> 4;
                        let tmp = (self.reg[x as usize] as u16) + (self.reg[y as usize] as u16);
                        if tmp > 0x00FF {
                            self.reg[0xF] = 1;
                        } else {
                            self.reg[0xF] = 0;
                        }
                        self.reg[x as usize] = tmp as u8;
                        self.pc += 2;
                    },
                    _ => panic!("Unknown opcode or not implemented yet: {:X}", self.opcode)
                }
            },
            0xA000 => { // ANNN: Sets I to the address NNN
                let val = self.opcode & 0x0FFF;
                self.index = val as usize;
                self.pc += 2;
            },
            0xD000 => { // DXYN: Draws sprite at cordinate VX, VY with height N
                let x = (self.opcode & 0x0F00) >> 8;
                let y = (self.opcode & 0x00F0) >> 4;
                let n = self.opcode & 0x000F;
                let mut pix: u8;

                let tmp = self.index as usize;
                let sprite = &self.memory[tmp..(tmp + (n as usize))];

                self.reg[0xF] = 0;
                for i in 0..n {
                    pix = (&sprite)[i as usize];
                    for j in 0..8 {
                        if (pix & (0x80 >> j)) != 0 {
                            if self.gfx[(x + j + ((y + i) * 64)) as usize] == 1 {
                                self.reg[0xF] = 1;
                            }
                            self.gfx[(x + j + ((y + i) * 64)) as usize] ^= 1;
                        }
                    }
                }
                self.pc += 2;
            },
            0xF000 => {
                match self.opcode & 0x00FF {
                    0x001E => { // FX1E: add VX to I
                        let x = (self.opcode & 0x0F00) >> 8;
                        self.index += x as usize;
                        self.pc += 2;
                    },
                    0x0029 => { // FX29: set I to character sprite in VX
                        let x = (self.opcode & 0x0F00) >> 8;
                        let tmp = FONT_SET_START + ((self.reg[x as usize] * 5) as usize);
                        self.index = self.memory[tmp] as usize;
                        self.pc += 2;
                    },
                    0x0033 => { // FX33: set memory at I:I+2 to VX
                        let x = (self.opcode & 0x0F00) >> 8;
                        let val = self.reg[x as usize];
                        self.memory[self.index] = val / 100;
                        self.memory[self.index + 1] = (val / 10) % 10;
                        self.memory[self.index + 2] = val % 10;
                        self.pc += 2;
                    },
                    0x0055 => { // FX55: set I:I+X to values in V0 to VX
                        let x = (self.opcode & 0x0F00) >> 8;
                        for i in 0..x {
                            self.memory[self.index + (i as usize)] = self.reg[i as usize];
                        }
                        self.pc += 2;
                    },
                    0x0065 => { // FX65: fill V0 to VX with values at I:I+X
                        let x = (self.opcode & 0x0F00) >> 8;
                        for i in 0..x {
                            self.reg[i as usize] = self.memory[self.index + (i as usize)];
                        }
                        self.pc += 2;
                    },
                    _ => panic!("Unknown opcode or not implemented yet: {:X}", self.opcode)
                }
            },
            _ => panic!("Unknown opcode or not implemented yet: {:X}", self.opcode)
        }

        if self.delay_timer > 0 {
            self.delay_timer -= 1;
        }
        if self.sound_timer > 0 {
            if self.sound_timer == 1 {
                println!("BEEP!");
            }
            self.sound_timer -= 1;
        }
    }
}
<|endoftext|>


<commit_before>//! The Divide & Conquer recursive strategy.
//!
//! From [Wikipedia][1]:
//! > A divide and conquer algorithm works by recursively breaking down a
//! > problem into two or more sub-problems of the same (or related) type
//! > (**divide**) until these become simple enough to be solved directly
//! > (**conquer**). The solution to the sub-problems are then combined
//! > to give a solution to the original problem.
//!
//! To use this strategy you need to implement the [`DacProblem`][2] trait and
//! everything else is handled for you.
//!
//! [1]: https://en.wikipedia.org/wiki/Divide_and_conquer_algorithms
//! [2]: trait.DacProblem.html

use std::collections::HashMap;
use std::hash::Hash;
use std::marker::PhantomData;

/// Divide & Conquer Problem.
///
/// You have to implement this trait in order to use the algorithm. Simply fill
/// all the methods and you're all set. We have two generic types:
///
/// - `E`: A partial solution, wich we work with.
/// - `S`: The final solution, the output of the algorithm.
///
/// Sometimes `E` and `S` are the same type because we don't need conversion
/// between the partial and the final solution (e.g. when calculating a
/// factorial), but if we are working with a list or an array, `E` could simply
/// be a pointer to an element and `S` the actual element.
///
/// Once you have defined the problem, use [`DacAlgorithm`][1] or
/// [`DacMemAlgorithm`][2] to solve it.
///
/// [1]: struct.DacAlgorithm.html
/// [2]: struct.DacMemAlgorithm.html
pub trait DacProblem<S, E> {
    /// The size of your problem. Usually referred to as `n`.
    ///
    /// It should decrease as you split the problem, otherwise the algorithm
    /// will never stop, and we don't want that.
    fn size(&self) -> usize;

    /// The moment when the problem is simple enough to be solved directly.
    ///
    /// Here `DacProblem::size` is the smallest.
    fn is_base_case(&self) -> bool;

    /// The base case's solution.
    fn base_case_solution(&self) -> E;

    /// The number of subproblems the problem has.
    fn subproblem_count(&self) -> usize;

    /// Return the subproblem corresponding to the given `i`. (i.e. the first
    /// subproblem, the second...).
    ///
    /// `i` is in the range [0, `DacProblem::subproblem_count`).
    fn get_subproblem(&self, i: usize) -> Self;

    /// How to combine the subproblems' solutions into the current problem's
    /// solution.
    fn combine(&self, solutions: Vec<E>) -> E;

    /// Transforms the partial solution `E`, if it is possible, into a final
    /// solution `S`.
    fn get_solution(&self, partial_solution: &E) -> Option<S>;
}

/// The problem solver.
///
/// Solves a divide & conquer problem without memory. Useful if we don't need
/// to store partial solutions.
pub struct DacAlgorithm<P, S, E>
    where P: DacProblem<S, E>
{
    phan: PhantomData<S>,
    partial_solution: E,
    problem: P,
}

impl<P, S, E> DacAlgorithm<P, S, E>
    where P: DacProblem<S, E>
{
    /// Solve the `problem` problem.
    pub fn new(problem: P) -> Self {
        let e = Self::solve(&problem);

        DacAlgorithm {
            phan: PhantomData,
            partial_solution: e,
            problem: problem,
        }
    }

    fn solve(problem: &P) -> E {
        if problem.is_base_case() {
            problem.base_case_solution()

        } else {
            let solutions = (0..problem.subproblem_count())
                                .map(|i| problem.get_subproblem(i))
                                .map(|p| Self::solve(&p))
                                .collect::<Vec<E>>();

            problem.combine(solutions)
        }
    }

    /// Get the final solution.
    pub fn get_solution(&self) -> Option<S> {
        self.problem.get_solution(&self.partial_solution)
    }
}

/// The problem solver, with memory.
///
/// # Explanation
///
/// Solves a divide & conquer problem with memory: it stores the partial
/// solutions of all the subproblems, in case they are needed by another
/// subproblem. An usual example is the [Fibonacci sequence][1]:
///
///     fn fib(n: u64) -> u64 {
///         match n {
///             0 => 0,
///             1 => 1,
///             n => fib(n - 1) + fib(n - 2),
///         }
///     }
///
/// As you can see, `fib(5)` needs `fib(4)` and `fib(3)`. But then `fib(4)` also
/// needs `fib(3)`. Memory here is useful so we don't recalculate values.
///
/// # Usage
///
/// Using this is the same as using [`DacAlgorithm`][2] but you problem has to
/// implement some traits:
///
/// - `DacProblem` has to implement the following traits:
///     - `Eq` (and therefore `PartialEq`)
///     - `Hash`
///     - `Clone`
/// - `E` has to be `Clone` too.
///
/// Which is not complicated to do:
///
///     #[derive(Eq, PartialEq, Hash, Clone)]
///     struct Fibonacci(u64);
///
/// [1]: https://en.wikipedia.org/wiki/Fibonacci_number
/// [2]: struct.DacAlgorithm.html#usage
pub struct DacMemAlgorithm<P, S, E>
    where P: DacProblem<S, E> + Eq + Hash + Clone,
          E: Clone
{
    phan: PhantomData<S>,
    solutions: HashMap<P, E>,
    problem: P,
}

impl<P, S, E> DacMemAlgorithm<P, S, E>
    where P: DacProblem<S, E> + Eq + Hash + Clone,
          E: Clone
{
    pub fn new(problem: P) -> Self {
        let mut map = HashMap::new();
        Self::solve(&problem, &mut map);

        DacMemAlgorithm {
            phan: PhantomData,
            solutions: map,
            problem: problem,
        }
    }

    fn solve(problem: &P, mut solutions: &mut HashMap<P, E>) -> E {
        if problem.is_base_case() {
            problem.base_case_solution()

        } else if solutions.contains_key(&problem) {
            solutions.get(&problem).unwrap().clone()

        } else {
            let solution = {
                let solutions = (0..problem.subproblem_count())
                                    .map(|i| problem.get_subproblem(i))
                                    .map(|p| Self::solve(&p, &mut solutions))
                                    .collect::<Vec<E>>();

                problem.combine(solutions)
            };

            solutions.insert(problem.clone(), solution);
            solutions.get(&problem).unwrap().clone()
        }
    }

    pub fn get_solution(&self) -> Option<S> {
        self.solutions
            .get(&self.problem)
            .and_then(|e| self.problem.get_solution(e))
    }
}
<commit_msg>Change fibonacci example<commit_after>//! The Divide & Conquer recursive strategy.
//!
//! From [Wikipedia][1]:
//! > A divide and conquer algorithm works by recursively breaking down a
//! > problem into two or more sub-problems of the same (or related) type
//! > (**divide**) until these become simple enough to be solved directly
//! > (**conquer**). The solution to the sub-problems are then combined
//! > to give a solution to the original problem.
//!
//! To use this strategy you need to implement the [`DacProblem`][2] trait and
//! everything else is handled for you.
//!
//! [1]: https://en.wikipedia.org/wiki/Divide_and_conquer_algorithms
//! [2]: trait.DacProblem.html

use std::collections::HashMap;
use std::hash::Hash;
use std::marker::PhantomData;

/// Divide & Conquer Problem.
///
/// You have to implement this trait in order to use the algorithm. Simply fill
/// all the methods and you're all set. We have two generic types:
///
/// - `E`: A partial solution, wich we work with.
/// - `S`: The final solution, the output of the algorithm.
///
/// Sometimes `E` and `S` are the same type because we don't need conversion
/// between the partial and the final solution (e.g. when calculating a
/// factorial), but if we are working with a list or an array, `E` could simply
/// be a pointer to an element and `S` the actual element.
///
/// Once you have defined the problem, use [`DacAlgorithm`][1] or
/// [`DacMemAlgorithm`][2] to solve it.
///
/// [1]: struct.DacAlgorithm.html
/// [2]: struct.DacMemAlgorithm.html
pub trait DacProblem<S, E> {
    /// The size of your problem. Usually referred to as `n`.
    ///
    /// It should decrease as you split the problem, otherwise the algorithm
    /// will never stop, and we don't want that.
    fn size(&self) -> usize;

    /// The moment when the problem is simple enough to be solved directly.
    ///
    /// Here `DacProblem::size` is the smallest.
    fn is_base_case(&self) -> bool;

    /// The base case's solution.
    fn base_case_solution(&self) -> E;

    /// The number of subproblems the problem has.
    fn subproblem_count(&self) -> usize;

    /// Return the subproblem corresponding to the given `i`. (i.e. the first
    /// subproblem, the second...).
    ///
    /// `i` is in the range [0, `DacProblem::subproblem_count`).
    fn get_subproblem(&self, i: usize) -> Self;

    /// How to combine the subproblems' solutions into the current problem's
    /// solution.
    fn combine(&self, solutions: Vec<E>) -> E;

    /// Transforms the partial solution `E`, if it is possible, into a final
    /// solution `S`.
    fn get_solution(&self, partial_solution: &E) -> Option<S>;
}

/// The problem solver.
///
/// Solves a divide & conquer problem without memory. Useful if we don't need
/// to store partial solutions.
pub struct DacAlgorithm<P, S, E>
    where P: DacProblem<S, E>
{
    phan: PhantomData<S>,
    partial_solution: E,
    problem: P,
}

impl<P, S, E> DacAlgorithm<P, S, E>
    where P: DacProblem<S, E>
{
    /// Solve the `problem` problem.
    pub fn new(problem: P) -> Self {
        let e = Self::solve(&problem);

        DacAlgorithm {
            phan: PhantomData,
            partial_solution: e,
            problem: problem,
        }
    }

    fn solve(problem: &P) -> E {
        if problem.is_base_case() {
            problem.base_case_solution()

        } else {
            let solutions = (0..problem.subproblem_count())
                                .map(|i| problem.get_subproblem(i))
                                .map(|p| Self::solve(&p))
                                .collect::<Vec<E>>();

            problem.combine(solutions)
        }
    }

    /// Get the final solution.
    pub fn get_solution(&self) -> Option<S> {
        self.problem.get_solution(&self.partial_solution)
    }
}

/// The problem solver, with memory.
///
/// # Explanation
///
/// Solves a divide & conquer problem with memory: it stores the partial
/// solutions of all the subproblems, in case they are needed by another
/// subproblem. An usual example is the [Fibonacci sequence][1]:
///
/// ``` text
/// fib(0) = 0
/// fib(1) = 1
/// fib(n) = fib(n - 1) + fib(n - 2)
/// ```
///
/// As you can see, `fib(5)` needs `fib(4)` and `fib(3)`. But then `fib(4)` also
/// needs `fib(3)`. Memory here is useful so we don't recalculate values.
///
/// # Usage
///
/// Using this is the same as using [`DacAlgorithm`][2] but you problem has to
/// implement some traits:
///
/// - `DacProblem` has to implement the following traits:
///     - `Eq` (and therefore `PartialEq`)
///     - `Hash`
///     - `Clone`
/// - `E` has to be `Clone` too.
///
/// Which is not complicated to do:
///
///     #[derive(Eq, PartialEq, Hash, Clone)]
///     struct Fibonacci(u64);
///
/// [1]: https://en.wikipedia.org/wiki/Fibonacci_number
/// [2]: struct.DacAlgorithm.html#usage
pub struct DacMemAlgorithm<P, S, E>
    where P: DacProblem<S, E> + Eq + Hash + Clone,
          E: Clone
{
    phan: PhantomData<S>,
    solutions: HashMap<P, E>,
    problem: P,
}

impl<P, S, E> DacMemAlgorithm<P, S, E>
    where P: DacProblem<S, E> + Eq + Hash + Clone,
          E: Clone
{
    pub fn new(problem: P) -> Self {
        let mut map = HashMap::new();
        Self::solve(&problem, &mut map);

        DacMemAlgorithm {
            phan: PhantomData,
            solutions: map,
            problem: problem,
        }
    }

    fn solve(problem: &P, mut solutions: &mut HashMap<P, E>) -> E {
        if problem.is_base_case() {
            problem.base_case_solution()

        } else if solutions.contains_key(&problem) {
            solutions.get(&problem).unwrap().clone()

        } else {
            let solution = {
                let solutions = (0..problem.subproblem_count())
                                    .map(|i| problem.get_subproblem(i))
                                    .map(|p| Self::solve(&p, &mut solutions))
                                    .collect::<Vec<E>>();

                problem.combine(solutions)
            };

            solutions.insert(problem.clone(), solution);
            solutions.get(&problem).unwrap().clone()
        }
    }

    pub fn get_solution(&self) -> Option<S> {
        self.solutions
            .get(&self.problem)
            .and_then(|e| self.problem.get_solution(e))
    }
}
<|endoftext|>