<commit_before>use desync::scheduler::*;

use super::timeout::*;

use std::thread;
use std::time::*;
use std::sync::*;
use std::sync::mpsc::*;

use futures::prelude::*;
use futures::task;
use futures::task::{ArcWake, Poll};
use futures::channel::oneshot;

#[test]
fn schedule_future() {
    timeout(|| {
        use futures::executor;

        let queue       = queue();
        let future      = future_sync(&queue, move || async {
            thread::sleep(Duration::from_millis(100));
            42
        });

        executor::block_on(async {
            assert!(future.await.unwrap() == 42);
        });
    }, 500);
}

#[test]
fn schedule_future_with_no_scheduler_threads() {
    timeout(|| {
        use futures::executor;

        let scheduler   = Scheduler::new();

        // Even with 0 threads, futures should still run (by draining on the current thread as for sync actions)
        scheduler.set_max_threads(0);
        scheduler.despawn_threads_if_overloaded();

        let queue       = queue();
        let future      = scheduler.future_sync(&queue, move || async {
            thread::sleep(Duration::from_millis(100));
            42
        });

        executor::block_on(async {
            assert!(future.await.unwrap() == 42);
        });
    }, 500);
}

#[test]
fn wake_future_with_no_scheduler_threads() {
    timeout(|| {
        use futures::executor;

        let (tx, rx)    = oneshot::channel::<i32>();
        let scheduler   = Scheduler::new();

        // Even with 0 threads, futures should still run (by draining on the current thread as for sync actions)
        scheduler.set_max_threads(0);
        scheduler.despawn_threads_if_overloaded();

        // Schedule a future that will block until we send a value
        let queue       = queue();
        let future      = scheduler.future_sync(&queue, move || async {
            rx.await.expect("Receive result")
        });

        // Schedule a thread that will send a value
        thread::spawn(move || {
            // Wait for a bit before sending the result so the future should block
            thread::sleep(Duration::from_millis(100));

            tx.send(42).expect("Send")
        });

        executor::block_on(async {
            assert!(future.await.expect("result") == 42);
        });
    }, 500);
}

#[test]
fn wait_for_future() {
    timeout(|| {
        use futures::executor;

        // We use a oneshot as our future, and a mpsc channel to track progress
        let (tx, rx)                = channel();
        let (future_tx, future_rx)  = oneshot::channel();

        let scheduler   = scheduler();
        let queue       = queue();

        // Start by sending '1' from an async
        let tx2 = tx.clone();
        desync(&queue, move || { tx2.send(1).unwrap(); });

        // Then send the value sent via our oneshot using a future
        let tx2 = tx.clone();
        let future = scheduler.after(&queue, future_rx,
            move |val| val.map(move |val| { tx2.send(val).unwrap(); 4 }));

        // Then send '3'
        let tx2 = tx.clone();
        desync(&queue, move || { tx2.send(3).unwrap(); });

        // '1' should be available, but we should otherwise be blocked on the future
        assert!(rx.recv().unwrap() == 1);
        assert!(rx.recv_timeout(Duration::from_millis(100)).is_err());

        // Send '2' to the future
        future_tx.send(2).unwrap();

        executor::block_on(async {
            // Future should resolve to 4
            assert!(future.await.unwrap() == Ok(4));

            // Should receive the '2' from the future, then 3
            assert!(rx.recv_timeout(Duration::from_millis(100)).unwrap() == 2);
            assert!(rx.recv().unwrap() == 3);
        });
    }, 500);
}

#[test]
fn future_waits_for_us() {
    timeout(|| {
        use futures::executor;

        // We use a oneshot as our future, and a mpsc channel to track progress
        let (tx, rx)                = channel();
        let (future_tx, future_rx)  = oneshot::channel();

        let scheduler   = scheduler();
        let queue       = queue();

        // Start by sending '1' from an async
        let tx2 = tx.clone();
        desync(&queue, move || { thread::sleep(Duration::from_millis(100)); tx2.send(1).unwrap(); });

        // Then send the value sent via our oneshot using a future
        let tx2 = tx.clone();
        let future = scheduler.after(&queue, future_rx,
            move |val| val.map(move |val| { tx2.send(val).unwrap(); 4 }));

        // Then send '3'
        let tx2 = tx.clone();
        desync(&queue, move || { tx2.send(3).unwrap(); });

        // Send '2' to the future
        future_tx.send(2).unwrap();

        executor::block_on(async {
            // Future should resolve to 4
            assert!(future.await.unwrap() == Ok(4));

            // '1' should be available first
            assert!(rx.recv().unwrap() == 1);

            // Should receive the '2' from the future, then 3
            assert!(rx.recv_timeout(Duration::from_millis(100)).unwrap() == 2);
            assert!(rx.recv().unwrap() == 3);
        });
    }, 500);
}

///
/// Used for polling futures to see if they've notified us yet
///
struct TestWaker {
    pub awake: Mutex<bool>
}

impl ArcWake for TestWaker {
    fn wake_by_ref(arc_self: &Arc<Self>) {
        (*arc_self.awake.lock().unwrap()) = true;
    }
}

#[test]
fn poll_two_futures_on_one_queue() {
    // 0 threads so we force the future to act in 'drain' mode
    let scheduler   = Scheduler::new();

    // Even with 0 threads, futures should still run (by draining on the current thread as for sync actions)
    scheduler.set_max_threads(0);
    scheduler.despawn_threads_if_overloaded();

    // If a single queue has a future on
    let queue           = queue();
    let (done1, recv1)  = oneshot::channel::<()>();
    let (done2, recv2)  = oneshot::channel::<()>();

    let wake1           = Arc::new(TestWaker { awake: Mutex::new(false) });
    let wake2           = Arc::new(TestWaker { awake: Mutex::new(false) });

    // Wait for done1 then done2 to signal
    let mut future_1    = scheduler.future_sync(&queue, move || {
        async move { recv1.await.ok(); }
    });

    let mut future_2    = scheduler.future_sync(&queue, move || {
        async move { recv2.await.ok(); }
    });

    // Poll future 1 then future 2 (as there are no threads to run, we'll use the 'drain on current thread' style, which will return pending as recv is pending)
    let waker_ref           = task::waker_ref(&wake1);
    let mut ctxt            = task::Context::from_waker(&waker_ref);

    assert!(future_1.poll_unpin(&mut ctxt) == Poll::Pending);

    // Only future_1 should be 'pollable' at this point (ie, is in the WaitForPoll state from the previous call)
    let waker_ref           = task::waker_ref(&wake2);
    let mut ctxt            = task::Context::from_waker(&waker_ref);

    assert!(future_2.poll_unpin(&mut ctxt) == Poll::Pending);

    // Finish both futures
    done1.send(()).unwrap();

    let waker_ref           = task::waker_ref(&wake2);
    let mut ctxt            = task::Context::from_waker(&waker_ref);

    // Poll the other future: it should be pending as it's waiting to be scheduled
    assert!(future_2.poll_unpin(&mut ctxt) == Poll::Pending);

    done2.send(()).unwrap();

    // future_1 should be signalled for polling, future_2 should not (as it can't start until future_1 is finished)
    assert!((*wake2.awake.lock().unwrap()) == false);
    assert!((*wake1.awake.lock().unwrap()) == true);

    // Retrieve the result for future_1
    let waker_ref           = task::waker_ref(&wake1);
    let mut ctxt            = task::Context::from_waker(&waker_ref);

    assert!(future_1.poll_unpin(&mut ctxt) == Poll::Ready(Ok(())));

    // Both future 1 and future 2 should have signalled now

    // TODO: this is a possible bug with 0 threads - the thread won't reschedule after future_1 completes, so wake2 will not yet be set
    //          (This is quite a complicated problem: if the drain continued processing jobs until it became pending instead of scheduling
    //          in the background, this would work but the return from poll could be delayed indefinitely)
    // assert!((*wake2.awake.lock().unwrap()) == true);

    // Give the scheduler a chance to run the other future (it will be queued in the background, so this is required for the notification to occur)
    scheduler.set_max_threads(1);
    for _ in 0..100 {
        if *wake2.awake.lock().unwrap() { break; }
        thread::sleep(Duration::from_millis(1));
    }
    assert!((*wake2.awake.lock().unwrap()) == true);

    let waker_ref           = task::waker_ref(&wake2);
    let mut ctxt            = task::Context::from_waker(&waker_ref);

    // Should be able to retrieve the result of future_2
    assert!(future_2.poll_unpin(&mut ctxt) == Poll::Ready(Ok(())));

    // TODO: not actually sure if this is bad behaviour or not but if future_2 is polled first, future_1 won't be available until future_2
    //      completes. This is another 0 thread only issue as future_1 will be able to send its notification when the thread pool is available.
}
<commit_msg>We need to be able to await sync and desync futures from each other, but there's a bad state transition somewhere and their queues stop getting scheduled<commit_after>use desync::scheduler::*;

use super::timeout::*;

use std::thread;
use std::time::*;
use std::sync::*;
use std::sync::mpsc::*;

use futures::prelude::*;
use futures::task;
use futures::task::{ArcWake, Poll};
use futures::channel::oneshot;

#[test]
fn schedule_future() {
    timeout(|| {
        use futures::executor;

        let queue       = queue();
        let future      = future_sync(&queue, move || async {
            thread::sleep(Duration::from_millis(100));
            42
        });

        executor::block_on(async {
            assert!(future.await.unwrap() == 42);
        });
    }, 500);
}

#[test]
fn schedule_future_with_no_scheduler_threads() {
    timeout(|| {
        use futures::executor;

        let scheduler   = Scheduler::new();

        // Even with 0 threads, futures should still run (by draining on the current thread as for sync actions)
        scheduler.set_max_threads(0);
        scheduler.despawn_threads_if_overloaded();

        let queue       = queue();
        let future      = scheduler.future_sync(&queue, move || async {
            thread::sleep(Duration::from_millis(100));
            42
        });

        executor::block_on(async {
            assert!(future.await.unwrap() == 42);
        });
    }, 500);
}

#[test]
fn wake_future_with_no_scheduler_threads() {
    timeout(|| {
        use futures::executor;

        let (tx, rx)    = oneshot::channel::<i32>();
        let scheduler   = Scheduler::new();

        // Even with 0 threads, futures should still run (by draining on the current thread as for sync actions)
        scheduler.set_max_threads(0);
        scheduler.despawn_threads_if_overloaded();

        // Schedule a future that will block until we send a value
        let queue       = queue();
        let future      = scheduler.future_sync(&queue, move || async {
            rx.await.expect("Receive result")
        });

        // Schedule a thread that will send a value
        thread::spawn(move || {
            // Wait for a bit before sending the result so the future should block
            thread::sleep(Duration::from_millis(100));

            tx.send(42).expect("Send")
        });

        executor::block_on(async {
            assert!(future.await.expect("result") == 42);
        });
    }, 500);
}

#[test]
fn wait_for_future() {
    timeout(|| {
        use futures::executor;

        // We use a oneshot as our future, and a mpsc channel to track progress
        let (tx, rx)                = channel();
        let (future_tx, future_rx)  = oneshot::channel();

        let scheduler   = scheduler();
        let queue       = queue();

        // Start by sending '1' from an async
        let tx2 = tx.clone();
        desync(&queue, move || { tx2.send(1).unwrap(); });

        // Then send the value sent via our oneshot using a future
        let tx2 = tx.clone();
        let future = scheduler.after(&queue, future_rx,
            move |val| val.map(move |val| { tx2.send(val).unwrap(); 4 }));

        // Then send '3'
        let tx2 = tx.clone();
        desync(&queue, move || { tx2.send(3).unwrap(); });

        // '1' should be available, but we should otherwise be blocked on the future
        assert!(rx.recv().unwrap() == 1);
        assert!(rx.recv_timeout(Duration::from_millis(100)).is_err());

        // Send '2' to the future
        future_tx.send(2).unwrap();

        executor::block_on(async {
            // Future should resolve to 4
            assert!(future.await.unwrap() == Ok(4));

            // Should receive the '2' from the future, then 3
            assert!(rx.recv_timeout(Duration::from_millis(100)).unwrap() == 2);
            assert!(rx.recv().unwrap() == 3);
        });
    }, 500);
}

#[test]
fn future_waits_for_us() {
    timeout(|| {
        use futures::executor;

        // We use a oneshot as our future, and a mpsc channel to track progress
        let (tx, rx)                = channel();
        let (future_tx, future_rx)  = oneshot::channel();

        let scheduler   = scheduler();
        let queue       = queue();

        // Start by sending '1' from an async
        let tx2 = tx.clone();
        desync(&queue, move || { thread::sleep(Duration::from_millis(100)); tx2.send(1).unwrap(); });

        // Then send the value sent via our oneshot using a future
        let tx2 = tx.clone();
        let future = scheduler.after(&queue, future_rx,
            move |val| val.map(move |val| { tx2.send(val).unwrap(); 4 }));

        // Then send '3'
        let tx2 = tx.clone();
        desync(&queue, move || { tx2.send(3).unwrap(); });

        // Send '2' to the future
        future_tx.send(2).unwrap();

        executor::block_on(async {
            // Future should resolve to 4
            assert!(future.await.unwrap() == Ok(4));

            // '1' should be available first
            assert!(rx.recv().unwrap() == 1);

            // Should receive the '2' from the future, then 3
            assert!(rx.recv_timeout(Duration::from_millis(100)).unwrap() == 2);
            assert!(rx.recv().unwrap() == 3);
        });
    }, 500);
}

///
/// Used for polling futures to see if they've notified us yet
///
struct TestWaker {
    pub awake: Mutex<bool>
}

impl ArcWake for TestWaker {
    fn wake_by_ref(arc_self: &Arc<Self>) {
        (*arc_self.awake.lock().unwrap()) = true;
    }
}

#[test]
fn wait_for_sync_future_from_desync_future() {
    use futures::executor;

    timeout(|| {
        // This reproduces a deadlock due to a race condition, so we usually need several iterations through the test before the issue will occur
        for _i in 0..1000 {
            // We'll schedule a sync future on queue1, and wait for it from a desync future on queue2
            let queue1      = queue();
            let queue2      = queue();

            // Oneshot channel to wake the sync queue
            let (done1, recv1)  = oneshot::channel::<()>();

            let sync_future     = future_sync(&queue1, move || { async move { recv1.await.ok(); } });
            let desync_future   = future_desync(&queue2, move || { async move { sync_future.await.ok(); } });

            // Signal
            done1.send(()).unwrap();

            // Wait for the desync future in an executor
            executor::block_on(async move {
                desync_future.await.ok();
            });

            // Run sync on both queues
            sync(&queue1, move || { });
            sync(&queue2, move || { });
        }
    }, 5000);
}

#[test]
fn wait_for_desync_future_from_sync_future() {
    use futures::executor;

    timeout(|| {
        // This reproduces a deadlock due to a race condition, so we usually need several iterations through the test before the issue will occur
        for _i in 0..1000 {
            // We'll schedule a sync future on queue1, and wait for it from a desync future on queue2
            let queue1      = queue();
            let queue2      = queue();

            // Oneshot channel to wake the sync queue
            let (done1, recv1)  = oneshot::channel::<()>();

            let desync_future   = future_desync(&queue1, move || { async move { recv1.await.ok(); } });
            let sync_future     = future_sync(&queue2, move || { async move { desync_future.await.ok(); } });

            // Signal
            done1.send(()).unwrap();

            // Wait for the desync future in an executor
            executor::block_on(async move {
                sync_future.await.ok();
            });

            // Run sync on both queues
            sync(&queue1, move || { });
            sync(&queue2, move || { });
        }
    }, 5000);
}

#[test]
fn poll_two_futures_on_one_queue() {
    // 0 threads so we force the future to act in 'drain' mode
    let scheduler   = Scheduler::new();

    // Even with 0 threads, futures should still run (by draining on the current thread as for sync actions)
    scheduler.set_max_threads(0);
    scheduler.despawn_threads_if_overloaded();

    // If a single queue has a future on
    let queue           = queue();
    let (done1, recv1)  = oneshot::channel::<()>();
    let (done2, recv2)  = oneshot::channel::<()>();

    let wake1           = Arc::new(TestWaker { awake: Mutex::new(false) });
    let wake2           = Arc::new(TestWaker { awake: Mutex::new(false) });

    // Wait for done1 then done2 to signal
    let mut future_1    = scheduler.future_sync(&queue, move || {
        async move { recv1.await.ok(); }
    });

    let mut future_2    = scheduler.future_sync(&queue, move || {
        async move { recv2.await.ok(); }
    });

    // Poll future 1 then future 2 (as there are no threads to run, we'll use the 'drain on current thread' style, which will return pending as recv is pending)
    let waker_ref           = task::waker_ref(&wake1);
    let mut ctxt            = task::Context::from_waker(&waker_ref);

    assert!(future_1.poll_unpin(&mut ctxt) == Poll::Pending);

    // Only future_1 should be 'pollable' at this point (ie, is in the WaitForPoll state from the previous call)
    let waker_ref           = task::waker_ref(&wake2);
    let mut ctxt            = task::Context::from_waker(&waker_ref);

    assert!(future_2.poll_unpin(&mut ctxt) == Poll::Pending);

    // Finish both futures
    done1.send(()).unwrap();

    let waker_ref           = task::waker_ref(&wake2);
    let mut ctxt            = task::Context::from_waker(&waker_ref);

    // Poll the other future: it should be pending as it's waiting to be scheduled
    assert!(future_2.poll_unpin(&mut ctxt) == Poll::Pending);

    done2.send(()).unwrap();

    // future_1 should be signalled for polling, future_2 should not (as it can't start until future_1 is finished)
    assert!((*wake2.awake.lock().unwrap()) == false);
    assert!((*wake1.awake.lock().unwrap()) == true);

    // Retrieve the result for future_1
    let waker_ref           = task::waker_ref(&wake1);
    let mut ctxt            = task::Context::from_waker(&waker_ref);

    assert!(future_1.poll_unpin(&mut ctxt) == Poll::Ready(Ok(())));

    // Both future 1 and future 2 should have signalled now

    // TODO: this is a possible bug with 0 threads - the thread won't reschedule after future_1 completes, so wake2 will not yet be set
    //          (This is quite a complicated problem: if the drain continued processing jobs until it became pending instead of scheduling
    //          in the background, this would work but the return from poll could be delayed indefinitely)
    // assert!((*wake2.awake.lock().unwrap()) == true);

    // Give the scheduler a chance to run the other future (it will be queued in the background, so this is required for the notification to occur)
    scheduler.set_max_threads(1);
    for _ in 0..100 {
        if *wake2.awake.lock().unwrap() { break; }
        thread::sleep(Duration::from_millis(1));
    }
    assert!((*wake2.awake.lock().unwrap()) == true);

    let waker_ref           = task::waker_ref(&wake2);
    let mut ctxt            = task::Context::from_waker(&waker_ref);

    // Should be able to retrieve the result of future_2
    assert!(future_2.poll_unpin(&mut ctxt) == Poll::Ready(Ok(())));

    // TODO: not actually sure if this is bad behaviour or not but if future_2 is polled first, future_1 won't be available until future_2
    //      completes. This is another 0 thread only issue as future_1 will be able to send its notification when the thread pool is available.
}
<|endoftext|>


<commit_before>use std::old_io;
use cell::CellStatus;
use grid::Grid;
use cell::Cell;
use cell::PositionWeight;

pub struct Player {
	pub name: String,
	pub cell_code: CellStatus,
	pub player_type: PlayerType,
	pub played_cells: Vec<Cell>,
	pub path_cells: Vec<Cell>
}

pub enum PlayerType {
	RandomAI,
	PathAI,
	MindPathAI,
	ButeforceAI,
	Human
}

impl Player {
	pub fn new(num: u8, grid_length: u8) -> Player {
		let possibilities: u16 = match num {
			1 if grid_length % 2 != 0 => {
				(grid_length*grid_length + 1) as u16
			},
			_ => {
				(grid_length*grid_length) as u16
			}
		};grid_length as u16 * grid_length as u16;
		println!("Please, give us a name for player {}", num);

		let mut stdin = old_io::stdin();
		let grid_input = stdin.lock().lines().next().unwrap().ok().unwrap();
		let name = grid_input.trim();

		let player_type: PlayerType;
		loop {
			println!("{} will be [h]uman, [r]andom IA, [p]ath IA, [m]ind path IA, [b]ruteforce IA ?", name);
			let grid_input = stdin.lock().lines().next().unwrap().ok().unwrap();
			match grid_input.trim() {
					"h" => { player_type = PlayerType::Human; break; },
					"p" => { player_type = PlayerType::PathAI; break;},
					"m" => { player_type = PlayerType::MindPathAI; break;},
					"r" => { player_type = PlayerType::RandomAI; break;},
					"b" => { player_type = PlayerType::ButeforceAI; break;}
					_ => {continue;}
				};
		};

		return Player {
			name: (*name).to_string(),
			cell_code: CellStatus::get_color_for_player(num),
			player_type: player_type,
			played_cells: Vec::with_capacity(possibilities as usize),
			path_cells: Vec::new()
		};
	}

	pub fn inverse(&self) -> CellStatus {
		return match self.cell_code {
			CellStatus::Black => CellStatus::White,
			CellStatus::White => CellStatus::Black,
			_ => panic!("Bad player color")
		}
	}

	pub fn get_next_PathAI_move(&self, grid: &Grid) -> Option<[u8; 2]> {
		use std::rand;
		use std::rand::Rng;
		if grid.count_for_player(self) == 0 {
			let aleat: u8 = rand::thread_rng().gen_range(1, grid.length-1);
			if self.cell_code == CellStatus::White {
				return Some([aleat, 0]);
			} else {
				return Some([0, aleat]);
			}
		}
		let available_moves = self.played_cells.last().unwrap().get_available_close_random_uniq_weight(grid, None);
		if available_moves.len() < 1 {
			return None;
		}
		let next = available_moves[0];
		return Some([next.x, next.y]);
	}

	pub fn init_path_cells(&mut self, grid: &Grid) {
		use std::rand;
		use std::rand::Rng;
		let aleat: u8 = rand::thread_rng().gen_range(1, grid.length-1);
		if self.cell_code == CellStatus::White {
			self.path_cells.push(*grid.get_cell([aleat, 0]));
		} else {
			self.path_cells.push(*grid.get_cell([0, aleat]));
		}
		while !self.path_cells.last().unwrap().is_a_goal(&self, grid) {
			let next = self.path_cells.last().unwrap().get_available_close_random_uniq_weight(grid, Some(self.cell_code))[0];
			self.path_cells.push(next);
		}
	}

	pub fn update_path_data(&mut self, grid: &Grid) {
		let temp_vector: Vec<Cell> = self.path_cells.clone();
		self.path_cells = Vec::with_capacity(temp_vector.len());
		for cell in temp_vector.iter() {
			self.path_cells.push(*grid.get_cell([cell.x, cell.y]));
		}

	}

	pub fn path_must_be_recalc(&self) -> bool {
		for cell in self.path_cells.iter() {
			if cell.status == self.inverse() {
				return true;
			}
		}
		return false;
	}

	pub fn recalc_path(&mut self, grid: &Grid) {
		let mut i = 0;
		let mut new_path: Vec<Cell> = Vec::new();
		for cell in self.path_cells.iter() {
			if cell.status != CellStatus::Empty && cell.status != self.cell_code {
				break;
			}
			new_path.push(*cell);
		}
		loop {
			let mut to_ignore: Vec<[u8;2 ]> = Vec::new();
			let last_coord: [u8; 2] = match new_path.clone().last() {
				Some(x) => { [x.x, x.y] },
				None => {
					use std::rand;
					use std::rand::Rng;
					let aleat: u8 = rand::thread_rng().gen_range(1, grid.length-1);
					if self.cell_code == CellStatus::White {
						new_path.push(*grid.get_cell([aleat, 0]));
						[aleat, 0]
					} else {
						new_path.push(*grid.get_cell([0, aleat]));
						[0, aleat]
					}
				}
			};
			match self.get_path_to_goal(grid, &last_coord, &mut to_ignore) {
				Some(x) => {
					let mut path = x;
					self.path_cells.append(&mut path);
					break;
				},
				None => {
					self.path_cells.pop();
				}
			};
		}
		self.path_cells = new_path;

//		println!("{:?}", );
//		while !self.path_cells.last().unwrap().is_a_goal(&self, grid) {
//			let next = self.path_cells.last().unwrap().get_available_close_random_uniq_weight(grid, Some(self.cell_code))[0];
//			self.path_cells.push(next);
//		}
	}

	pub fn get_next_MindPathAI_move(&mut self, grid: &Grid) -> Option<Cell> {
		if self.path_cells.len() == 0 {
			self.init_path_cells(grid);
			return Some(self.path_cells[0]);
		} else {
			self.update_path_data(grid);
		}
		if self.path_must_be_recalc() {
			self.recalc_path(grid)
		}
		for cell in self.path_cells.iter() {
			if cell.status == CellStatus::Empty {
				return Some(*cell);
			}
		}
		println!("{:?}", self.path_cells);
		return None;
	}

	pub fn add_played_cell(&mut self, cell: Cell) {
		self.played_cells.push(cell);
	}

	pub fn get_best_move(&self, grid: &Grid) -> Option<[u8; 2]> {
		let mut best_move: Option<[u8; 2]> = None;
		let mut best_move_cost: Option<u8> = None;
		let shuffled_positions: Vec<[u8; 2]> = grid.get_shuffled_free_cells();
		for cell in shuffled_positions.iter() {
			let mut grid_to_test = grid.clone();
			grid_to_test.edit(&self.cell_code, *cell);
			for i in 0..grid.length {
				let coord: [u8; 2] = match self.cell_code {
					CellStatus::White => [0, i],
					CellStatus::Black => [i, 0],
					_ => { panic!("Failed to match the color"); }
				};
				let to_ignore_init: Vec<[u8; 2]> = Vec::new();
				let weight_to_goal = self.get_weight_to_goal(&grid_to_test, &coord, &to_ignore_init);
				if weight_to_goal == None {
					continue;
				}
				if best_move_cost == None || best_move_cost.unwrap() > weight_to_goal.unwrap() {
					best_move_cost = weight_to_goal;
					best_move = Some(*cell);
				}
			}
		}
		return best_move;
	}

	pub fn get_path_to_goal(&self, grid: &Grid, cell: &[u8; 2], to_ignore: &Vec<[u8; 2]>) -> Option<Vec<Cell>> {
		let cell_object = grid.get_cell(*cell);
		if cell_object.is_a_goal(&self, grid) {
			let mut vec: Vec<Cell> = Vec::new();
			vec.push(*cell_object);
			return Some(vec);
		}
		let mut to_ignore_cell = to_ignore.clone();
		to_ignore_cell.push(*cell);
		let available_cells_close = cell_object.get_close(grid, self.cell_code);
		let mut shorter_path: Vec<Cell> = Vec::new();
		let mut last_weight: Option<i8> = None;
		let mut has_shorter_path = false;
		let mut goal_reached: bool = false;
		for cell in available_cells_close.iter() {
			if cell.is_in_vector(&to_ignore_cell) {
				continue;
			}
//			if last_weight == None {
//				last_weight = Some(cell.weight);
//			} else if last_weight.unwrap > cell.weight  {
//
//			}
			let path_to_goal: Vec<Cell> = match self.get_path_to_goal(grid, &[cell.x, cell.y], &to_ignore_cell) {
				Some(x) => x,
				None => { continue; }
			};
			goal_reached = true;
			if !has_shorter_path || path_to_goal.len() < shorter_path.len() {
				shorter_path = path_to_goal;
				has_shorter_path = true;
			}
			break;

		}
		if !goal_reached || !has_shorter_path {
			return None;
		}
		let mut new_cell_list: Vec<Cell> = Vec::new();
		new_cell_list.push(*cell_object);
		new_cell_list.append(&mut shorter_path);
		return Some(shorter_path);
	}

	pub fn get_weight_to_goal(&self, grid: &Grid, cell: &[u8; 2], to_ignore: &Vec<[u8; 2]>) -> Option<u8> {
		let cell_object = grid.get_cell(*cell);
		if cell_object.is_a_goal(&self, grid) {
			return Some(cell_object.get_weight(&self));
		}
		let mut to_ignore_cell = to_ignore.clone();
		to_ignore_cell.push(*cell);
		let available_cells_close = cell_object.get_close(grid, self.cell_code);
		let mut shorter_path: Option<u8> = None;
		let mut last_weight: Option<i8> = None;
		let mut goal_reached: bool = false;
		for cell in available_cells_close.iter() {
			if cell.is_in_vector(&to_ignore_cell) {
				continue;
			}
			let weight_to_goal = self.get_weight_to_goal(grid, &[cell.x, cell.y], &to_ignore_cell);
			if weight_to_goal == None {
				continue;
			}
			goal_reached = true;
			if shorter_path == None || weight_to_goal.unwrap() < shorter_path.unwrap() {
				shorter_path = weight_to_goal;
			}
			last_weight = Some(cell.weight);
		}
		if !goal_reached || shorter_path == None {
			return None;
		}
		return Some(shorter_path.unwrap() + cell_object.get_weight(&self));
	}
}

impl PlayerType {
	pub fn to_string(&self) -> &'static str {
		return match *self {
				PlayerType::PathAI => "Path AI",
				PlayerType::MindPathAI => "Mind path AI",
				PlayerType::RandomAI => "Random AI",
				PlayerType::ButeforceAI => "Bruteforce AI",
				PlayerType::Human => "Human"
			};
	}
}<commit_msg>Useless code<commit_after>use std::old_io;
use cell::CellStatus;
use grid::Grid;
use cell::Cell;
use cell::PositionWeight;

pub struct Player {
	pub name: String,
	pub cell_code: CellStatus,
	pub player_type: PlayerType,
	pub played_cells: Vec<Cell>,
	pub path_cells: Vec<Cell>
}

pub enum PlayerType {
	RandomAI,
	PathAI,
	MindPathAI,
	ButeforceAI,
	Human
}

impl Player {
	pub fn new(num: u8, grid_length: u8) -> Player {
		let possibilities: u16 = match num {
			1 if grid_length % 2 != 0 => {
				(grid_length*grid_length + 1) as u16
			},
			_ => {
				(grid_length*grid_length) as u16
			}
		};grid_length as u16 * grid_length as u16;
		println!("Please, give us a name for player {}", num);

		let mut stdin = old_io::stdin();
		let grid_input = stdin.lock().lines().next().unwrap().ok().unwrap();
		let name = grid_input.trim();

		let player_type: PlayerType;
		loop {
			println!("{} will be [h]uman, [r]andom IA, [p]ath IA, [m]ind path IA, [b]ruteforce IA ?", name);
			let grid_input = stdin.lock().lines().next().unwrap().ok().unwrap();
			match grid_input.trim() {
					"h" => { player_type = PlayerType::Human; break; },
					"p" => { player_type = PlayerType::PathAI; break;},
					"m" => { player_type = PlayerType::MindPathAI; break;},
					"r" => { player_type = PlayerType::RandomAI; break;},
					"b" => { player_type = PlayerType::ButeforceAI; break;}
					_ => {continue;}
				};
		};

		return Player {
			name: (*name).to_string(),
			cell_code: CellStatus::get_color_for_player(num),
			player_type: player_type,
			played_cells: Vec::with_capacity(possibilities as usize),
			path_cells: Vec::new()
		};
	}

	pub fn inverse(&self) -> CellStatus {
		return match self.cell_code {
			CellStatus::Black => CellStatus::White,
			CellStatus::White => CellStatus::Black,
			_ => panic!("Bad player color")
		}
	}

	pub fn get_next_PathAI_move(&self, grid: &Grid) -> Option<[u8; 2]> {
		use std::rand;
		use std::rand::Rng;
		if grid.count_for_player(self) == 0 {
			let aleat: u8 = rand::thread_rng().gen_range(1, grid.length-1);
			if self.cell_code == CellStatus::White {
				return Some([aleat, 0]);
			} else {
				return Some([0, aleat]);
			}
		}
		let available_moves = self.played_cells.last().unwrap().get_available_close_random_uniq_weight(grid, None);
		if available_moves.len() < 1 {
			return None;
		}
		let next = available_moves[0];
		return Some([next.x, next.y]);
	}

	pub fn init_path_cells(&mut self, grid: &Grid) {
		use std::rand;
		use std::rand::Rng;
		let aleat: u8 = rand::thread_rng().gen_range(1, grid.length-1);
		if self.cell_code == CellStatus::White {
			self.path_cells.push(*grid.get_cell([aleat, 0]));
		} else {
			self.path_cells.push(*grid.get_cell([0, aleat]));
		}
		while !self.path_cells.last().unwrap().is_a_goal(&self, grid) {
			let next = self.path_cells.last().unwrap().get_available_close_random_uniq_weight(grid, Some(self.cell_code))[0];
			self.path_cells.push(next);
		}
	}

	pub fn update_path_data(&mut self, grid: &Grid) {
		let temp_vector: Vec<Cell> = self.path_cells.clone();
		self.path_cells = Vec::with_capacity(temp_vector.len());
		for cell in temp_vector.iter() {
			self.path_cells.push(*grid.get_cell([cell.x, cell.y]));
		}

	}

	pub fn path_must_be_recalc(&self) -> bool {
		for cell in self.path_cells.iter() {
			if cell.status == self.inverse() {
				return true;
			}
		}
		return false;
	}

	pub fn recalc_path(&mut self, grid: &Grid) {
		let mut new_path: Vec<Cell> = Vec::new();
		for cell in self.path_cells.iter() {
			if cell.status != CellStatus::Empty && cell.status != self.cell_code {
				break;
			}
			new_path.push(*cell);
		}
		loop {
			let mut to_ignore: Vec<[u8;2 ]> = Vec::new();
			let last_coord: [u8; 2] = match new_path.clone().last() {
				Some(x) => { [x.x, x.y] },
				None => {
					use std::rand;
					use std::rand::Rng;
					let aleat: u8 = rand::thread_rng().gen_range(1, grid.length-1);
					if self.cell_code == CellStatus::White {
						new_path.push(*grid.get_cell([aleat, 0]));
						[aleat, 0]
					} else {
						new_path.push(*grid.get_cell([0, aleat]));
						[0, aleat]
					}
				}
			};
			match self.get_path_to_goal(grid, &last_coord, &mut to_ignore) {
				Some(x) => {
					let mut path = x;
					self.path_cells.append(&mut path);
					break;
				},
				None => {
					self.path_cells.pop();
				}
			};
		}
		self.path_cells = new_path;

//		println!("{:?}", );
//		while !self.path_cells.last().unwrap().is_a_goal(&self, grid) {
//			let next = self.path_cells.last().unwrap().get_available_close_random_uniq_weight(grid, Some(self.cell_code))[0];
//			self.path_cells.push(next);
//		}
	}

	pub fn get_next_MindPathAI_move(&mut self, grid: &Grid) -> Option<Cell> {
		if self.path_cells.len() == 0 {
			self.init_path_cells(grid);
			return Some(self.path_cells[0]);
		} else {
			self.update_path_data(grid);
		}
		if self.path_must_be_recalc() {
			self.recalc_path(grid)
		}
		for cell in self.path_cells.iter() {
			if cell.status == CellStatus::Empty {
				return Some(*cell);
			}
		}
		println!("{:?}", self.path_cells);
		return None;
	}

	pub fn add_played_cell(&mut self, cell: Cell) {
		self.played_cells.push(cell);
	}

	pub fn get_best_move(&self, grid: &Grid) -> Option<[u8; 2]> {
		let mut best_move: Option<[u8; 2]> = None;
		let mut best_move_cost: Option<u8> = None;
		let shuffled_positions: Vec<[u8; 2]> = grid.get_shuffled_free_cells();
		for cell in shuffled_positions.iter() {
			let mut grid_to_test = grid.clone();
			grid_to_test.edit(&self.cell_code, *cell);
			for i in 0..grid.length {
				let coord: [u8; 2] = match self.cell_code {
					CellStatus::White => [0, i],
					CellStatus::Black => [i, 0],
					_ => { panic!("Failed to match the color"); }
				};
				let to_ignore_init: Vec<[u8; 2]> = Vec::new();
				let weight_to_goal = self.get_weight_to_goal(&grid_to_test, &coord, &to_ignore_init);
				if weight_to_goal == None {
					continue;
				}
				if best_move_cost == None || best_move_cost.unwrap() > weight_to_goal.unwrap() {
					best_move_cost = weight_to_goal;
					best_move = Some(*cell);
				}
			}
		}
		return best_move;
	}

	pub fn get_path_to_goal(&self, grid: &Grid, cell: &[u8; 2], to_ignore: &Vec<[u8; 2]>) -> Option<Vec<Cell>> {
		let cell_object = grid.get_cell(*cell);
		if cell_object.is_a_goal(&self, grid) {
			let mut vec: Vec<Cell> = Vec::new();
			vec.push(*cell_object);
			return Some(vec);
		}
		let mut to_ignore_cell = to_ignore.clone();
		to_ignore_cell.push(*cell);
		let available_cells_close = cell_object.get_close(grid, self.cell_code);
		let mut shorter_path: Vec<Cell> = Vec::new();
		let mut has_shorter_path = false;
		let mut goal_reached: bool = false;
		for cell in available_cells_close.iter() {
			if cell.is_in_vector(&to_ignore_cell) {
				continue;
			}
			let path_to_goal: Vec<Cell> = match self.get_path_to_goal(grid, &[cell.x, cell.y], &to_ignore_cell) {
				Some(x) => x,
				None => { continue; }
			};
			goal_reached = true;
			if !has_shorter_path || path_to_goal.len() < shorter_path.len() {
				shorter_path = path_to_goal;
				has_shorter_path = true;
			}
			break;

		}
		if !goal_reached || !has_shorter_path {
			return None;
		}
		let mut new_cell_list: Vec<Cell> = Vec::new();
		new_cell_list.push(*cell_object);
		new_cell_list.append(&mut shorter_path);
		return Some(shorter_path);
	}

	pub fn get_weight_to_goal(&self, grid: &Grid, cell: &[u8; 2], to_ignore: &Vec<[u8; 2]>) -> Option<u8> {
		let cell_object = grid.get_cell(*cell);
		if cell_object.is_a_goal(&self, grid) {
			return Some(cell_object.get_weight(&self));
		}
		let mut to_ignore_cell = to_ignore.clone();
		to_ignore_cell.push(*cell);
		let available_cells_close = cell_object.get_close(grid, self.cell_code);
		let mut shorter_path: Option<u8> = None;
		let mut goal_reached: bool = false;
		for cell in available_cells_close.iter() {
			if cell.is_in_vector(&to_ignore_cell) {
				continue;
			}
			let weight_to_goal = self.get_weight_to_goal(grid, &[cell.x, cell.y], &to_ignore_cell);
			if weight_to_goal == None {
				continue;
			}
			goal_reached = true;
			if shorter_path == None || weight_to_goal.unwrap() < shorter_path.unwrap() {
				shorter_path = weight_to_goal;
			}
		}
		if !goal_reached || shorter_path == None {
			return None;
		}
		return Some(shorter_path.unwrap() + cell_object.get_weight(&self));
	}
}

impl PlayerType {
	pub fn to_string(&self) -> &'static str {
		return match *self {
				PlayerType::PathAI => "Path AI",
				PlayerType::MindPathAI => "Mind path AI",
				PlayerType::RandomAI => "Random AI",
				PlayerType::ButeforceAI => "Bruteforce AI",
				PlayerType::Human => "Human"
			};
	}
}<|endoftext|>


<commit_before>use chrono::*;
pub use super::split;

pub fn pretty_short(dur: Duration) -> String {
    let components = split::split_duration(dur).as_vec();

    let mut components_iter = components.iter().skip_while(|a| a.val() == 0);
    let first_component = components_iter.next();
    let second_component = components_iter.next();

    let final_str = match first_component {
        Some(x) => {
            match second_component {
                Some(y) => {format!("{} and {}", x.to_string(), y.to_string())},
                None => {x.to_string()}
            }
        },
        // The duration is 0
        None => {split::TimePeriod::Millisecond(0).to_string()},
    };

    return final_str;
}

pub fn pretty_full(dur: Duration) -> String {
    let components = split::split_duration(dur);
    let mut final_str = String::new();

    for (i, component) in components.as_vec().iter().enumerate() {
        if i != 0 {
            final_str.push_str(", ");
        }
        final_str.push_str(&component.to_string());
    }

    return final_str;
}

#[test]
fn test_pretty_full_simple() {
    let test_data = vec![
        (Duration::days(365), "1 year, 0 months, 0 weeks, 0 days, 0 hours, 0 minutes, 0 seconds, 0 milliseconds"),
        (Duration::days(30), "0 years, 1 month, 0 weeks, 0 days, 0 hours, 0 minutes, 0 seconds, 0 milliseconds"),
        (Duration::weeks(1), "0 years, 0 months, 1 week, 0 days, 0 hours, 0 minutes, 0 seconds, 0 milliseconds"),
        (Duration::days(1), "0 years, 0 months, 0 weeks, 1 day, 0 hours, 0 minutes, 0 seconds, 0 milliseconds"),
        (Duration::hours(1), "0 years, 0 months, 0 weeks, 0 days, 1 hour, 0 minutes, 0 seconds, 0 milliseconds"),
        (Duration::minutes(1), "0 years, 0 months, 0 weeks, 0 days, 0 hours, 1 minute, 0 seconds, 0 milliseconds"),
        (Duration::seconds(1), "0 years, 0 months, 0 weeks, 0 days, 0 hours, 0 minutes, 1 second, 0 milliseconds"),
        (Duration::milliseconds(1), "0 years, 0 months, 0 weeks, 0 days, 0 hours, 0 minutes, 0 seconds, 1 millisecond"),
    ];

    for (dur, final_str) in test_data {
        assert_eq!(pretty_full(dur), final_str);
    }
}

#[test]
fn test_pretty_short() {
    let test_data = vec![
        (Duration::milliseconds(0), "0 milliseconds"),
        (Duration::milliseconds(1), "1 millisecond"),
        (-Duration::milliseconds(1), "1 millisecond"),
        (Duration::milliseconds(200), "200 milliseconds"),
        (Duration::seconds(1) + Duration::milliseconds(200), "1 second and 200 milliseconds"),
        (Duration::days(1) + Duration::hours(2), "1 day and 2 hours"),
        (Duration::days(1) + Duration::seconds(2), "1 day and 0 hours"),
    ];

    for (dur, final_str) in test_data {
        assert_eq!(pretty_short(dur), final_str);
    }
}
<commit_msg>Improved the pretty function<commit_after>use chrono::*;
pub use super::split;

pub fn pretty_short(dur: Duration) -> String {
    let components = split::split_duration(dur).as_vec();

    let mut components_iter = components.iter().skip_while(|a| a.val() == 0);
    let first_component = components_iter.next();
    let second_component = components_iter.next();

    let final_str = match first_component {
        Some(x) => {
            match second_component.and_then(has_second) {
                Some(y) => {format!("{} and {}", x.to_string(), y.to_string())},
                None => {x.to_string()}
            }
        },
        // The duration is 0
        None => {split::TimePeriod::Millisecond(0).to_string()},
    };

    fn has_second(val: &split::TimePeriod) -> Option<&split::TimePeriod> {
        if val.val() == 0 {return None};
        return Some(val);
    }

    return final_str;
}

pub fn pretty_full(dur: Duration) -> String {
    let components = split::split_duration(dur);
    let mut final_str = String::new();

    for (i, component) in components.as_vec().iter().enumerate() {
        if i != 0 {
            final_str.push_str(", ");
        }
        final_str.push_str(&component.to_string());
    }

    return final_str;
}

#[test]
fn test_pretty_full_simple() {
    let test_data = vec![
        (Duration::days(365), "1 year, 0 months, 0 weeks, 0 days, 0 hours, 0 minutes, 0 seconds, 0 milliseconds"),
        (Duration::days(30), "0 years, 1 month, 0 weeks, 0 days, 0 hours, 0 minutes, 0 seconds, 0 milliseconds"),
        (Duration::weeks(1), "0 years, 0 months, 1 week, 0 days, 0 hours, 0 minutes, 0 seconds, 0 milliseconds"),
        (Duration::days(1), "0 years, 0 months, 0 weeks, 1 day, 0 hours, 0 minutes, 0 seconds, 0 milliseconds"),
        (Duration::hours(1), "0 years, 0 months, 0 weeks, 0 days, 1 hour, 0 minutes, 0 seconds, 0 milliseconds"),
        (Duration::minutes(1), "0 years, 0 months, 0 weeks, 0 days, 0 hours, 1 minute, 0 seconds, 0 milliseconds"),
        (Duration::seconds(1), "0 years, 0 months, 0 weeks, 0 days, 0 hours, 0 minutes, 1 second, 0 milliseconds"),
        (Duration::milliseconds(1), "0 years, 0 months, 0 weeks, 0 days, 0 hours, 0 minutes, 0 seconds, 1 millisecond"),
    ];

    for (dur, final_str) in test_data {
        assert_eq!(pretty_full(dur), final_str);
    }
}

#[test]
fn test_pretty_short() {
    let test_data = vec![
        (Duration::milliseconds(0), "0 milliseconds"),
        (Duration::milliseconds(1), "1 millisecond"),
        (-Duration::milliseconds(1), "1 millisecond"),
        (Duration::milliseconds(200), "200 milliseconds"),
        (Duration::seconds(1) + Duration::milliseconds(200), "1 second and 200 milliseconds"),
        (Duration::days(1) + Duration::hours(2), "1 day and 2 hours"),
        (Duration::days(1) + Duration::seconds(2), "1 day"),
    ];

    for (dur, final_str) in test_data {
        assert_eq!(pretty_short(dur), final_str);
    }
}
<|endoftext|>


<commit_before>use argvalues::ArgValues;

use loader;

use gfx;
use glutin;
use gfx_window_glutin;

use gfx::traits::FactoryExt;
use gfx::Device;

use glutin::{VirtualKeyCode, ElementState, MouseButton, Event};

use std::time::Instant;

type ColorFormat = gfx::format::Rgba8;
type DepthFormat = gfx::format::DepthStencil;

gfx_defines! {
    vertex Vertex {
        pos: [f32; 2] = "position",
    }

    pipeline pipe {
        // Vertex buffer
        vbuf: gfx::VertexBuffer<Vertex> = (),

        // Uniforms
        i_global_time: gfx::Global<f32> = "iGlobalTime",
        i_resolution: gfx::Global<[f32; 3]> = "iResolution",
        i_mouse: gfx::Global<[f32; 4]> = "iMouse",
        i_frame: gfx::Global<i32> = "iFrame",
        i_channel0: gfx::TextureSampler<[f32; 4]> = "iChannel0",
        i_channel1: gfx::TextureSampler<[f32; 4]> = "iChannel1",
        i_channel2: gfx::TextureSampler<[f32; 4]> = "iChannel2",
        i_channel3: gfx::TextureSampler<[f32; 4]> = "iChannel3",

        // Output color
        frag_color: gfx::BlendTarget<ColorFormat> = ("fragColor", gfx::state::MASK_ALL, gfx::preset::blend::ALPHA),
    }
}

const SCREEN: [Vertex; 4] = [
    Vertex{pos: [ 1.0,  1.0]}, // Top right
    Vertex{pos: [-1.0,  1.0]}, // Top left
    Vertex{pos: [-1.0, -1.0]}, // Bottom left
    Vertex{pos: [ 1.0, -1.0]}, // Bottom right
];

const SCREEN_INDICES: [u16; 6] = [
    0, 1, 2,
    0, 2, 3,
];

const CLEAR_COLOR: [f32; 4] = [1.0; 4];

pub fn run(av: &ArgValues) -> Result<(), String> {
    let ArgValues {
        mut width,
        mut height,
        ref shaderpath,
        not_from_shadertoy,
        ref texture0path,
        ref texture1path,
        ref texture2path,
        ref texture3path,
    } = *av;

    // Load vertex and fragment shaders into byte buffers
    let (vert_src_res, frag_src_res) = loader::load_shaders(&av);
    let (vert_src_buf, frag_src_buf): (Vec<u8>, Vec<u8>);
    match (vert_src_res, frag_src_res) {
        (Ok(vsbuf), Ok(fsbuf)) => {
            vert_src_buf = vsbuf;
            frag_src_buf = fsbuf;
        },

        (Err(vse), _) => return Err(format!("Error reading vertex shader: {}", vse)),
        (_, Err(fse)) => return Err(format!("Error reading fragment shader: {}", fse)),
    }
    let (vert_src_buf, frag_src_buf) = (vert_src_buf.as_slice(), frag_src_buf.as_slice());

    let builder = glutin::WindowBuilder::new()
        .with_title("shadertoy-rs")
        .with_dimensions(width as u32, height as u32)
        .with_vsync();

    let (window, mut device, mut factory, main_color, mut main_depth) =
        gfx_window_glutin::init::<ColorFormat, DepthFormat>(builder);

    let mut encoder: gfx::Encoder<_,_> = factory.create_command_buffer().into();

    let mut pipeline;
    match factory.create_pipeline_simple(vert_src_buf, frag_src_buf, pipe::new()) {
        Ok(p)  => pipeline = p,
        Err(e) => return Err(format!("Error creating pipeline: {}", e)),
    }

    let (vertex_buffer, slice) = factory.create_vertex_buffer_with_slice(&SCREEN, &SCREEN_INDICES[..]);

    // Load textures
    let sampler = factory.create_sampler_linear();
    let texture0;
    let texture1;
    let texture2;
    let texture3;
    match loader::load_texture(&texture0path, &mut factory) {
        Ok(tex) => texture0 = tex,
        Err(e)  => return Err(e),
    }
    match loader::load_texture(&texture1path, &mut factory) {
        Ok(tex) => texture1 = tex,
        Err(e)  => return Err(e),
    }
    match loader::load_texture(&texture2path, &mut factory) {
        Ok(tex) => texture2 = tex,
        Err(e)  => return Err(e),
    }
    match loader::load_texture(&texture3path, &mut factory) {
        Ok(tex) => texture3 = tex,
        Err(e)  => return Err(e),
    }

    let mut data = pipe::Data {
        vbuf: vertex_buffer,

        i_global_time: 0.0,
        i_resolution: [width, height, width/height],
        i_mouse: [0.0; 4],
        i_frame: -1,

        i_channel0: (texture0, sampler.clone()),
        i_channel1: (texture1, sampler.clone()),
        i_channel2: (texture2, sampler.clone()),
        i_channel3: (texture3, sampler.clone()),

        frag_color: main_color,
    };

    let mut last_mouse = ElementState::Released;
    let mut current_mouse = ElementState::Released;

    let (mut mx, mut my) = (0.0, 0.0);

    let mut xyzw = [0.0; 4];

    let mut start_time = Instant::now();

    loop {
        for event in window.poll_events() {
            match event {
                Event::KeyboardInput(_, _, Some(VirtualKeyCode::Escape)) | Event::Closed => {
                    return Ok(());
                },

                Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::F5)) => {
                    // Reload fragment shader into byte buffer
                    let frag_src_res = loader::load_fragment_shader(&av);
                    let frag_src_buf: Vec<u8>;
                    match frag_src_res {
                        Ok(fsbuf) => frag_src_buf = fsbuf,
                        Err(fse)  => return Err(format!("Error reloading fragment shader: {}", fse)),
                    }
                    let frag_src_buf = frag_src_buf.as_slice();

                    // Recreate pipeline
                    match factory.create_pipeline_simple(vert_src_buf, frag_src_buf, pipe::new()) {
                        Ok(p)  => pipeline = p,
                        Err(e) => return Err(format!("Error recreating pipeline: {}", e)),
                    }

                    // Reset uniforms
                    data.i_global_time = 0.0;
                    data.i_resolution = [width, height, width/height];
                    data.i_mouse = [0.0; 4];
                    data.i_frame = -1;

                    start_time = Instant::now();
                },

                Event::Resized(new_width, new_height) => {
                    gfx_window_glutin::update_views(&window, &mut data.frag_color, &mut main_depth);

                    width = new_width as f32;
                    height = new_height as f32;
                },

                Event::MouseMoved(x, y) => {
                    mx = x as f32;
                    my = height - y as f32; // Flip y-axis
                },

                Event::MouseInput(state, button) => {
                    last_mouse = current_mouse;
                    if state == ElementState::Pressed && button == MouseButton::Left {
                        current_mouse = ElementState::Pressed;
                    } else {
                        current_mouse = ElementState::Released;
                    }
                },

                _ => ()
            }
        }

        // Mouse
        if current_mouse == ElementState::Pressed {
            xyzw[0] = mx;
            xyzw[1] = my;
            if last_mouse == ElementState::Released {
                xyzw[2] = mx;
                xyzw[3] = my;
            }
        } else {
            xyzw[2] = 0.0;
            xyzw[3] = 0.0;
        }
        data.i_mouse = xyzw;

        // Elapsed time
        let elapsed = start_time.elapsed();
        let elapsed_ms = (elapsed.as_secs() * 1000) + (elapsed.subsec_nanos()/1000000) as u64;
        let elapsed_sec = (elapsed_ms as f32) / 1000.0;
        data.i_global_time = elapsed_sec;

        // Resolution
        data.i_resolution = [width, height, width/height];

        // Frame
        data.i_frame += 1;

        // Draw
        encoder.clear(&data.frag_color, CLEAR_COLOR);
        encoder.draw(&slice, &pipeline, &data);
        encoder.flush(&mut device);
        window.swap_buffers().unwrap();
        device.cleanup();
    }
}
<commit_msg>Get rid of unused variable warnings<commit_after>use argvalues::ArgValues;

use loader;

use gfx;
use glutin;
use gfx_window_glutin;

use gfx::traits::FactoryExt;
use gfx::Device;

use glutin::{VirtualKeyCode, ElementState, MouseButton, Event};

use std::time::Instant;

type ColorFormat = gfx::format::Rgba8;
type DepthFormat = gfx::format::DepthStencil;

gfx_defines! {
    vertex Vertex {
        pos: [f32; 2] = "position",
    }

    pipeline pipe {
        // Vertex buffer
        vbuf: gfx::VertexBuffer<Vertex> = (),

        // Uniforms
        i_global_time: gfx::Global<f32> = "iGlobalTime",
        i_resolution: gfx::Global<[f32; 3]> = "iResolution",
        i_mouse: gfx::Global<[f32; 4]> = "iMouse",
        i_frame: gfx::Global<i32> = "iFrame",
        i_channel0: gfx::TextureSampler<[f32; 4]> = "iChannel0",
        i_channel1: gfx::TextureSampler<[f32; 4]> = "iChannel1",
        i_channel2: gfx::TextureSampler<[f32; 4]> = "iChannel2",
        i_channel3: gfx::TextureSampler<[f32; 4]> = "iChannel3",

        // Output color
        frag_color: gfx::BlendTarget<ColorFormat> = ("fragColor", gfx::state::MASK_ALL, gfx::preset::blend::ALPHA),
    }
}

const SCREEN: [Vertex; 4] = [
    Vertex{pos: [ 1.0,  1.0]}, // Top right
    Vertex{pos: [-1.0,  1.0]}, // Top left
    Vertex{pos: [-1.0, -1.0]}, // Bottom left
    Vertex{pos: [ 1.0, -1.0]}, // Bottom right
];

const SCREEN_INDICES: [u16; 6] = [
    0, 1, 2,
    0, 2, 3,
];

const CLEAR_COLOR: [f32; 4] = [1.0; 4];

pub fn run(av: &ArgValues) -> Result<(), String> {
    let mut width = av.width;
    let mut height = av.height;

    let texture0path = &av.texture0path;
    let texture1path = &av.texture1path;
    let texture2path = &av.texture2path;
    let texture3path = &av.texture3path;

    // Load vertex and fragment shaders into byte buffers
    let (vert_src_res, frag_src_res) = loader::load_shaders(&av);
    let (vert_src_buf, frag_src_buf): (Vec<u8>, Vec<u8>);
    match (vert_src_res, frag_src_res) {
        (Ok(vsbuf), Ok(fsbuf)) => {
            vert_src_buf = vsbuf;
            frag_src_buf = fsbuf;
        },

        (Err(vse), _) => return Err(format!("Error reading vertex shader: {}", vse)),
        (_, Err(fse)) => return Err(format!("Error reading fragment shader: {}", fse)),
    }
    let (vert_src_buf, frag_src_buf) = (vert_src_buf.as_slice(), frag_src_buf.as_slice());

    let builder = glutin::WindowBuilder::new()
        .with_title("shadertoy-rs")
        .with_dimensions(width as u32, height as u32)
        .with_vsync();

    let (window, mut device, mut factory, main_color, mut main_depth) =
        gfx_window_glutin::init::<ColorFormat, DepthFormat>(builder);

    let mut encoder: gfx::Encoder<_,_> = factory.create_command_buffer().into();

    let mut pipeline;
    match factory.create_pipeline_simple(vert_src_buf, frag_src_buf, pipe::new()) {
        Ok(p)  => pipeline = p,
        Err(e) => return Err(format!("Error creating pipeline: {}", e)),
    }

    let (vertex_buffer, slice) = factory.create_vertex_buffer_with_slice(&SCREEN, &SCREEN_INDICES[..]);

    // Load textures
    let sampler = factory.create_sampler_linear();
    let texture0;
    let texture1;
    let texture2;
    let texture3;
    match loader::load_texture(&texture0path, &mut factory) {
        Ok(tex) => texture0 = tex,
        Err(e)  => return Err(e),
    }
    match loader::load_texture(&texture1path, &mut factory) {
        Ok(tex) => texture1 = tex,
        Err(e)  => return Err(e),
    }
    match loader::load_texture(&texture2path, &mut factory) {
        Ok(tex) => texture2 = tex,
        Err(e)  => return Err(e),
    }
    match loader::load_texture(&texture3path, &mut factory) {
        Ok(tex) => texture3 = tex,
        Err(e)  => return Err(e),
    }

    let mut data = pipe::Data {
        vbuf: vertex_buffer,

        i_global_time: 0.0,
        i_resolution: [width, height, width/height],
        i_mouse: [0.0; 4],
        i_frame: -1,

        i_channel0: (texture0, sampler.clone()),
        i_channel1: (texture1, sampler.clone()),
        i_channel2: (texture2, sampler.clone()),
        i_channel3: (texture3, sampler.clone()),

        frag_color: main_color,
    };

    let mut last_mouse = ElementState::Released;
    let mut current_mouse = ElementState::Released;

    let (mut mx, mut my) = (0.0, 0.0);

    let mut xyzw = [0.0; 4];

    let mut start_time = Instant::now();

    loop {
        for event in window.poll_events() {
            match event {
                Event::KeyboardInput(_, _, Some(VirtualKeyCode::Escape)) | Event::Closed => {
                    return Ok(());
                },

                Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::F5)) => {
                    // Reload fragment shader into byte buffer
                    let frag_src_res = loader::load_fragment_shader(&av);
                    let frag_src_buf: Vec<u8>;
                    match frag_src_res {
                        Ok(fsbuf) => frag_src_buf = fsbuf,
                        Err(fse)  => return Err(format!("Error reloading fragment shader: {}", fse)),
                    }
                    let frag_src_buf = frag_src_buf.as_slice();

                    // Recreate pipeline
                    match factory.create_pipeline_simple(vert_src_buf, frag_src_buf, pipe::new()) {
                        Ok(p)  => pipeline = p,
                        Err(e) => return Err(format!("Error recreating pipeline: {}", e)),
                    }

                    // Reset uniforms
                    data.i_global_time = 0.0;
                    data.i_resolution = [width, height, width/height];
                    data.i_mouse = [0.0; 4];
                    data.i_frame = -1;

                    start_time = Instant::now();
                },

                Event::Resized(new_width, new_height) => {
                    gfx_window_glutin::update_views(&window, &mut data.frag_color, &mut main_depth);

                    width = new_width as f32;
                    height = new_height as f32;
                },

                Event::MouseMoved(x, y) => {
                    mx = x as f32;
                    my = height - y as f32; // Flip y-axis
                },

                Event::MouseInput(state, button) => {
                    last_mouse = current_mouse;
                    if state == ElementState::Pressed && button == MouseButton::Left {
                        current_mouse = ElementState::Pressed;
                    } else {
                        current_mouse = ElementState::Released;
                    }
                },

                _ => ()
            }
        }

        // Mouse
        if current_mouse == ElementState::Pressed {
            xyzw[0] = mx;
            xyzw[1] = my;
            if last_mouse == ElementState::Released {
                xyzw[2] = mx;
                xyzw[3] = my;
            }
        } else {
            xyzw[2] = 0.0;
            xyzw[3] = 0.0;
        }
        data.i_mouse = xyzw;

        // Elapsed time
        let elapsed = start_time.elapsed();
        let elapsed_ms = (elapsed.as_secs() * 1000) + (elapsed.subsec_nanos()/1000000) as u64;
        let elapsed_sec = (elapsed_ms as f32) / 1000.0;
        data.i_global_time = elapsed_sec;

        // Resolution
        data.i_resolution = [width, height, width/height];

        // Frame
        data.i_frame += 1;

        // Draw
        encoder.clear(&data.frag_color, CLEAR_COLOR);
        encoder.draw(&slice, &pipeline, &data);
        encoder.flush(&mut device);
        window.swap_buffers().unwrap();
        device.cleanup();
    }
}
<|endoftext|>


<commit_before>use std::hash::Hash;
use std::collections::HashSet;

pub trait SearchSpace {
    type State: Ord + Hash + Eq;
    type Action;
    type Iterator: Iterator<Item=Self::Action>;

    fn actions(&self, state: &Self::State) -> Self::Iterator;
    fn next_state(&self, state: &Self::State, action: &Self::Action) -> Self::State;
    fn is_goal(&self, state: &Self::State) -> bool;
}

pub fn depth_first_search<S>(space: &S, start: S::State) -> Option<Vec<S::Action>>
where S: SearchSpace {
    let mut path = Vec::new();
    let actions = space.actions(&start);
    let mut frontier = vec![(start, actions)];

    loop {
        let result = match frontier.last_mut() {
            None => return None,
            Some(&mut (ref mut state, ref mut actions)) => {
                if space.is_goal(&state) {
                    return Some(path);
                }
                match actions.next() {
                    None => None,
                    Some(action) => {
                        let next_state = space.next_state(&state, &action);
                        let next_actions = space.actions(&next_state);
                        path.push(action);
                        Some((next_state, next_actions))
                    }
                }
            }
        };
        match result {
            None => {
                path.pop();
                frontier.pop();
            },
            Some((next_state, next_actions)) => {
                frontier.push((next_state, next_actions));
            },
        };
    }
}

#[cfg(test)]
pub mod tests {
    use std::vec::IntoIter;
    use super::*;

    #[test]
    pub fn test_depth_first_search() {
        struct S {
            goal: i32,
        }

        #[derive(Debug, Clone, PartialEq)]
        enum Direction {
            Left,
            Right
        }

        impl SearchSpace for S {
            type State = i32;
            type Action = Direction;
            type Iterator = IntoIter<Self::Action>;

            fn actions(&self, state: &i32) -> Self::Iterator {
                if *state == 0 || *state == 1 {
                    vec![Direction::Left, Direction::Right].into_iter()
                } else {
                    vec![].into_iter()
                }
            }

            fn next_state(&self, state: &i32, action: &Direction) -> i32 {
                match *state {
                    0 => match *action {
                        Direction::Left => 1,
                        Direction::Right => 2,
                    },
                    1 => match *action {
                        Direction::Left => 3,
                        Direction::Right => 4,
                    },
                    node => node
                }
            }

            fn is_goal(&self, state: &i32) -> bool {
                return self.goal == *state
            }
        }

        impl S {
            fn solve(start: i32, goal: i32) -> Option<Vec<Direction>> {
                let space = S { goal: goal };
                depth_first_search(&space, start)
            }
        }

        assert_eq!(S::solve(0, 0).unwrap(), vec![]);
        assert_eq!(S::solve(0, 1).unwrap(), vec![Direction::Left]);
        assert_eq!(S::solve(0, 2).unwrap(), vec![Direction::Right]);
        assert_eq!(S::solve(0, 3).unwrap(), vec![Direction::Left, Direction::Left]);
        assert_eq!(S::solve(0, 4).unwrap(), vec![Direction::Left, Direction::Right]);
        assert_eq!(S::solve(2, 2).unwrap(), vec![]);
        assert!(S::solve(5, 0).is_none());
    }
}
<commit_msg>Track visited state via HashSet<commit_after>use std::hash::{Hash, Hasher, SipHasher};
use std::collections::HashSet;

pub trait SearchSpace {
    type State: Ord + Hash + Eq;
    type Action;
    type Iterator: Iterator<Item=Self::Action>;

    fn actions(&self, state: &Self::State) -> Self::Iterator;
    fn next_state(&self, state: &Self::State, action: &Self::Action) -> Self::State;
    fn is_goal(&self, state: &Self::State) -> bool;
}

pub fn depth_first_search<S>(space: &S, start: S::State) -> Option<Vec<S::Action>>
where S: SearchSpace {
    let mut path = Vec::new();
    let actions = space.actions(&start);
    let mut frontier = vec![(start, actions)];
    let mut visited = HashSet::new();

    loop {
        let result = match frontier.last_mut() {
            None => return None,
            Some(&mut (ref mut state, ref mut actions)) => {
                if space.is_goal(&state) {
                    return Some(path);
                }
                match actions.next() {
                    None => None,
                    Some(action) => {
                        let next_state = space.next_state(&state, &action);

                        let mut hasher = SipHasher::new();
                        next_state.hash(&mut hasher);
                        let hash = hasher.finish();
                        if visited.contains(&hash) {
                            continue;
                        }
                        visited.insert(hash);

                        let next_actions = space.actions(&next_state);
                        path.push(action);
                        Some((next_state, next_actions))
                    }
                }
            }
        };
        match result {
            None => {
                path.pop();
                frontier.pop();
            },
            Some((next_state, next_actions)) => {
                frontier.push((next_state, next_actions));
            },
        };
    }
}

#[cfg(test)]
pub mod tests {
    use std::vec::IntoIter;
    use super::*;

    #[test]
    pub fn test_depth_first_search() {
        struct S {
            goal: i32,
        }

        #[derive(Debug, Clone, PartialEq)]
        enum Direction {
            Left,
            Right
        }

        impl SearchSpace for S {
            type State = i32;
            type Action = Direction;
            type Iterator = IntoIter<Self::Action>;

            fn actions(&self, state: &i32) -> Self::Iterator {
                if *state == 0 || *state == 1 {
                    vec![Direction::Left, Direction::Right].into_iter()
                } else if *state == 2 {
                    vec![Direction::Left].into_iter()
                }
                else {
                    vec![].into_iter()
                }
            }

            fn next_state(&self, state: &i32, action: &Direction) -> i32 {
                match *state {
                    0 => match *action {
                        Direction::Left => 1,
                        Direction::Right => 2,
                    },
                    1 => match *action {
                        Direction::Left => 3,
                        Direction::Right => 4,
                    },
                    2 => 2,
                    node => node
                }
            }

            fn is_goal(&self, state: &i32) -> bool {
                return self.goal == *state
            }
        }

        impl S {
            fn solve(start: i32, goal: i32) -> Option<Vec<Direction>> {
                let space = S { goal: goal };
                depth_first_search(&space, start)
            }
        }

        assert_eq!(S::solve(0, 0).unwrap(), vec![]);
        assert_eq!(S::solve(0, 1).unwrap(), vec![Direction::Left]);
        assert_eq!(S::solve(0, 2).unwrap(), vec![Direction::Right]);
        assert_eq!(S::solve(0, 3).unwrap(), vec![Direction::Left, Direction::Left]);
        assert_eq!(S::solve(0, 4).unwrap(), vec![Direction::Left, Direction::Right]);
        assert_eq!(S::solve(2, 2).unwrap(), vec![]);
        assert!(S::solve(2, 0).is_none());
        assert!(S::solve(5, 0).is_none());
    }
}
<|endoftext|>


<commit_before>use std::io::{self, Write, BufReader, BufRead};
use std::sync::mpsc::{self, TryRecvError};

use serde_json;

use app::TurtleApp;
use event::Event;
use query::{Query, DrawingCommand, Request, StateUpdate, Response};

/// Continuously read queries from stdin and send them to the renderer
pub fn run(
    mut app: TurtleApp,
    drawing_tx: mpsc::Sender<DrawingCommand>,
    events_rx: mpsc::Receiver<Event>,
    // Intentionally unused. Only used to tell if thread has already quit.
    _running_tx: mpsc::Sender<()>,
) {
    // Read queries from the turtle process
    let stdin = io::stdin();
    let mut reader = BufReader::new(stdin);
    loop {
        let mut buffer = String::new();
        let read_bytes = reader.read_line(&mut buffer)
            .expect("bug: unable to read data from stdin");
        if read_bytes == 0 {
            // Reached EOF, turtle process must have quit
            // We stop this loop since there is no point in continuing to read from something that
            // will never produce anything again
            break;
        }

        let query: Result<Query, _> = serde_json::from_str(&buffer);
        let result: Result<(), ()> = query.map_err(|err| {
            if err.is_io() || err.is_syntax() || err.is_data() {
                panic!("bug: failed to read command from turtle process");
            }
            else if err.is_eof() {
                // Could not read anymore bytes from stdin, the turtle process must have ended
                ()
            }
            else {
                unreachable!("bug: reached unreachable case of serde error");
            }
        }).and_then(|query| {
            handle_query(query, &mut app, &events_rx, &drawing_tx).and_then(|resp| match resp {
                Some(ref response) => send_response(response),
                None => Ok(()),
            })
        });
        if let Err(_) = result {
            break;
        }
    }
}

/// We want to expose this specifically for tests so that tests can mimic the behaviour of the
/// server without actually spawning a new process. See renderer_process.rs for more details.
#[cfg(any(feature = "test", test))]
pub(crate) fn handle_query_for_test_use_only(
    query: Query,
    app: &mut TurtleApp,
    events_rx: &mpsc::Receiver<Event>,
    drawing_tx: &mpsc::Sender<DrawingCommand>,
) -> Result<Option<Response>, ()> {
    handle_query(query, app, events_rx, drawing_tx)
}

/// Returns the appropriate Response (if any) to the given Query
///
/// Returns Err(()) if it is time to quit because we have been disconnected.
fn handle_query(
    query: Query,
    app: &mut TurtleApp,
    events_rx: &mpsc::Receiver<Event>,
    drawing_tx: &mpsc::Sender<DrawingCommand>,
) -> Result<Option<Response>, ()> {
    match query {
        Query::Request(req) => handle_request(req, &app, &events_rx),
        Query::Update(update) => handle_update(update, app),
        Query::Drawing(cmd) => drawing_tx.send(cmd).map(|_| None).map_err(|_| ()),
    }
}

fn handle_request(
    request: Request,
    app: &TurtleApp,
    events_rx: &mpsc::Receiver<Event>,
) -> Result<Option<Response>, ()> {
    use self::Request::*;
    Ok(Some(match request {
        TurtleState => Response::TurtleState((*app.turtle()).clone()),
        DrawingState => Response::DrawingState((*app.drawing()).clone()),
        Event => Response::Event(match events_rx.try_recv() {
            Ok(event) => Some(event),
            Err(TryRecvError::Empty) => None,
            Err(TryRecvError::Disconnected) => return Err(()),
        }),
    }))
}

fn handle_update(
    update: StateUpdate,
    app: &mut TurtleApp,
) -> Result<Option<Response>, ()> {
    use self::StateUpdate::*;
    match update {
        TurtleState(turtle) => *app.turtle_mut() = turtle,
        DrawingState(drawing) => *app.drawing_mut() = drawing,
        TemporaryPath(path) => app.set_temporary_path(path),
    }

    Ok(None)
}

/// Sends a response to stdout
fn send_response(response: &Response) -> Result<(), ()> {
    let mut stdout = io::stdout();
    match serde_json::to_writer(&mut stdout, response) {
        Ok(_) => {
            writeln!(&mut stdout)
                .expect("bug: unable to write final newline when sending response");
            Ok(())
        },
        Err(err) => {
            if err.is_io() || err.is_eof() {
                Err(())
            }
            else {
                // The other cases for err all have to do with input, so those should never occur
                unreachable!("bug: got an input error when writing output");
            }
        },
    }
}
<commit_msg>Fixed panic caused by calling io::stdout() in every call to send_response<commit_after>use std::io::{self, Write, BufReader, BufRead};
use std::sync::mpsc::{self, TryRecvError};

use serde_json;

use app::TurtleApp;
use event::Event;
use query::{Query, DrawingCommand, Request, StateUpdate, Response};

/// Continuously read queries from stdin and send them to the renderer
pub fn run(
    mut app: TurtleApp,
    drawing_tx: mpsc::Sender<DrawingCommand>,
    events_rx: mpsc::Receiver<Event>,
    // Intentionally unused. Only used to tell if thread has already quit.
    _running_tx: mpsc::Sender<()>,
) {
    // Read queries from the turtle process
    let stdin = io::stdin();
    let mut stdout = io::stdout();
    let mut reader = BufReader::new(stdin);
    loop {
        let mut buffer = String::new();
        let read_bytes = reader.read_line(&mut buffer)
            .expect("bug: unable to read data from stdin");
        if read_bytes == 0 {
            // Reached EOF, turtle process must have quit
            // We stop this loop since there is no point in continuing to read from something that
            // will never produce anything again
            break;
        }

        let query: Result<Query, _> = serde_json::from_str(&buffer);
        let result: Result<(), ()> = query.map_err(|err| {
            if err.is_io() || err.is_syntax() || err.is_data() {
                panic!("bug: failed to read command from turtle process");
            }
            else if err.is_eof() {
                // Could not read anymore bytes from stdin, the turtle process must have ended
                ()
            }
            else {
                unreachable!("bug: reached unreachable case of serde error");
            }
        }).and_then(|query| {
            handle_query(query, &mut app, &events_rx, &drawing_tx).and_then(|resp| match resp {
                Some(ref response) => send_response(&mut stdout, response),
                None => Ok(()),
            })
        });
        if let Err(_) = result {
            break;
        }
    }
}

/// We want to expose this specifically for tests so that tests can mimic the behaviour of the
/// server without actually spawning a new process. See renderer_process.rs for more details.
#[cfg(any(feature = "test", test))]
pub(crate) fn handle_query_for_test_use_only(
    query: Query,
    app: &mut TurtleApp,
    events_rx: &mpsc::Receiver<Event>,
    drawing_tx: &mpsc::Sender<DrawingCommand>,
) -> Result<Option<Response>, ()> {
    handle_query(query, app, events_rx, drawing_tx)
}

/// Returns the appropriate Response (if any) to the given Query
///
/// Returns Err(()) if it is time to quit because we have been disconnected.
fn handle_query(
    query: Query,
    app: &mut TurtleApp,
    events_rx: &mpsc::Receiver<Event>,
    drawing_tx: &mpsc::Sender<DrawingCommand>,
) -> Result<Option<Response>, ()> {
    match query {
        Query::Request(req) => handle_request(req, &app, &events_rx),
        Query::Update(update) => handle_update(update, app),
        Query::Drawing(cmd) => drawing_tx.send(cmd).map(|_| None).map_err(|_| ()),
    }
}

fn handle_request(
    request: Request,
    app: &TurtleApp,
    events_rx: &mpsc::Receiver<Event>,
) -> Result<Option<Response>, ()> {
    use self::Request::*;
    Ok(Some(match request {
        TurtleState => Response::TurtleState((*app.turtle()).clone()),
        DrawingState => Response::DrawingState((*app.drawing()).clone()),
        Event => Response::Event(match events_rx.try_recv() {
            Ok(event) => Some(event),
            Err(TryRecvError::Empty) => None,
            Err(TryRecvError::Disconnected) => return Err(()),
        }),
    }))
}

fn handle_update(
    update: StateUpdate,
    app: &mut TurtleApp,
) -> Result<Option<Response>, ()> {
    use self::StateUpdate::*;
    match update {
        TurtleState(turtle) => *app.turtle_mut() = turtle,
        DrawingState(drawing) => *app.drawing_mut() = drawing,
        TemporaryPath(path) => app.set_temporary_path(path),
    }

    Ok(None)
}

/// Sends a response to stdout
fn send_response<W: Write>(mut writer: W, response: &Response) -> Result<(), ()> {
    match serde_json::to_writer(&mut writer, response) {
        Ok(_) => {
            writeln!(&mut writer)
                .expect("bug: unable to write final newline when sending response");
            Ok(())
        },
        Err(err) => {
            if err.is_io() || err.is_eof() {
                Err(())
            }
            else {
                // The other cases for err all have to do with input, so those should never occur
                unreachable!("bug: got an input error when writing output");
            }
        },
    }
}
<|endoftext|>


<commit_before>use std::thread;
use std::io::Write;
use std::net::{TcpListener, TcpStream};
use std::sync::{Arc, Mutex};
use {Matcher, SERVER_ADDRESS, Request, Mock};

impl Mock {
    fn method_matches(&self, request: &Request) -> bool {
        self.method == request.method
    }

    fn path_matches(&self, request: &Request) -> bool {
        self.path == request.path
    }

    fn headers_match(&self, request: &Request) -> bool {
        for &(ref field, ref value) in &self.headers {
            match request.find_header(field) {
                Some(request_header_value) => {
                    if value == request_header_value { continue }

                    return false
                },
                None => {
                    if value == &Matcher::Missing { continue }

                    return false
                },
            }
        }

        true
    }

    fn body_matches(&self, request: &Request) -> bool {
        self.body == String::from_utf8_lossy(&request.body).into_owned()
    }
}

impl<'a> PartialEq<Request> for &'a mut Mock {
    fn eq(&self, other: &Request) -> bool {
        self.method_matches(other)
            && self.path_matches(other)
            && self.headers_match(other)
            && self.body_matches(other)
    }
}

pub struct State {
    pub mocks: Vec<Mock>,
    pub unmatched_requests: Vec<Request>,
}

impl Default for State {
    fn default() -> Self {
        State {
            mocks: Vec::new(),
            unmatched_requests: Vec::new(),
        }
    }
}

lazy_static! {
    pub static ref STATE: Arc<Mutex<State>> = Arc::new(Mutex::new(State::default()));
}

pub fn try_start() {
    if is_listening() { return }

    start()
}

fn start() {
    thread::spawn(move || {
        let listener = TcpListener::bind(SERVER_ADDRESS).unwrap();
        for stream in listener.incoming() {
            match stream {
                Ok(mut stream) => {
                    let request = Request::from(&mut stream);
                    if request.is_ok() {
                        handle_request(request, stream);
                    } else {
                        let body = request.error().map_or("Could not parse the request.", |err| err.as_str());
                        let response = format!("HTTP/1.1 422 Unprocessable Entity\r\ncontent-length: {}\r\n\r\n{}", body.len(), body);
                        stream.write(response.as_bytes()).unwrap();
                    }
                },
                Err(_) => {},
            }
        }
    });

    while !is_listening() {}
}

fn is_listening() -> bool {
    TcpStream::connect(SERVER_ADDRESS).is_ok()
}

fn handle_request(request: Request, stream: TcpStream) {
    handle_match_mock(request, stream);
}

fn handle_match_mock(request: Request, mut stream: TcpStream) {
    let found;

    let state_mutex = STATE.clone();
    let mut state = state_mutex.lock().unwrap();

    match state.mocks.iter_mut().rev().find(|mock| mock == &request) {
        Some(mut mock) => {
            found = true;

            mock.hits = mock.hits + 1;

            let mut headers = String::new();
            for &(ref key, ref value) in &mock.response.headers {
                headers.push_str(key);
                headers.push_str(": ");
                headers.push_str(value);
                headers.push_str("\r\n");
            }

            let ref body = mock.response.body;

            let response = format!("HTTP/1.1 {}\r\ncontent-length: {}\r\n{}\r\n{}", mock.response.status, body.len(), headers, body);
            stream.write(response.as_bytes()).unwrap();
        },
        None => {
            found = false;
            stream.write("HTTP/1.1 501 Not Implemented\r\n\r\n".as_bytes()).unwrap();
        }
    }

    if !found { state.unmatched_requests.push(request); }
}
<commit_msg>Clean up server.rs.<commit_after>use std::thread;
use std::io::Write;
use std::net::{TcpListener, TcpStream};
use std::sync::{Arc, Mutex};
use {Matcher, SERVER_ADDRESS, Request, Mock};

impl Mock {
    fn method_matches(&self, request: &Request) -> bool {
        self.method == request.method
    }

    fn path_matches(&self, request: &Request) -> bool {
        self.path == request.path
    }

    fn headers_match(&self, request: &Request) -> bool {
        for &(ref field, ref value) in &self.headers {
            match request.find_header(field) {
                Some(request_header_value) => {
                    if value == request_header_value { continue }

                    return false
                },
                None => {
                    if value == &Matcher::Missing { continue }

                    return false
                },
            }
        }

        true
    }

    fn body_matches(&self, request: &Request) -> bool {
        self.body == String::from_utf8_lossy(&request.body).into_owned()
    }
}

impl<'a> PartialEq<Request> for &'a mut Mock {
    fn eq(&self, other: &Request) -> bool {
        self.method_matches(other)
            && self.path_matches(other)
            && self.headers_match(other)
            && self.body_matches(other)
    }
}

pub struct State {
    pub mocks: Vec<Mock>,
    pub unmatched_requests: Vec<Request>,
}

impl Default for State {
    fn default() -> Self {
        State {
            mocks: Vec::new(),
            unmatched_requests: Vec::new(),
        }
    }
}

lazy_static! {
    pub static ref STATE: Arc<Mutex<State>> = Arc::new(Mutex::new(State::default()));
}

pub fn try_start() {
    if is_listening() { return }

    start()
}

fn start() {
    thread::spawn(move || {
        let listener = TcpListener::bind(SERVER_ADDRESS).unwrap();
        for stream in listener.incoming() {
            match stream {
                Ok(mut stream) => {
                    let request = Request::from(&mut stream);
                    if request.is_ok() {
                        handle_request(request, stream);
                    } else {
                        let message = request.error().map_or("Could not parse the request.", |err| err.as_str());
                        respond_with_error(stream, message);
                    }
                },
                Err(_) => {},
            }
        }
    });

    while !is_listening() {}
}

fn is_listening() -> bool {
    TcpStream::connect(SERVER_ADDRESS).is_ok()
}

fn handle_request(request: Request, stream: TcpStream) {
    handle_match_mock(request, stream);
}

fn handle_match_mock(request: Request, stream: TcpStream) {
    let found;

    let state_mutex = STATE.clone();
    let mut state = state_mutex.lock().unwrap();

    match state.mocks.iter_mut().rev().find(|mock| mock == &request) {
        Some(mut mock) => {
            found = true;

            mock.hits = mock.hits + 1;

            respond_with_mock(stream, &mock)
        },
        None => {
            found = false;

            respond_with_mock_not_found(stream);
        }
    }

    if !found { state.unmatched_requests.push(request); }
}

fn respond(mut stream: TcpStream, status: &str, headers: Option<&str>, body: Option<&str>) {
    let mut response = format!("HTTP/1.1 {}\r\n", status);

    if let Some(headers) = headers {
        response.push_str(headers);
    }

    if let Some(body) = body {
        response.push_str(&format!("content-length: {}\r\n\r\n{}", body.len(), body));
    } else {
        response.push_str("\r\n");
    }

    let _ = stream.write(response.as_bytes());
}

fn respond_with_mock(stream: TcpStream, mock: &Mock) {
    let mut headers = String::new();
    for &(ref key, ref value) in &mock.response.headers {
        headers.push_str(key);
        headers.push_str(": ");
        headers.push_str(value);
        headers.push_str("\r\n");
    }

    respond(stream, &mock.response.status.to_string(), Some(&headers), Some(&mock.response.body));
}

fn respond_with_mock_not_found(stream: TcpStream) {
    respond(stream, "501 Not Implemented", None, None);
}

fn respond_with_error(stream: TcpStream, message: &str) {
    respond(stream, "422 Unprocessable Entity", None, Some(message));
}
<|endoftext|>


<commit_before>use std::io::{self, BufReader, BufRead};
use std::sync::mpsc;

use serde_json;

use app::TurtleApp;
use query::{Query, DrawingCommand};

/// Continuously read queries from stdin and send them to the renderer
pub fn run(
    app: TurtleApp,
    drawing_tx: mpsc::Sender<DrawingCommand>,
    // Intentionally unused. Only used to tell if thread has already quit.
    _running_tx: mpsc::Sender<()>,
) {
    // Read queries from the turtle process
    let stdin = io::stdin();
    let mut reader = BufReader::new(stdin);
    loop {
        let mut buffer = String::new();
        let read_bytes = reader.read_line(&mut buffer)
            .expect("bug: unable to read data from stdin");
        if read_bytes == 0 {
            // Reached EOF, turtle process must have quit
            // We stop this loop since there is no point in continuing to read from something that
            // will never produce anything again
            break;
        }

        let query: Result<Query, _> = serde_json::from_str(&buffer);
        match query {
            Ok(query) => match query {
                Query::Request(req) => unimplemented!(),
                Query::Update(update) => unimplemented!(),
                Query::Drawing(cmd) => match drawing_tx.send(cmd) {
                    Ok(_) => {},
                    // The renderer thread is no longer around, so quit
                    Err(_) => break,
                },
            },
            Err(err) => {
                if err.is_io() || err.is_syntax() || err.is_data() {
                    panic!("bug: failed to read command from turtle process");
                }
                else if err.is_eof() {
                    // Could not read anymore bytes from stdin, the turtle process must have ended
                    break;
                }
            },
        }
    }
}
<commit_msg>Added a method for sending responses to stdout from the server<commit_after>use std::io::{self, Write, BufReader, BufRead};
use std::sync::mpsc;

use serde_json;

use app::TurtleApp;
use query::{Query, DrawingCommand};

/// Continuously read queries from stdin and send them to the renderer
pub fn run(
    app: TurtleApp,
    drawing_tx: mpsc::Sender<DrawingCommand>,
    // Intentionally unused. Only used to tell if thread has already quit.
    _running_tx: mpsc::Sender<()>,
) {
    // Read queries from the turtle process
    let stdin = io::stdin();
    let mut reader = BufReader::new(stdin);
    loop {
        let mut buffer = String::new();
        let read_bytes = reader.read_line(&mut buffer)
            .expect("bug: unable to read data from stdin");
        if read_bytes == 0 {
            // Reached EOF, turtle process must have quit
            // We stop this loop since there is no point in continuing to read from something that
            // will never produce anything again
            break;
        }

        let query: Result<Query, _> = serde_json::from_str(&buffer);
        match query {
            Ok(query) => match query {
                Query::Request(req) => unimplemented!(),
                Query::Update(update) => unimplemented!(),
                Query::Drawing(cmd) => match drawing_tx.send(cmd) {
                    Ok(_) => {},
                    // The renderer thread is no longer around, so quit
                    Err(_) => break,
                },
            },
            Err(err) => {
                if err.is_io() || err.is_syntax() || err.is_data() {
                    panic!("bug: failed to read command from turtle process");
                }
                else if err.is_eof() {
                    // Could not read anymore bytes from stdin, the turtle process must have ended
                    break;
                }
            },
        }
    }
}

/// Sends a response to stdout
fn send_response(query: &Query) -> Result<(), ()> {
    let mut stdout = io::stdout();
    match serde_json::to_writer(&mut stdout, query) {
        Ok(_) => {
            writeln!(&mut stdout)
                .expect("bug: unable to write final newline when sending response");
            Ok(())
        },
        Err(err) => {
            if err.is_io() || err.is_eof() {
                Err(())
            }
            else {
                // The other cases for err all have to do with input, so those should never occur
                unreachable!("bug: got an input error when writing output");
            }
        },
    }
}
<|endoftext|>