<commit_before>extern crate image;
extern crate img_hash;
extern crate postgres;
#[macro_use] extern crate log;
extern crate log4rs;
extern crate time;
#[macro_use] extern crate hyper;
extern crate url;
extern crate toml;

use std::env;
use postgres::{Connection, SslMode};
use img_hash::{ImageHash, HashType};
use std::thread;
use std::default::Default;
use time::{Timespec, Duration};
use hyper::Client;
use hyper::header::ContentType;
use image::ImageFormat;
use image::GenericImage;
use std::io::Read;
use hyper::status::StatusCode;
use postgres::stmt::Statement;
use std::fs::File;
use url::form_urlencoded;

header! { (XExtra, "X-Extra") => [String] }
header! { (XStream, "X-Stream") => [String] }

fn prepare_statement<'a>(conn: &'a Connection, stmt: &str) -> Statement<'a> {
    loop {
        let prep_stmt = conn.prepare_cached(stmt);
        if prep_stmt.is_err() {
            error!("Error in prepare for '{}': {}",
                   stmt,
                   prep_stmt.unwrap_err());
            thread::sleep(Duration::seconds(4).to_std().unwrap());
            continue;
        }
        return prep_stmt.unwrap();
    }
}

fn main() {
    let mut config_string = String::new();
    File::open("config.toml").unwrap().read_to_string(&mut config_string).unwrap();
    let mut parser = toml::Parser::new(&config_string);

    let config = parser.parse().unwrap();
    let config_table = config.get("config").unwrap();
    let interval = Duration::minutes(config_table.lookup("refresh_minutes")
                                                 .unwrap()
                                                 .as_integer()
                                                 .unwrap());
    let imager_url: &str = &(String::from(config_table.lookup("imager_host")
                                                      .unwrap()
                                                      .as_str()
                                                      .unwrap()) +
                             &String::from("/streams"));
    let check_ms = Duration::milliseconds(
        config_table.lookup("check_ms").unwrap().as_integer().unwrap())
        .to_std().unwrap();

    log4rs::init_file("log.toml", Default::default()).unwrap();
    let db_url: &str = &env::var("DATABASE_URL").unwrap();
    let conn = Connection::connect(db_url, SslMode::None).unwrap();

    let query_stmt = prepare_statement(&conn,
                                       "select * from videos_video order by \"lastRetrieved\" \
                                        asc limit 1");
    let update_stmt = prepare_statement(&conn,
                                        "update videos_video set working = true, hash = $1, \
                                         motion = $2, \"lastRetrieved\" = $3, extra = $4, \"streamURL\" = $5 where id = $6");
    let not_working_stmt = prepare_statement(&conn,
                                     "update videos_video set working = false, \"lastRetrieved\" = $1 where id = $2");

    info!("Connected to Postgres and ready to update video...");
    loop {
        let res = query_stmt.query(&[]);
        if res.is_err() {
            error!("Error in query: {}", res.unwrap_err());
            thread::sleep(check_ms);
            continue;
        }

        let items = res.unwrap();
        if items.is_empty() {
            warn!("No video feeds");
            thread::sleep(check_ms);
            continue;
        }
        let item = items.get(0);
        let url: String = item.get("url");
        let when: postgres::Result<Timespec> = item.get_opt("lastRetrieved").unwrap();
        let id: i32 = item.get("id");
        let old_hash: postgres::Result<String> = item.get_opt("hash").unwrap();

        if when.is_err() {
            debug!("Item: {}, When: never", url);
        } else {
            let now = time::now().to_timespec();
            let diff: Duration = now - when.unwrap();
            debug!("Item: {}, When: {}", url, diff);
            if diff < interval {
                debug!("oldest item is young: {}", diff);
                thread::sleep(check_ms);
                continue;
            }
        }
        info!("Updating {}", url);

        let data: String = form_urlencoded::Serializer::new(String::new())
            .append_pair("url", &url)
            .finish();

        let raw_resp = Client::new()
                           .post(imager_url)
                           .header(ContentType::form_url_encoded())
                           .body(&data)
                           .send();

        if raw_resp.is_err() {
            warn!("{:?}", raw_resp.unwrap_err());
            warn!("Can't connect to imager");
            thread::sleep(check_ms);
            continue;
        }

        let mut resp = raw_resp.unwrap();

        if resp.status != StatusCode::Ok {
            warn!("{:?}", resp.status_raw());
            let now = time::now().to_timespec();
            not_working_stmt.execute(&[&now, &id]).unwrap();
            thread::sleep(check_ms);
            continue;
        }

        let extra: String = match resp.headers.get::<XExtra>() {
            Some(val) => val.to_string(),
            None => "{}".to_string()
        };

        let stream: String = match resp.headers.get::<XStream>() {
            Some(val) => val.to_string(),
            None => "".to_string()
        };

        let mut buf = Vec::new();
        resp.read_to_end(&mut buf).unwrap();
        let image = image::load_from_memory_with_format(&buf, ImageFormat::PNG).unwrap();
        let (width, height) = image.dimensions();
        if width == 0 || height == 0 {
            warn!("Dodgy image dimensions, skipping (width = {}, height = {})", width, height);
            let now = time::now().to_timespec();
            not_working_stmt.execute(&[&now, &id]).unwrap();
            thread::sleep(check_ms);
            continue;
        }
        let hash = ImageHash::hash(&image, 16, HashType::DoubleGradient);

        debug!("Image hash: {}", hash.to_base64());
        let motion: f64 = match old_hash {
            Ok(val) => {
                match ImageHash::from_base64(&val) {
                    Ok(val) => val.dist_ratio(&hash) as f64,
                    Err(_) => -1 as f64
                }
            },
            Err(_) => -1 as f64
        };
        debug!("Difference {}", motion);
        let now = time::now().to_timespec();
        match update_stmt.execute(&[&hash.to_base64(), &motion, &now, &extra, &stream, &id]) {
            Ok(_) => info!("Updated {} with motion {}", url, motion),
            Err(err) => warn!("Error executing update: {:?}", err),
        }
    }
}
<commit_msg>If we can't get the motion for a feed, set it to 0<commit_after>extern crate image;
extern crate img_hash;
extern crate postgres;
#[macro_use] extern crate log;
extern crate log4rs;
extern crate time;
#[macro_use] extern crate hyper;
extern crate url;
extern crate toml;

use std::env;
use postgres::{Connection, SslMode};
use img_hash::{ImageHash, HashType};
use std::thread;
use std::default::Default;
use time::{Timespec, Duration};
use hyper::Client;
use hyper::header::ContentType;
use image::ImageFormat;
use image::GenericImage;
use std::io::Read;
use hyper::status::StatusCode;
use postgres::stmt::Statement;
use std::fs::File;
use url::form_urlencoded;

header! { (XExtra, "X-Extra") => [String] }
header! { (XStream, "X-Stream") => [String] }

fn prepare_statement<'a>(conn: &'a Connection, stmt: &str) -> Statement<'a> {
    loop {
        let prep_stmt = conn.prepare_cached(stmt);
        if prep_stmt.is_err() {
            error!("Error in prepare for '{}': {}",
                   stmt,
                   prep_stmt.unwrap_err());
            thread::sleep(Duration::seconds(4).to_std().unwrap());
            continue;
        }
        return prep_stmt.unwrap();
    }
}

fn main() {
    let mut config_string = String::new();
    File::open("config.toml").unwrap().read_to_string(&mut config_string).unwrap();
    let mut parser = toml::Parser::new(&config_string);

    let config = parser.parse().unwrap();
    let config_table = config.get("config").unwrap();
    let interval = Duration::minutes(config_table.lookup("refresh_minutes")
                                                 .unwrap()
                                                 .as_integer()
                                                 .unwrap());
    let imager_url: &str = &(String::from(config_table.lookup("imager_host")
                                                      .unwrap()
                                                      .as_str()
                                                      .unwrap()) +
                             &String::from("/streams"));
    let check_ms = Duration::milliseconds(
        config_table.lookup("check_ms").unwrap().as_integer().unwrap())
        .to_std().unwrap();

    log4rs::init_file("log.toml", Default::default()).unwrap();
    let db_url: &str = &env::var("DATABASE_URL").unwrap();
    let conn = Connection::connect(db_url, SslMode::None).unwrap();

    let query_stmt = prepare_statement(&conn,
                                       "select * from videos_video order by \"lastRetrieved\" \
                                        asc limit 1");
    let update_stmt = prepare_statement(&conn,
                                        "update videos_video set working = true, hash = $1, \
                                         motion = $2, \"lastRetrieved\" = $3, extra = $4, \"streamURL\" = $5 where id = $6");
    let not_working_stmt = prepare_statement(&conn,
                                     "update videos_video set working = false, motion = 0, \"lastRetrieved\" = $1 where id = $2");

    info!("Connected to Postgres and ready to update video...");
    loop {
        let res = query_stmt.query(&[]);
        if res.is_err() {
            error!("Error in query: {}", res.unwrap_err());
            thread::sleep(check_ms);
            continue;
        }

        let items = res.unwrap();
        if items.is_empty() {
            warn!("No video feeds");
            thread::sleep(check_ms);
            continue;
        }
        let item = items.get(0);
        let url: String = item.get("url");
        let when: postgres::Result<Timespec> = item.get_opt("lastRetrieved").unwrap();
        let id: i32 = item.get("id");
        let old_hash: postgres::Result<String> = item.get_opt("hash").unwrap();

        if when.is_err() {
            debug!("Item: {}, When: never", url);
        } else {
            let now = time::now().to_timespec();
            let diff: Duration = now - when.unwrap();
            debug!("Item: {}, When: {}", url, diff);
            if diff < interval {
                debug!("oldest item is young: {}", diff);
                thread::sleep(check_ms);
                continue;
            }
        }
        info!("Updating {}", url);

        let data: String = form_urlencoded::Serializer::new(String::new())
            .append_pair("url", &url)
            .finish();

        let raw_resp = Client::new()
                           .post(imager_url)
                           .header(ContentType::form_url_encoded())
                           .body(&data)
                           .send();

        if raw_resp.is_err() {
            warn!("{:?}", raw_resp.unwrap_err());
            warn!("Can't connect to imager");
            thread::sleep(check_ms);
            continue;
        }

        let mut resp = raw_resp.unwrap();

        if resp.status != StatusCode::Ok {
            warn!("{:?}", resp.status_raw());
            let now = time::now().to_timespec();
            not_working_stmt.execute(&[&now, &id]).unwrap();
            thread::sleep(check_ms);
            continue;
        }

        let extra: String = match resp.headers.get::<XExtra>() {
            Some(val) => val.to_string(),
            None => "{}".to_string()
        };

        let stream: String = match resp.headers.get::<XStream>() {
            Some(val) => val.to_string(),
            None => "".to_string()
        };

        let mut buf = Vec::new();
        resp.read_to_end(&mut buf).unwrap();
        let image = image::load_from_memory_with_format(&buf, ImageFormat::PNG).unwrap();
        let (width, height) = image.dimensions();
        if width == 0 || height == 0 {
            warn!("Dodgy image dimensions, skipping (width = {}, height = {})", width, height);
            let now = time::now().to_timespec();
            not_working_stmt.execute(&[&now, &id]).unwrap();
            thread::sleep(check_ms);
            continue;
        }
        let hash = ImageHash::hash(&image, 16, HashType::DoubleGradient);

        debug!("Image hash: {}", hash.to_base64());
        let motion: f64 = match old_hash {
            Ok(val) => {
                match ImageHash::from_base64(&val) {
                    Ok(val) => val.dist_ratio(&hash) as f64,
                    Err(_) => -1 as f64
                }
            },
            Err(_) => -1 as f64
        };
        debug!("Difference {}", motion);
        let now = time::now().to_timespec();
        match update_stmt.execute(&[&hash.to_base64(), &motion, &now, &extra, &stream, &id]) {
            Ok(_) => info!("Updated {} with motion {}", url, motion),
            Err(err) => warn!("Error executing update: {:?}", err),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

use std::process::Command;
extern crate serde_json;
use serde_json::value::Value;

/// Simple call to a BANO load into ES base
/// Checks that we are able to find one object (a specific address)
pub fn osm2mimir_sample_test(es_wrapper: ::ElasticSearchWrapper) {
    let osm2mimir = concat!(env!("OUT_DIR"), "/../../../osm2mimir");
    let status = Command::new(osm2mimir)
                     .args(&["--input=./tests/fixtures/rues_trois_communes.osm.pbf".into(),
                             "--import-way".into(),
                             "--import-admin".into(),
                             "--level=8".into(),
                             format!("--connection-string={}", es_wrapper.host())])
                     .status()
                     .unwrap();
    assert!(status.success(), "`bano2mimir` failed {}", &status);
    es_wrapper.refresh();

    // Test: Import of Admin
    let city = es_wrapper.search("name:Livry-sur-Seine");
    let nb_hits = city.pointer("/hits/total").and_then(|v| v.as_u64()).unwrap_or(0);
    assert_eq!(nb_hits, 1);
    let city_type = city.pointer("/hits/hits/0/_type").and_then(|v| v.as_string()).unwrap_or("");
    assert_eq!(city_type, "admin");

    // Test: search for "Rue des Près"
    let search = es_wrapper.search(r#"name:Rue des Près"#);
    // The first hit should be "Rue des Près"
    let rue_name = search.pointer("/hits/hits/0/_source/name").and_then(|v| v.as_string()).unwrap_or("");
    assert_eq!(rue_name, r#"Rue des Près"#);
    // And there should be only ONE "Rue des Près"
    let street_filter = |street: &Value| {
    	         	let name = street.pointer("/_source/name").and_then(|n| n.as_string()).unwrap_or("");
    	            name == r#"Rue des Près"#
    			};
    let nb = es_wrapper.search_and_filter(r#"name:Rue des Près"#, street_filter).count();
    assert_eq!(nb, 1);

    // Test: Search for "Rue du Four à Chaux" in "Livry-sur-Seine"
    let street_filter = |street: &Value| {
    	            let name = street.pointer("/_source/name").and_then(|n| n.as_string()).unwrap_or("");
    	            let admin_name = street.pointer("/_source/administrative_regions/0/name").and_then(|n| n.as_string()).unwrap_or("");
    	            name == r#"Rue du Four à Chaux"# && admin_name == r#"Livry-sur-Seine"#
    			};
    let nb = es_wrapper.search_and_filter(r#"name:Rue du Four à Chaux"#, street_filter).count();
    assert_eq!(nb, 6);

    //Test: Streets having the same name in different cities
    let street_filter = |street: &Value| {
                        let name = street.pointer("/_source/name").and_then(|n| n.as_string()).unwrap_or("");
                        let admin_name = street.pointer("/_source/administrative_regions/0/name").and_then(|n| n.as_string()).unwrap_or("");
                        name == r#"Rue du Port"# && admin_name == r#"Melun"#
    			};
    let nb = es_wrapper.search_and_filter(r#"name:Rue du Port"#, street_filter).count();
    assert_eq!(nb, 1);
}
<commit_msg>fix test<commit_after>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

use std::process::Command;
extern crate serde_json;
use serde_json::value::Value;

/// Simple call to a BANO load into ES base
/// Checks that we are able to find one object (a specific address)
pub fn osm2mimir_sample_test(es_wrapper: ::ElasticSearchWrapper) {
    let osm2mimir = concat!(env!("OUT_DIR"), "/../../../osm2mimir");
    let status = Command::new(osm2mimir)
                     .args(&["--input=./tests/fixtures/rues_trois_communes.osm.pbf".into(),
                             "--import-way".into(),
                             "--import-admin".into(),
                             "--level=8".into(),
                             format!("--connection-string={}", es_wrapper.host())])
                     .status()
                     .unwrap();
    assert!(status.success(), "`bano2mimir` failed {}", &status);
    es_wrapper.refresh();

    // Test: Import of Admin
    let city = es_wrapper.search("name:Livry-sur-Seine");
    let nb_hits = city.lookup("hits.total").and_then(|v| v.as_u64()).unwrap_or(0);
    assert_eq!(nb_hits, 1);
    let city_type = city.pointer("/hits/hits/0/_type").and_then(|v| v.as_string()).unwrap_or("");
    assert_eq!(city_type, "admin");

    // Test: search for "Rue des Près"
    let search = es_wrapper.search(r#"name:Rue des Près"#);
    // The first hit should be "Rue des Près"
    let rue_name = search.pointer("/hits/hits/0/_source/name").and_then(|v| v.as_string()).unwrap_or("");
    assert_eq!(rue_name, r#"Rue des Près"#);
    // And there should be only ONE "Rue des Près"
    let street_filter = |street: &Value| {
    	         	let name = street.pointer("/_source/name").and_then(|n| n.as_string()).unwrap_or("");
    	            name == r#"Rue des Près"#
    			};
    let nb = es_wrapper.search_and_filter(r#"name:Rue des Près"#, street_filter).count();
    assert_eq!(nb, 1);

    // Test: Search for "Rue du Four à Chaux" in "Livry-sur-Seine"
    let street_filter = |street: &Value| {
    	            let name = street.pointer("/_source/name").and_then(|n| n.as_string()).unwrap_or("");
    	            let admin_name = street.pointer("/_source/administrative_regions/0/name").and_then(|n| n.as_string()).unwrap_or("");
    	            name == r#"Rue du Four à Chaux"# && admin_name == r#"Livry-sur-Seine"#
    			};
    let nb = es_wrapper.search_and_filter(r#"name:Rue du Four à Chaux"#, street_filter).count();
    assert_eq!(nb, 6);

    //Test: Streets having the same name in different cities
    let street_filter = |street: &Value| {
                        let name = street.pointer("/_source/name").and_then(|n| n.as_string()).unwrap_or("");
                        let admin_name = street.pointer("/_source/administrative_regions/0/name").and_then(|n| n.as_string()).unwrap_or("");
                        name == r#"Rue du Port"# && admin_name == r#"Melun"#
    			};
    let nb = es_wrapper.search_and_filter(r#"name:Rue du Port"#, street_filter).count();
    assert_eq!(nb, 1);
}
<|endoftext|>


<commit_before>#![feature(test)]
extern crate test;

use std::collections::VecDeque;

#[macro_use]
extern crate strider;
use strider::SliceRing;
use strider::SliceRingImpl;

#[bench]
fn bench_empty_to_probe_for_release_mode(b: &mut test::Bencher) {
    b.iter(|| 1)
}

macro_rules! bench_push_many_back {
    ($bencher:expr, $new:expr) => {{
        let vec = (0..1000).collect::<Vec<i32>>();
        $bencher.iter(|| {
            let mut testable = $new;
            testable.push_many_back(&vec[..]);
            testable
        });
    }}
}
#[bench]
fn bench_push_many_back_deque(b: &mut test::Bencher) {
    bench_push_many_back!(b, VecDeque::new());
}
#[bench]
fn bench_push_many_back_deque_with_capacity(b: &mut test::Bencher) {
    bench_push_many_back!(b, VecDeque::with_capacity(1000));
}
#[bench]
fn bench_push_many_back_optimized(b: &mut test::Bencher) {
    bench_push_many_back!(b, SliceRingImpl::new());
}
#[bench]
fn bench_push_many_back_optimized_with_capacity(b: &mut test::Bencher) {
    bench_push_many_back!(b, SliceRingImpl::with_capacity(1000));
}

macro_rules! bench_drop_many_front {
    ($bencher:expr, $new:expr) => {{
        let vec = (0..1000).collect::<Vec<i32>>();
        $bencher.iter(|| {
            let mut testable = $new;
            testable.push_many_back(&vec[..]);
            testable.drop_many_front(1000)
        });
    }}
}

#[bench]
fn bench_drop_many_front_deque(b: &mut test::Bencher) {
    bench_drop_many_front!(b, VecDeque::new());
}
#[bench]
fn bench_drop_many_front_deque_with_capacity(b: &mut test::Bencher) {
    bench_drop_many_front!(b, VecDeque::with_capacity(1000));
}
#[bench]
fn bench_drop_many_front_optimized(b: &mut test::Bencher) {
    bench_drop_many_front!(b, SliceRingImpl::new());
}
#[bench]
fn bench_drop_many_front_optimized_with_capacity(b: &mut test::Bencher) {
    bench_drop_many_front!(b, SliceRingImpl::with_capacity(1000));
}

macro_rules! bench_read_many_front {
    ($bencher:expr, $new:expr) => {{
        let mut output: Vec<i32> = std::iter::repeat(0).take(1000).collect();
        let vec = (0..1000).collect::<Vec<i32>>();
        let mut testable = $new;
        testable.push_many_back(&vec[..]);
        $bencher.iter(|| {
            testable.read_many_front(&mut output[..])
        });
    }}
}
#[bench]
fn bench_read_many_front_deque(b: &mut test::Bencher) {
    bench_read_many_front!(b, VecDeque::new());
}
#[bench]
fn bench_read_many_front_deque_with_capacity(b: &mut test::Bencher) {
    bench_read_many_front!(b, VecDeque::with_capacity(1000));
}
#[bench]
fn bench_read_many_front_optimized(b: &mut test::Bencher) {
    bench_read_many_front!(b, SliceRingImpl::new());
}
#[bench]
fn bench_read_many_front_optimized_with_capacity(b: &mut test::Bencher) {
    bench_read_many_front!(b, SliceRingImpl::with_capacity(1000));
}

#[bench]
fn bench_test_slice_ring_deque(b: &mut test::Bencher) {
    b.iter(|| {
        test_slice_ring!(VecDeque::<i32>::new());
    });
}
#[bench]
fn bench_test_slice_ring_optimized(b: &mut test::Bencher) {
    b.iter(|| {
        test_slice_ring!(SliceRingImpl::<i32>::new())
    });
}
#[macro_export]
macro_rules! bench_slice_ring_windowing {
    ($new:expr) => {{
        let window_size = 4096;
        let step_size = 512;
        let mut testable = $new;
        let input: Vec<i32> = std::iter::repeat(0).take(6000).collect();
        let mut output: Vec<i32> = std::iter::repeat(0).take(window_size).collect();
        for _ in 0..100 {
            testable.push_many_back(&input[..]);
            while testable.len() >= window_size {
                testable.read_many_front(&mut output[..]);
                testable.drop_many_front(step_size);
            }
        }
        testable
    }};
}
#[bench]
fn bench_slice_ring_windowing_deque(b: &mut test::Bencher) {
    b.iter(|| {
        bench_slice_ring_windowing!(VecDeque::<i32>::new());
    });
}
#[bench]
fn bench_slice_ring_windowing_optimized(b: &mut test::Bencher) {
    b.iter(|| {
        bench_slice_ring_windowing!(SliceRingImpl::<i32>::new())
    });
}
<commit_msg>add messy realworld benchmark/test and make it pass<commit_after>#![feature(test)]
extern crate test;

use std::collections::VecDeque;

#[macro_use]
extern crate strider;
use strider::SliceRing;
use strider::SliceRingImpl;

#[bench]
fn bench_empty_to_probe_for_release_mode(b: &mut test::Bencher) {
    b.iter(|| 1)
}

macro_rules! bench_push_many_back {
    ($bencher:expr, $new:expr) => {{
        let vec = (0..1000).collect::<Vec<i32>>();
        $bencher.iter(|| {
            let mut testable = $new;
            testable.push_many_back(&vec[..]);
            testable
        });
    }}
}
#[bench]
fn bench_push_many_back_deque(b: &mut test::Bencher) {
    bench_push_many_back!(b, VecDeque::new());
}
#[bench]
fn bench_push_many_back_deque_with_capacity(b: &mut test::Bencher) {
    bench_push_many_back!(b, VecDeque::with_capacity(1000));
}
#[bench]
fn bench_push_many_back_optimized(b: &mut test::Bencher) {
    bench_push_many_back!(b, SliceRingImpl::new());
}
#[bench]
fn bench_push_many_back_optimized_with_capacity(b: &mut test::Bencher) {
    bench_push_many_back!(b, SliceRingImpl::with_capacity(1000));
}

macro_rules! bench_drop_many_front {
    ($bencher:expr, $new:expr) => {{
        let vec = (0..1000).collect::<Vec<i32>>();
        $bencher.iter(|| {
            let mut testable = $new;
            testable.push_many_back(&vec[..]);
            testable.drop_many_front(1000)
        });
    }}
}

#[bench]
fn bench_drop_many_front_deque(b: &mut test::Bencher) {
    bench_drop_many_front!(b, VecDeque::new());
}
#[bench]
fn bench_drop_many_front_deque_with_capacity(b: &mut test::Bencher) {
    bench_drop_many_front!(b, VecDeque::with_capacity(1000));
}
#[bench]
fn bench_drop_many_front_optimized(b: &mut test::Bencher) {
    bench_drop_many_front!(b, SliceRingImpl::new());
}
#[bench]
fn bench_drop_many_front_optimized_with_capacity(b: &mut test::Bencher) {
    bench_drop_many_front!(b, SliceRingImpl::with_capacity(1000));
}

macro_rules! bench_read_many_front {
    ($bencher:expr, $new:expr) => {{
        let mut output: Vec<i32> = std::iter::repeat(0).take(1000).collect();
        let vec = (0..1000).collect::<Vec<i32>>();
        let mut testable = $new;
        testable.push_many_back(&vec[..]);
        $bencher.iter(|| {
            testable.read_many_front(&mut output[..])
        });
    }}
}
#[bench]
fn bench_read_many_front_deque(b: &mut test::Bencher) {
    bench_read_many_front!(b, VecDeque::new());
}
#[bench]
fn bench_read_many_front_deque_with_capacity(b: &mut test::Bencher) {
    bench_read_many_front!(b, VecDeque::with_capacity(1000));
}
#[bench]
fn bench_read_many_front_optimized(b: &mut test::Bencher) {
    bench_read_many_front!(b, SliceRingImpl::new());
}
#[bench]
fn bench_read_many_front_optimized_with_capacity(b: &mut test::Bencher) {
    bench_read_many_front!(b, SliceRingImpl::with_capacity(1000));
}

#[bench]
fn bench_test_slice_ring_deque(b: &mut test::Bencher) {
    b.iter(|| {
        test_slice_ring!(VecDeque::<i32>::new());
    });
}
#[bench]
fn bench_test_slice_ring_optimized(b: &mut test::Bencher) {
    b.iter(|| {
        test_slice_ring!(SliceRingImpl::<i32>::new())
    });
}
#[macro_export]
macro_rules! bench_slice_ring_windowing {
    ($new:expr) => {{
        let window_size = 4096;
        let step_size = 512;
        let mut testable = $new;
        let input: Vec<i32> = std::iter::repeat(0).take(6000).collect();
        let mut output: Vec<i32> = std::iter::repeat(0).take(window_size).collect();
        for _ in 0..100 {
            testable.push_many_back(&input[..]);
            while testable.len() >= window_size {
                testable.read_many_front(&mut output[..]);
                testable.drop_many_front(step_size);
            }
        }
        testable
    }};
}
#[bench]
fn bench_slice_ring_windowing_deque(b: &mut test::Bencher) {
    b.iter(|| {
        bench_slice_ring_windowing!(VecDeque::<i32>::new());
    });
}
#[bench]
fn bench_slice_ring_windowing_optimized(b: &mut test::Bencher) {
    b.iter(|| {
        bench_slice_ring_windowing!(SliceRingImpl::<i32>::new())
    });
}

#[macro_export]
macro_rules! bench_slice_ring_one_minute_audio {
    ($bencher:expr, $new:expr) => {{
        // we move this outside the bencher
        // to measure only the time taken by the
        // slice ring operations.
        // keep all allocations out of the benchmark iteration.
        let samples_per_second = 44100;
        let seconds = 60;
        let sample_count: usize = seconds * samples_per_second;
        // println!("sample_count = {}", sample_count);
        let samples = (0..(sample_count as i32)).collect::<Vec<i32>>();
        let input_slice_size = 10000;
        let window_size = 1024;
        let step_size = 512;

        // determine the output_size by
        // simulating just the indexes without data
        let mut output_size = 0;
        let mut input_index = 0;
        let mut output_index = 0;
        let mut ring_size = 0;
        while input_index < samples.len() {
            let input_range_start = input_index;
            let input_range_end = std::cmp::min(sample_count, input_index + input_slice_size);
            // push_many_back
            ring_size += input_range_end - input_range_start;
            while ring_size >= window_size {
                let output_range_start = output_index;
                let output_range_end = output_index + window_size;
                output_size += output_range_end - output_range_start;
                ring_size -= step_size;
                output_index += window_size;
            }
            input_index += input_slice_size;
        }
        // println!("output_size = {}", output_size);
        let mut output = std::iter::repeat(0).take(output_size).collect::<Vec<i32>>();
        // println!("output.len() = {}", output.len());
        let mut expected_output = Vec::<i32>::new();
        let mut expected_output_index = 0;
        while expected_output_index < sample_count {
            let range_start = expected_output_index as i32;
            let range_end = (expected_output_index + window_size) as i32;
            let mut range_vec = (range_start..range_end).collect::<Vec<i32>>();
            expected_output.append(&mut range_vec);
            expected_output_index += step_size;
        }
        // println!("expected_output.len() = {}", expected_output.len());
        $bencher.iter(|| {
            let mut testable = $new;
            let mut input_index = 0;
            let mut output_index = 0;
            while input_index < samples.len() {
                let input_range_start = input_index;
                let input_range_end = std::cmp::min(sample_count, input_index + input_slice_size);
                let input_slice =
                    &samples[input_range_start..input_range_end];
                testable.push_many_back(input_slice);
                while testable.len() >= window_size {
                    let output_range_start = output_index;
                    let output_range_end = output_index + window_size;
                    let output_slice =
                        &mut output[output_range_start..output_range_end];
                    testable.read_many_front(output_slice);
                    testable.drop_many_front(step_size);
                    output_index += window_size;
                }
                input_index += input_slice_size;
            }
            // println!("input_index = {}", input_index);
            // println!("output_index = {}", output_index);
            testable
        });
        for i in 0..output.len() {
            assert!(output[i] == expected_output[i], "{} != {} at {}", output[i], expected_output[i], i);
        }
        // assert_eq!(output.len(), expected_output.len());
    }};
}
#[bench]
fn bench_slice_ring_one_minute_audio_deque(b: &mut test::Bencher) {
    bench_slice_ring_one_minute_audio!(b, VecDeque::<i32>::new());
}
#[bench]
fn bench_slice_ring_one_minute_audio_optimized(b: &mut test::Bencher) {
    bench_slice_ring_one_minute_audio!(b, SliceRingImpl::<i32>::new());
}
<|endoftext|>


<commit_before>use board::*;
use std::io::{self, BufRead};

/* Modify board state */

//Allow something to draw a card
pub fn draw_card<'a>(player: &'a mut Player, max_id: &'a mut i32) {
    if player.deck.cards.len() > 0 {
        let mut topcard: Card = player.deck.cards.pop().unwrap();
        *max_id += 1;
        topcard.id = max_id.clone();
        println!("{}", topcard);
        player.hand.push(topcard);
    }
}

//Move a card from one location to another
pub fn move_card<'a>(id: &'a i32, curr_loc: &'a mut Vec<Card>, destination: &'a mut Vec<Card>) {
    //find the index
    let mut card: i32 = -1;
    for i in 0..curr_loc.len() {
        if curr_loc[i].id == id.clone() {
            card = i as i32;
            break;
        }
    }
    if card == -1{
        println!("Card doesnt exist");
    }
    else {
        //actually move the card
        destination.push(curr_loc.remove(card as usize));

        //Check for effects of card
        //for i in current_player.field.last().unwrap().clone().abilities {
        //    //TODO:
        //}
    }
}

// Attack a player right in the face with one of your cards
pub fn attack_face<'a>(attacker: &'a mut i32, mut target: &'a mut Player, mut you: &'a mut Player) {
    let mut index: i32 = -1;
    for i in 0..you.field.len() {
        if you.field[i].id == attacker.clone() { index = i as i32; }

    }
    if index < 0 {
        println!("Monster doesnt exist");}
    else {
        //trigger_abilities("on_player_attacked".to_owned(), &mut you.field[index as usize].clone(), &mut you, &mut target);

        target.health -= you.field[index as usize].attack;
    }
}

//Force two creatures to fight
pub fn attack<'a>(attacker: &'a i32, target: &'a i32, mut you: &'a mut Player, mut opponent: &'a mut Player) {
    //For the fighting we shouldnt need the players, but if someone has an ability that when it
    //dies do something to the rest of the field then we need it

    //turn the ids into an index. we can assume that the cards are all on the field
    let mut a_index: i32 = -1;
    for i in 0..you.field.len() {
        if you.field[i].id == attacker.clone() { a_index = i as i32; }
    }
    let mut t_index: i32 = -1;
    for i in 0..opponent.field.len() {
        if opponent.field[i].id == target.clone() { t_index = i as i32; }
    }

    //Check that this is valid
    if a_index > -1 && t_index > -1 {
        let a = a_index as usize;
        let t = t_index as usize;

        if !you.field[a].fatigued {

            //Check for on-combat abilities
            //trigger_abilities("on-combat".to_owned(), &mut you.field[a].clone(), &mut you, &mut opponent);
            //trigger_abilities("on-combat".to_owned(), &mut opponent.field[t].clone(), &mut opponent, &mut you);

            //actually do the dmg
            you.field[a].health -= opponent.field[t].attack;
            opponent.field[t].health -= you.field[a].attack;

            //Trigger on death
            //trigger_abilities("on-combat".to_owned(), &mut you.field[a].clone(), &mut you, &mut opponent);
            //trigger_abilities("on-combat".to_owned(), &mut opponent.field[t].clone(), &mut opponent, &mut you);

            //move bodies to the graveyard
            if you.field[a].health < 1 { move_card(&attacker, &mut you.field, &mut you.graveyard); }
            if opponent.field[t].health < 1 { move_card(&target, &mut opponent.field, &mut opponent.graveyard); }
        }
    }
}

fn get_index<'a>(id: &'a i32, location: &'a Vec<Card>) -> Option<i32> {
    let mut index = None;
    for i in 0..location.len() {
        if location[i].id == id.clone() {
            index = Some(i as i32)

        }
    }
    return index;
}

fn ask(message: String) -> String {
    //This will be sent to the current player
    println!("{}", message);
    let mut line = String::new();
    let stdin = io::stdin();
    stdin.lock().read_line(&mut line).expect("could not read line");
    return line.trim_right_matches("\r\n").to_string();
}
/* Abilities */

pub fn trigger_single<'a>(trigger: String, id: &i32, caster: &'a mut Player, target_owner: &'a mut Player) {

    //Get a reference to the card
    let mut card: Card = Card::default();
    let index_o = get_index(&id, &caster.field);
    let index_c = get_index(&id, &target_owner.field);
    if index_o.is_some() { card = caster.field[index_o.unwrap() as usize].clone();  }
    if index_c.is_some() { card = target_owner.field[index_c.unwrap()as usize].clone(); }

    //Check abilities
    for ability in card.clone().abilities {
        //If its the correct trigger type
        if ability.trigger == trigger {
            println!("activating {}", ability.name);
            //We know that the card is valid, and we have its index.
            //Things can only ever use thier effects when they are on the feild,
            //so we dont need to try and figure out where that is

            let effect:Vec<&str> = ability.effect.split_whitespace().collect();
            //attack's only valid target is another monster

            if effect[0].to_string() == "destroy" {
                //Figure out what card will be destroyed
                let t = ask("what monster do you want destroyed".to_owned());

                //Check both fields
                let index_c = get_index(&t.trim().parse::<i32>().unwrap(), &caster.field);
                let index_t = get_index(&t.trim().parse::<i32>().unwrap(), &target_owner.field);

                //if its your side
                if index_c.is_some() {
                    if ability.target == "target creature".to_owned() || ability.target == "ally creature".to_owned() {
                        move_card(&t.trim().parse::<i32>().unwrap(), &mut caster.field, &mut caster.graveyard);
                        //trigger_single("on_death".to_owned(), &id, &'a );
                    }
                }

                //If its on the opponents side
                else if index_t.is_some() {
                    if ability.target == "target enemy creature".to_owned() {
                        move_card(&t.trim().parse::<i32>().unwrap(), &mut target_owner.field, &mut target_owner.graveyard);
                        //trigger_single("on_death".to_owned());
                    }
                }
                else {
                    println!("invalid target");
                    break;
                }
            }
            //Modify ability
            else if effect[0].to_string() == "modify" {
                //effect[1] is the stat we are looking to change,
                //effect[2] is by how much we will change it
                if ability.target == "self" {
                    if index_o.is_some() {
                        modify_stat(&id, effect[1].to_owned(), effect[2].parse().unwrap_or(0), &mut caster.field);
                    }
                }
                else if ability.target == "target_creature" {
                    let tmp_id: String = ask("What id do you want to target".to_owned());
                    let target_id = tmp_id.parse::<i32>();

                    if target_id.is_ok() {
                        let is_ally = get_index(&target_id.clone().unwrap(), &caster.field);
                        if is_ally.is_some() {
                            modify_stat(&id, effect[1].to_owned(), effect[2].parse().unwrap_or(0), &mut caster.field);
                        }
                        else {
                            let is_ally = get_index(&target_id.unwrap(), &caster.field);
                            if is_ally.is_some() {
                                modify_stat(&id, effect[1].to_owned(), effect[2].parse().unwrap_or(0), &mut target_owner.field);
                            }
                        }
                    }
                }
                else if ability.target == "target_ally_creature" {
                    let tmp_id: String = ask("What id do you want to target".to_owned());
                    let target_id = tmp_id.parse::<i32>();

                    if target_id.is_ok() {
                        let is_ally = get_index(&target_id.clone().unwrap(), &caster.field);
                        if is_ally.is_some() {
                            modify_stat(&id, effect[1].to_owned(), effect[2].parse().unwrap_or(0), &mut caster.field);
                        }
                    }
                }
                else if ability.target == "target_enemy_creature" {
                    let tmp_id: String = ask("What id do you want to target".to_owned());
                    let target_id = tmp_id.parse::<i32>();

                    if target_id.is_ok() {
                        let is_ally = get_index(&target_id.unwrap(), &caster.field);
                        if is_ally.is_some() {
                            modify_stat(&id, effect[1].to_owned(), effect[2].parse().unwrap_or(0), &mut target_owner.field);
                        }
                    }
                }
                else if ability.target == "both_fields" {
                    for i  in 0..caster.field.len() {
                        modify_stat(&&caster.field[i].id.clone(), effect[1].to_owned(), effect[2].parse().unwrap_or(0), &mut caster.field);
                    }
                    for i in 0..target_owner.field.len() {
                        modify_stat(&&target_owner.field[i].id.clone(), effect[1].to_owned(), effect[2].parse().unwrap_or(0), &mut target_owner.field);
                    }
                }
                else if ability.target == "enemy_field" {
                    for i in 0..target_owner.field.len() {
                        modify_stat(&&target_owner.field[i].id.clone(), effect[1].to_owned(), effect[2].parse().unwrap_or(0), &mut target_owner.field);
                    }

                }
                else if ability.target == "ally_field" {
                    for i in 0..caster.field.len() {
                        modify_stat(&&caster.field[i].id.clone(), effect[1].to_owned(), effect[2].parse::<i32>().unwrap(), &mut caster.field);
                    }
                }
            }
        }
    }
}

pub fn modify_stat<'a>(id: &'a &i32, stat: String, amount: i32, location: &'a mut Vec<Card>) {
    let index = get_index(id, location);
    if index.is_some() {
        if stat == "health" { location[index.unwrap() as usize].health += amount; }
        else if stat == "attack" { location[index.unwrap() as usize].attack += amount; }
        else if stat == "durability" { location[index.unwrap() as usize].durability += amount; }
    }
    else {
        println!("Could not find creature");
    }
}

//Checks all creatures on a field
pub fn trigger_player<'a>(trigger: String, you: &'a mut Player, opponent: &'a mut Player) {}
//This will have the following triggers,
//on player_attacked
//on turn_start
//on turn_end

pub fn untill_turn_start<'a>(mut player: &'a mut Player) {

    player.field[0].abilities.remove(0);

    for i in &mut player.field {
        for j in 0..i.abilities.len() {
            if i.abilities[j].trigger == "untill_turn_start".to_owned() {
                i.abilities.remove(j);
            }
        }
    }
}
pub fn untill_turn_end<'a>(mut player: &'a mut Player) {

    player.field[0].abilities.remove(0);

    for i in &mut player.field {
        for j in 0..i.abilities.len() {
            if i.abilities[j].trigger == "untill_turn_end".to_owned() {
                i.abilities.remove(j);
            }
        }
    }
}

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

    #[test]
    fn test_move_card() {
        let card: Card = Card{name: "Test_card".to_owned(),  ..Card::default()};
        let mut hand: Vec<Card> = Vec::new();
        let mut field: Vec<Card> = Vec::new();
        hand.push(card.clone());
        move_card(&card.id, &mut hand, &mut field);
        assert!(field.last().unwrap().name == "Test_card");
    }

    #[test]
    fn test_ability_modify(){
        let buff: Ability = Ability{
            name: "buff 5 attack".to_owned(),
            level_requirement: 0,
            target: "enemy_field".to_owned(),
            trigger: "on_play".to_owned(),
            effect: "modify attack 5".to_owned()};

           let mut card: Card = Card{name: "Test_card".to_owned(), id: 1,  ..Card::default()};

           let card1 = Card{ attack: 0, id: 2, ..Card::default()};
           let mut card2: Card = card1.clone();
           card2.id = 3;

           card.abilities.push(buff);

           let mut d: Deck = Deck{cards: Vec::new(), name_of_deck: "deck".to_owned()};
           let mut p1: Player = create_player("p1".to_owned(), d.clone());
           let mut p2: Player = create_player("p2".to_owned(), d.clone());

           p1.field.push(card.clone());
           p2.field.push(card1);
           p2.field.push(card2);

           trigger_single("on_play".to_owned(), &card.id, &mut p1, &mut p2 );
           assert!(p2.field[0].attack == 5);
           assert!(p2.field[1].attack == 5);

    }
}
<commit_msg>triggering travis<commit_after>use board::*;
use std::io::{self, BufRead};

/* Modify board state */

//Allow something to draw a card
pub fn draw_card<'a>(player: &'a mut Player, max_id: &'a mut i32) {
    if player.deck.cards.len() > 0 {
        let mut topcard: Card = player.deck.cards.pop().unwrap();
        *max_id += 1;
        topcard.id = max_id.clone();
        println!("{}", topcard);
        player.hand.push(topcard);
    }
}

//Move a card from one location to another
pub fn move_card<'a>(id: &'a i32, curr_loc: &'a mut Vec<Card>, destination: &'a mut Vec<Card>) {
    //find the index
    let mut card: i32 = -1;
    for i in 0..curr_loc.len() {
        if curr_loc[i].id == id.clone() {
            card = i as i32;
            break;
        }
    }
    if card == -1{
        println!("Card doesnt exist");
    }
    else {
        //actually move the card
        destination.push(curr_loc.remove(card as usize));

        //Check for effects of card
        //for i in current_player.field.last().unwrap().clone().abilities {
        //    //TODO:
        //}
    }
}

// Attack a player right in the face with one of your cards
pub fn attack_face<'a>(attacker: &'a mut i32, mut target: &'a mut Player, mut you: &'a mut Player) {
    let mut index: i32 = -1;
    for i in 0..you.field.len() {
        if you.field[i].id == attacker.clone() { index = i as i32; }

    }
    if index < 0 {
        println!("Monster doesnt exist");}
    else {
        //trigger_abilities("on_player_attacked".to_owned(), &mut you.field[index as usize].clone(), &mut you, &mut target);

        target.health -= you.field[index as usize].attack;
    }
}

//Force two creatures to fight
pub fn attack<'a>(attacker: &'a i32, target: &'a i32, mut you: &'a mut Player, mut opponent: &'a mut Player) {
    //For the fighting we shouldnt need the players, but if someone has an ability that when it
    //dies do something to the rest of the field then we need it

    //turn the ids into an index. we can assume that the cards are all on the field
    let mut a_index: i32 = -1;
    for i in 0..you.field.len() {
        if you.field[i].id == attacker.clone() { a_index = i as i32; }
    }
    let mut t_index: i32 = -1;
    for i in 0..opponent.field.len() {
        if opponent.field[i].id == target.clone() { t_index = i as i32; }
    }

    //Check that this is valid
    if a_index > -1 && t_index > -1 {
        let a = a_index as usize;
        let t = t_index as usize;

        if !you.field[a].fatigued {

            //Check for on-combat abilities
            //trigger_abilities("on-combat".to_owned(), &mut you.field[a].clone(), &mut you, &mut opponent);
            //trigger_abilities("on-combat".to_owned(), &mut opponent.field[t].clone(), &mut opponent, &mut you);

            //actually do the dmg
            you.field[a].health -= opponent.field[t].attack;
            opponent.field[t].health -= you.field[a].attack;

            //Trigger on death
            //trigger_abilities("on-combat".to_owned(), &mut you.field[a].clone(), &mut you, &mut opponent);
            //trigger_abilities("on-combat".to_owned(), &mut opponent.field[t].clone(), &mut opponent, &mut you);

            //move bodies to the graveyard
            if you.field[a].health < 1 { move_card(&attacker, &mut you.field, &mut you.graveyard); }
            if opponent.field[t].health < 1 { move_card(&target, &mut opponent.field, &mut opponent.graveyard); }
        }
    }
}

fn get_index<'a>(id: &'a i32, location: &'a Vec<Card>) -> Option<i32> {
    let mut index = None;
    for i in 0..location.len() {
        if location[i].id == id.clone() {
            index = Some(i as i32)

        }
    }
    return index;
}

fn ask(message: String) -> String {
    //This will be sent to the current player
    println!("{}", message);
    let mut line = String::new();
    let stdin = io::stdin();
    stdin.lock().read_line(&mut line).expect("could not read line");
    return line.trim_right_matches("\r\n").to_string();
}
/* Abilities */

pub fn trigger_single<'a>(trigger: String, id: &i32, caster: &'a mut Player, target_owner: &'a mut Player) {

    //Get a reference to the card
    let mut card: Card = Card::default();
    let index_o = get_index(&id, &caster.field);
    let index_c = get_index(&id, &target_owner.field);
    if index_o.is_some() { card = caster.field[index_o.unwrap() as usize].clone();  }
    if index_c.is_some() { card = target_owner.field[index_c.unwrap()as usize].clone(); }

    //Check abilities
    for ability in card.clone().abilities {
        //If its the correct trigger type
        if ability.trigger == trigger {
            println!("activating {}", ability.name);
            //We know that the card is valid, and we have its index.
            //Things can only ever use thier effects when they are on the feild,
            //so we dont need to try and figure out where that is

            let effect:Vec<&str> = ability.effect.split_whitespace().collect();
            //attack's only valid target is another monster

            if effect[0].to_string() == "destroy" {
                //Figure out what card will be destroyed
                let t = ask("what monster do you want destroyed".to_owned());

                //Check both fields
                let index_c = get_index(&t.trim().parse::<i32>().unwrap(), &caster.field);
                let index_t = get_index(&t.trim().parse::<i32>().unwrap(), &target_owner.field);

                //if its your side
                if index_c.is_some() {
                    if ability.target == "target creature".to_owned() || ability.target == "ally creature".to_owned() {
                        move_card(&t.trim().parse::<i32>().unwrap(), &mut caster.field, &mut caster.graveyard);
                        //trigger_single("on_death".to_owned(), &id, &'a );
                    }
                }

                //If its on the opponents side
                else if index_t.is_some() {
                    if ability.target == "target enemy creature".to_owned() {
                        move_card(&t.trim().parse::<i32>().unwrap(), &mut target_owner.field, &mut target_owner.graveyard);
                        //trigger_single("on_death".to_owned());
                    }
                }
                else {
                    println!("invalid target");
                    break;
                }
            }
            //Modify ability
            else if effect[0].to_string() == "modify" {
                //effect[1] is the stat we are looking to change,
                //effect[2] is by how much we will change it
                if ability.target == "self" {
                    if index_o.is_some() {
                        modify_stat(&id, effect[1].to_owned(), effect[2].parse().unwrap_or(0), &mut caster.field);
                    }
                }
                else if ability.target == "target_creature" {
                    let tmp_id: String = ask("What id do you want to target".to_owned());
                    let target_id = tmp_id.parse::<i32>();

                    if target_id.is_ok() {
                        let is_ally = get_index(&target_id.clone().unwrap(), &caster.field);
                        if is_ally.is_some() {
                            modify_stat(&id, effect[1].to_owned(), effect[2].parse().unwrap_or(0), &mut caster.field);
                        }
                        else {
                            let is_ally = get_index(&target_id.unwrap(), &caster.field);
                            if is_ally.is_some() {
                                modify_stat(&id, effect[1].to_owned(), effect[2].parse().unwrap_or(0), &mut target_owner.field);
                            }
                        }
                    }
                }
                else if ability.target == "target_ally_creature" {
                    let tmp_id: String = ask("What id do you want to target".to_owned());
                    let target_id = tmp_id.parse::<i32>();

                    if target_id.is_ok() {
                        let is_ally = get_index(&target_id.clone().unwrap(), &caster.field);
                        if is_ally.is_some() {
                            modify_stat(&id, effect[1].to_owned(), effect[2].parse().unwrap_or(0), &mut caster.field);
                        }
                    }
                }
                else if ability.target == "target_enemy_creature" {
                    let tmp_id: String = ask("What id do you want to target".to_owned());
                    let target_id = tmp_id.parse::<i32>();

                    if target_id.is_ok() {
                        let is_ally = get_index(&target_id.unwrap(), &caster.field);
                        if is_ally.is_some() {
                            modify_stat(&id, effect[1].to_owned(), effect[2].parse().unwrap_or(0), &mut target_owner.field);
                        }
                    }
                }
                else if ability.target == "both_fields" {
                    for i  in 0..caster.field.len() {
                        modify_stat(&&caster.field[i].id.clone(), effect[1].to_owned(), effect[2].parse().unwrap_or(0), &mut caster.field);
                    }
                    for i in 0..target_owner.field.len() {
                        modify_stat(&&target_owner.field[i].id.clone(), effect[1].to_owned(), effect[2].parse().unwrap_or(0), &mut target_owner.field);
                    }
                }
                else if ability.target == "enemy_field" {
                    for i in 0..target_owner.field.len() {
                        modify_stat(&&target_owner.field[i].id.clone(), effect[1].to_owned(), effect[2].parse().unwrap_or(0), &mut target_owner.field);
                    }

                }
                else if ability.target == "ally_field" {
                    for i in 0..caster.field.len() {
                        modify_stat(&&caster.field[i].id.clone(), effect[1].to_owned(), effect[2].parse::<i32>().unwrap(), &mut caster.field);
                    }
                }
            }
        }
    }
}

pub fn modify_stat<'a>(id: &'a &i32, stat: String, amount: i32, location: &'a mut Vec<Card>) {
    let index = get_index(id, location);
    if index.is_some() {
        if stat == "health" { location[index.unwrap() as usize].health += amount; }
        else if stat == "attack" { location[index.unwrap() as usize].attack += amount; }
        else if stat == "durability" { location[index.unwrap() as usize].durability += amount; }
    }
    else {
        println!("Could not find creature");
    }
}

//Checks all creatures on a field
pub fn trigger_player<'a>(trigger: String, you: &'a mut Player, opponent: &'a mut Player) {}
//This will have the following triggers,
//on player_attacked
//on turn_start
//on turn_end

pub fn untill_turn_start<'a>(mut player: &'a mut Player) {

    player.field[0].abilities.remove(0);

    for i in &mut player.field {
        for j in 0..i.abilities.len() {
            if i.abilities[j].trigger == "untill_turn_start".to_owned() {
                i.abilities.remove(j);
            }
        }
    }
}
pub fn untill_turn_end<'a>(mut player: &'a mut Player) {

    player.field[0].abilities.remove(0);

    for i in &mut player.field {
        for j in 0..i.abilities.len() {
            if i.abilities[j].trigger == "untill_turn_end".to_owned() {
                i.abilities.remove(j);
            }
        }
    }
}

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

    #[test]
    fn test_move_card() {
        let card: Card = Card{name: "Test_card".to_owned(),  ..Card::default()};
        let mut hand: Vec<Card> = Vec::new();
        let mut field: Vec<Card> = Vec::new();
        hand.push(card.clone());
        move_card(&card.id, &mut hand, &mut field);
        assert!(field.last().unwrap().name == "Test_card");
    }

    #[test]
    fn test_ability_modify(){
        let buff: Ability = Ability{
            name: "buff 5 attack".to_owned(),
            level_requirement: 0,
            target: "enemy_field".to_owned(),
            trigger: "on_play".to_owned(),
            effect: "modify attack 5".to_owned()};

           let mut card: Card = Card{name: "Test_card".to_owned(), id: 1,  ..Card::default()};

           let card1 = Card{ attack: 0, id: 2, ..Card::default()};
           let mut card2: Card = card1.clone();
           card2.id = 3;

           card.abilities.push(buff);

           let mut d: Deck = Deck{cards: Vec::new(), name_of_deck: "deck".to_owned()};
           let mut p1: Player = create_player("p1".to_owned(), d.clone());
           let mut p2: Player = create_player("p2".to_owned(), d.clone());

           p1.field.push(card.clone());
           p2.field.push(card1);
           p2.field.push(card2);

           trigger_single("on_play".to_owned(), &card.id, &mut p1, &mut p2 );
           assert!(p2.field[0].attack == 5);
           assert!(p2.field[1].attack == 5);

    }
}
<|endoftext|>


<commit_before>extern crate image;
extern crate img_hash;
extern crate postgres;
#[macro_use]
extern crate log;
extern crate log4rs;
extern crate time;
extern crate hyper;
extern crate url;
extern crate png;

use std::env;
use postgres::{Connection, SslMode};
use img_hash::{ImageHash, HashType};
use std::thread;
use std::default::Default;
use time::{Timespec, Duration};
use hyper::Client;
use hyper::header::ContentType;
use image::ImageFormat;
use std::io::Read;
use hyper::status::StatusCode;
use postgres::stmt::Statement;

fn prepare_statement<'a>(conn: &'a Connection, stmt: &str) -> Statement<'a> {
    loop {
        let prep_stmt = conn.prepare_cached(stmt);
        if prep_stmt.is_err() {
            error!("Error in prepare for '{}': {}",
                   stmt,
                   prep_stmt.unwrap_err());
            thread::sleep_ms(4000);
            continue;
        }
        return prep_stmt.unwrap();
    }
}

fn main() {
    log4rs::init_file("log.toml", Default::default()).unwrap();
    let db_url: &str = &env::var("DATABASE_URL").unwrap();
    let conn = Connection::connect(db_url, &SslMode::None).unwrap();

    let query_stmt = prepare_statement(&conn,
                                       "select * from videos_video order by \"lastRetrieved\" \
                                        desc limit 1");
    let update_stmt = prepare_statement(&conn,
                                        "update videos_video set working = true, hash = $1, \
                                         motion = $2, \"lastRetrieved\" = $3 where id = $4");

    loop {
        let res = query_stmt.query(&[]);
        if res.is_err() {
            error!("Error in query: {}", res.unwrap_err());
            thread::sleep_ms(4000);
            continue;
        }

        let items = res.unwrap();
        if items.len() == 0 {
            warn!("No video feeds");
            thread::sleep_ms(4000);
            continue;
        }
        let item = items.get(0);
        let url: String = item.get("url");
        let when: postgres::Result<Timespec> = item.get_opt("lastRetrieved");
        let id: i32 = item.get("id");
        let old_hash_raw: postgres::Result<String> = item.get_opt("hash");
        let old_hash = ImageHash::from_base64(&old_hash_raw.unwrap());

        if when.is_err() {
            debug!("Item: {}, When: never", url);
        } else {
            let now = time::now().to_timespec();
            let diff: Duration = now - when.unwrap();
            debug!("Item: {}, When: {}", url, diff);
            if diff < Duration::minutes(1) {
                debug!("oldest item is young: {}", diff);
                thread::sleep_ms(4000);
                continue;
            }
        }
        info!("Updating {}", url);

        let mut options = vec![];
        options.push(("url".to_string(), &url));
        let data: &str = &url::form_urlencoded::serialize(&options);

        let mut resp = Client::new()
                           .post("http://imager:8000/streams")
                           .header(ContentType::form_url_encoded())
                           .body(data)
                           .send()
                           .unwrap();

        if resp.status != StatusCode::Ok {
            warn!("{:?}", resp.status_raw());
            thread::sleep_ms(4000);
            continue;
        }

        let mut buf = Vec::new();
        resp.read_to_end(&mut buf).unwrap();
        let image = image::load_from_memory_with_format(&buf, ImageFormat::PNG).unwrap();
        let hash = ImageHash::hash(&image, 16, HashType::DoubleGradient);

        debug!("Image hash: {}", hash.to_base64());
        let motion: f64 = match old_hash {
            Ok(val) => val.dist_ratio(&hash) as f64,
            Err(_) => -1 as f64,
        };
        debug!("Difference {}", motion);
        let now = time::now().to_timespec();
        match update_stmt.execute(&[&hash.to_base64(), &motion, &now, &id]) {
            Ok(_) => info!("Updated {} with motion {}", url, motion),
            Err(err) => warn!("Error executing update: {:?}", err),
        }
    }
}
<commit_msg>Add initial info statement to comparer<commit_after>extern crate image;
extern crate img_hash;
extern crate postgres;
#[macro_use]
extern crate log;
extern crate log4rs;
extern crate time;
extern crate hyper;
extern crate url;
extern crate png;

use std::env;
use postgres::{Connection, SslMode};
use img_hash::{ImageHash, HashType};
use std::thread;
use std::default::Default;
use time::{Timespec, Duration};
use hyper::Client;
use hyper::header::ContentType;
use image::ImageFormat;
use std::io::Read;
use hyper::status::StatusCode;
use postgres::stmt::Statement;

fn prepare_statement<'a>(conn: &'a Connection, stmt: &str) -> Statement<'a> {
    loop {
        let prep_stmt = conn.prepare_cached(stmt);
        if prep_stmt.is_err() {
            error!("Error in prepare for '{}': {}",
                   stmt,
                   prep_stmt.unwrap_err());
            thread::sleep_ms(4000);
            continue;
        }
        return prep_stmt.unwrap();
    }
}

fn main() {
    log4rs::init_file("log.toml", Default::default()).unwrap();
    let db_url: &str = &env::var("DATABASE_URL").unwrap();
    let conn = Connection::connect(db_url, &SslMode::None).unwrap();

    let query_stmt = prepare_statement(&conn,
                                       "select * from videos_video order by \"lastRetrieved\" \
                                        desc limit 1");
    let update_stmt = prepare_statement(&conn,
                                        "update videos_video set working = true, hash = $1, \
                                         motion = $2, \"lastRetrieved\" = $3 where id = $4");

    info!("Connected to Postgres and ready to update video...");
    loop {
        let res = query_stmt.query(&[]);
        if res.is_err() {
            error!("Error in query: {}", res.unwrap_err());
            thread::sleep_ms(4000);
            continue;
        }

        let items = res.unwrap();
        if items.len() == 0 {
            warn!("No video feeds");
            thread::sleep_ms(4000);
            continue;
        }
        let item = items.get(0);
        let url: String = item.get("url");
        let when: postgres::Result<Timespec> = item.get_opt("lastRetrieved");
        let id: i32 = item.get("id");
        let old_hash_raw: postgres::Result<String> = item.get_opt("hash");
        let old_hash = ImageHash::from_base64(&old_hash_raw.unwrap());

        if when.is_err() {
            debug!("Item: {}, When: never", url);
        } else {
            let now = time::now().to_timespec();
            let diff: Duration = now - when.unwrap();
            debug!("Item: {}, When: {}", url, diff);
            if diff < Duration::minutes(1) {
                debug!("oldest item is young: {}", diff);
                thread::sleep_ms(4000);
                continue;
            }
        }
        info!("Updating {}", url);

        let mut options = vec![];
        options.push(("url".to_string(), &url));
        let data: &str = &url::form_urlencoded::serialize(&options);

        let mut resp = Client::new()
                           .post("http://imager:8000/streams")
                           .header(ContentType::form_url_encoded())
                           .body(data)
                           .send()
                           .unwrap();

        if resp.status != StatusCode::Ok {
            warn!("{:?}", resp.status_raw());
            thread::sleep_ms(4000);
            continue;
        }

        let mut buf = Vec::new();
        resp.read_to_end(&mut buf).unwrap();
        let image = image::load_from_memory_with_format(&buf, ImageFormat::PNG).unwrap();
        let hash = ImageHash::hash(&image, 16, HashType::DoubleGradient);

        debug!("Image hash: {}", hash.to_base64());
        let motion: f64 = match old_hash {
            Ok(val) => val.dist_ratio(&hash) as f64,
            Err(_) => -1 as f64,
        };
        debug!("Difference {}", motion);
        let now = time::now().to_timespec();
        match update_stmt.execute(&[&hash.to_base64(), &motion, &now, &id]) {
            Ok(_) => info!("Updated {} with motion {}", url, motion),
            Err(err) => warn!("Error executing update: {:?}", err),
        }
    }
}
<|endoftext|>


<commit_before>mod advent_of_code;

use std::cmp::{max,min};
use std::io;
use std::io::BufRead;

// assume square
const KEYPAD_SIZE: i32 = 3;

#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
struct KeyPadPosition
{
    row: i32,
    column: i32,
}

impl KeyPadPosition
{
    fn bounded(number: i32)
        -> i32
    {
        return max(0, min(number, KEYPAD_SIZE - 1));
    }

    fn get_key(&self)
        -> char
    {
        // TODO: can this be global static?
        let pad: [[char; 3]; 3] = [
            ['1', '2', '3'],
            ['4', '5', '6'],
            ['7', '8', '9'],
        ];
        return pad[self.row as usize][self.column as usize];
    }

    fn move_up(&mut self)
    {
        self.row = Self::bounded(self.row - 1);
    }

    fn move_down(&mut self)
    {
        self.row = Self::bounded(self.row + 1);
    }

    fn move_right(&mut self)
    {
        self.column = Self::bounded(self.column + 1);
    }

    fn move_left(&mut self)
    {
        self.column = Self::bounded(self.column - 1);
    }
}

#[cfg(test)]
mod test
{
    use KeyPadPosition;
    use KEYPAD_SIZE;

    #[test]
    fn test_bounded_up_from_first_row()
    {
        let mut pos = KeyPadPosition { row: 0, column: 1 };
        let expected = pos.clone();
        pos.move_up();
        assert_eq!(pos, expected);
    }

    #[test]
    fn test_bounded_left_from_first_column()
    {
        let mut pos = KeyPadPosition { row: 1, column: 0 };
        let expected = pos.clone();
        pos.move_left();
        assert_eq!(pos, expected);
    }

    #[test]
    fn test_bounded_down_from_last_row()
    {
        let mut pos = KeyPadPosition { row: KEYPAD_SIZE - 1, column: 1 };
        let expected = pos.clone();
        pos.move_down();
        assert_eq!(pos, expected);
    }

    #[test]
    fn test_bounded_right_from_last_col()
    {
        let mut pos = KeyPadPosition { row: 1, column: KEYPAD_SIZE - 1 };
        let expected = pos.clone();
        pos.move_right();
        assert_eq!(pos, expected);
    }

    #[test]
    fn test_bounded_up_from_middle()
    {
        let mut pos = KeyPadPosition { row: 1, column: 1 };
        let expected = KeyPadPosition { row: 0, column: 1 };
        pos.move_up();
        assert_eq!(pos, expected);
    }

    #[test]
    fn test_bounded_left_from_middle()
    {
        let mut pos = KeyPadPosition { row: 1, column: 1 };
        let expected = KeyPadPosition { row: 1, column: 0 };
        pos.move_left();
        assert_eq!(pos, expected);
    }

    #[test]
    fn test_bounded_down_from_middle()
    {
        let mut pos = KeyPadPosition { row: 1, column: 1 };
        let expected = KeyPadPosition { row: 2, column: 1 };
        pos.move_down();
        assert_eq!(pos, expected);
    }

    #[test]
    fn test_bounded_right_from_middle()
    {
        let mut pos = KeyPadPosition { row: 1, column: 1 };
        let expected = KeyPadPosition { row: 1, column: 2 };
        pos.move_right();
        assert_eq!(pos, expected);
    }

    #[test]
    fn test_get_key_1()
    {
        let pos = KeyPadPosition { row: 0, column: 0 };
        let actual = pos.get_key();
        assert_eq!(actual, '1');
    }

    #[test]
    fn test_get_key_3()
    {
        let pos = KeyPadPosition { row: 0, column: 2 };
        let actual = pos.get_key();
        assert_eq!(actual, '3');
    }

    #[test]
    fn test_get_key_4()
    {
        let pos = KeyPadPosition { row: 1, column: 0 };
        let actual = pos.get_key();
        assert_eq!(actual, '4');
    }
}

#[cfg(not(test))]
fn main()
{
    let stdin = io::stdin();
    let mut pad_position = KeyPadPosition { row: 1, column: 1 };

    for line in stdin.lock().lines()
    {
        for chr in line.unwrap().chars()
        {
            if chr == 'U'
            {
                pad_position.move_up();
            }
            else if chr == 'D'
            {
                pad_position.move_down();
            }
            else if chr == 'R'
            {
                pad_position.move_right();
            }
            else if chr == 'L'
            {
                pad_position.move_left();
            }
            else
            {
                panic!("Unexpected character '{:?}'.", chr);
            }
        }
        let key = pad_position.get_key();
        print!("{}", key);
    }
    println!("");
}
<commit_msg>Convert KeyPadPosition to immutable<commit_after>mod advent_of_code;

use std::cmp::{max,min};
use std::io;
use std::io::BufRead;

// assume square
const KEYPAD_SIZE: i32 = 3;

#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
struct KeyPadPosition
{
    row: i32,
    column: i32,
}

impl KeyPadPosition
{
    fn bounded(number: i32)
        -> i32
    {
        return max(0, min(number, KEYPAD_SIZE - 1));
    }

    fn get_key(&self)
        -> char
    {
        // TODO: can this be global static?
        let pad: [[char; 3]; 3] = [
            ['1', '2', '3'],
            ['4', '5', '6'],
            ['7', '8', '9'],
        ];
        return pad[self.row as usize][self.column as usize];
    }

    fn moved_up(&self)
        -> KeyPadPosition
    {
        return KeyPadPosition {
            row: Self::bounded(self.row - 1),
            column: self.column,
        };
    }

    fn moved_down(&self)
        -> KeyPadPosition
    {
        return KeyPadPosition {
            row: Self::bounded(self.row + 1),
            column: self.column,
        };
    }

    fn moved_right(&self)
        -> KeyPadPosition
    {
        return KeyPadPosition {
            row: self.row,
            column: Self::bounded(self.column + 1),
        };
    }

    fn moved_left(&self)
        -> KeyPadPosition
    {
        return KeyPadPosition {
            row: self.row,
            column: Self::bounded(self.column - 1),
        };
    }
}

#[cfg(test)]
mod test
{
    use KeyPadPosition;
    use KEYPAD_SIZE;

    #[test]
    fn test_bounded_up_from_first_row()
    {
        let expected = KeyPadPosition { row: 0, column: 1 };
        let actual = expected.moved_up();
        assert_eq!(actual, expected);
    }

    #[test]
    fn test_bounded_left_from_first_column()
    {
        let expected = KeyPadPosition { row: 1, column: 0 };
        let actual = expected.moved_left();
        assert_eq!(actual, expected);
    }

    #[test]
    fn test_bounded_down_from_last_row()
    {
        let expected = KeyPadPosition { row: KEYPAD_SIZE - 1, column: 1 };
        let actual = expected.moved_down();
        assert_eq!(actual, expected);
    }

    #[test]
    fn test_bounded_right_from_last_col()
    {
        let expected = KeyPadPosition { row: 1, column: KEYPAD_SIZE - 1 };
        let actual = expected.moved_right();
        assert_eq!(actual, expected);
    }

    #[test]
    fn test_bounded_up_from_middle()
    {
        let pos = KeyPadPosition { row: 1, column: 1 };
        let expected = KeyPadPosition { row: 0, column: 1 };
        let actual = pos.moved_up();
        assert_eq!(actual, expected);
    }

    #[test]
    fn test_bounded_left_from_middle()
    {
        let pos = KeyPadPosition { row: 1, column: 1 };
        let expected = KeyPadPosition { row: 1, column: 0 };
        let actual = pos.moved_left();
        assert_eq!(actual, expected);
    }

    #[test]
    fn test_bounded_down_from_middle()
    {
        let pos = KeyPadPosition { row: 1, column: 1 };
        let expected = KeyPadPosition { row: 2, column: 1 };
        let actual = pos.moved_down();
        assert_eq!(actual, expected);
    }

    #[test]
    fn test_bounded_right_from_middle()
    {
        let pos = KeyPadPosition { row: 1, column: 1 };
        let expected = KeyPadPosition { row: 1, column: 2 };
        let actual = pos.moved_right();
        assert_eq!(actual, expected);
    }

    #[test]
    fn test_get_key_1()
    {
        let pos = KeyPadPosition { row: 0, column: 0 };
        let actual = pos.get_key();
        assert_eq!(actual, '1');
    }

    #[test]
    fn test_get_key_3()
    {
        let pos = KeyPadPosition { row: 0, column: 2 };
        let actual = pos.get_key();
        assert_eq!(actual, '3');
    }

    #[test]
    fn test_get_key_4()
    {
        let pos = KeyPadPosition { row: 1, column: 0 };
        let actual = pos.get_key();
        assert_eq!(actual, '4');
    }
}

#[cfg(not(test))]
fn main()
{
    let stdin = io::stdin();
    let mut pad_position = KeyPadPosition { row: 1, column: 1 };

    for line in stdin.lock().lines()
    {
        for chr in line.unwrap().chars()
        {
            if chr == 'U'
            {
                pad_position = pad_position.moved_up();
            }
            else if chr == 'D'
            {
                pad_position = pad_position.moved_down();
            }
            else if chr == 'R'
            {
                pad_position = pad_position.moved_right();
            }
            else if chr == 'L'
            {
                pad_position = pad_position.moved_left();
            }
            else
            {
                panic!("Unexpected character '{:?}'.", chr);
            }
        }
        let key = pad_position.get_key();
        print!("{}", key);
    }
    println!("");
}
<|endoftext|>