<commit_before>//
// Copyright (c) Pirmin Kalberer. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//

use datasource::DatasourceInput;
use gdal;
use gdal::vector::{Dataset, FieldValue};
use gdal_sys::ogr;
use core::feature::{Feature, FeatureAttr, FeatureAttrValType};
use core::geom::{self, GeometryType};
use core::grid::Extent;
use core::grid::Grid;
use core::layer::Layer;
use std::path::Path;

pub struct GdalDatasource {
    pub path: String,
}

impl GdalDatasource {
    pub fn new(path: &str) -> GdalDatasource {
        GdalDatasource { path: path.to_string() }
    }
}

struct CoreGeometryType(GeometryType);

impl CoreGeometryType {
    pub fn from_geom_field(feature: &gdal::vector::Feature,
                           srid: Option<i32>)
                           -> Result<GeometryType, String> {
        let ogrgeom = feature.geometry(); //FIXME: support for multiple geometry columns
        let geometry_type = unsafe { ogr::OGR_G_GetGeometryType(ogrgeom.c_geometry()) };
        match geometry_type {
            ogr::WKB_POINT => {
                let (x, y, _) = ogrgeom.get_point(0); //TODO: ZM support?
                Ok(GeometryType::Point(geom::Point {
                                           x: x,
                                           y: y,
                                           srid: srid,
                                       }))
            }
            _ => Err("TODO".to_string()),
        }
    }
}

struct VectorFeature<'a> {
    layer: &'a Layer,
    fields_defn: &'a Vec<gdal::vector::Field<'a>>,
    feature: &'a gdal::vector::Feature<'a>,
}

impl<'a> Feature for VectorFeature<'a> {
    fn fid(&self) -> Option<u64> {
        self.layer
            .fid_field
            .as_ref()
            .and_then(|fid| {
                          let field_value = self.feature.field(&fid);
                          match field_value {
                              Ok(FieldValue::IntegerValue(v)) => Some(v as u64),
                              _ => None,
                          }
                      })
    }
    fn attributes(&self) -> Vec<FeatureAttr> {
        let mut attrs = Vec::new();
        for (_i, field) in self.fields_defn.into_iter().enumerate() {
            let field_value = self.feature.field(&field.name()); //TODO: get by index
            let val = match field_value {
                Ok(FieldValue::StringValue(v)) => Some(FeatureAttrValType::String(v)),
                Ok(FieldValue::IntegerValue(v)) => Some(FeatureAttrValType::Int(v as i64)),
                Ok(FieldValue::RealValue(v)) => Some(FeatureAttrValType::Double(v)),
                Err(err) => {
                    warn!("Layer '{}' - skipping field '{}': {}",
                          self.layer.name,
                          field.name(),
                          err);
                    None
                }
            };
            // match field.field_type {
            //    OGRFieldType::OFTString => {
            if let Some(val) = val {
                let fattr = FeatureAttr {
                    key: field.name(),
                    value: val,
                };
                attrs.push(fattr);
            };
        }
        attrs
    }
    fn geometry(&self) -> Result<GeometryType, String> {
        let geom = CoreGeometryType::from_geom_field(&self.feature, self.layer.srid);
        if let Err(ref err) = geom {
            error!("Layer '{}': {}", self.layer.name, err);
        }
        geom
    }
}

impl DatasourceInput for GdalDatasource {
    fn retrieve_features<F>(&self,
                            layer: &Layer,
                            _extent: &Extent,
                            _zoom: u8,
                            _grid: &Grid,
                            mut read: F)
        where F: FnMut(&Feature)
    {
        let mut dataset = Dataset::open(Path::new(&self.path)).unwrap();
        let ogr_layer = dataset
            .layer_by_name(layer.table_name.as_ref().unwrap())
            .unwrap();
        let fields_defn = ogr_layer.defn().fields().collect::<Vec<_>>();
        for feature in ogr_layer.features() {
            let feat = VectorFeature {
                layer: layer,
                fields_defn: &fields_defn,
                feature: &feature,
            };
            read(&feat);
        }
    }
}

#[test]
fn test_gdal_api() {
    use std::path::Path;
    use gdal::vector::Dataset;

    let mut dataset = Dataset::open(Path::new("natural_earth.gpkg")).unwrap();
    let layer = dataset.layer_by_name("ne_10m_populated_places").unwrap();
    let feature = layer.features().next().unwrap();
    let name_field = feature.field("NAME").unwrap();
    let geometry = feature.geometry();
    assert_eq!(name_field.to_string(),
               Some("Colonia del Sacramento".to_string()));
    assert_eq!(geometry.wkt().unwrap(),
               "POINT (-6438719.62282072 -4093437.71441017)".to_string());
}

#[test]
fn test_gdal_retrieve() {
    let mut layer = Layer::new("points");
    layer.table_name = Some(String::from("ne_10m_populated_places"));
    layer.geometry_field = Some(String::from("wkb_geometry"));
    layer.srid = Some(3857);
    layer.fid_field = Some(String::from("SCALERANK"));
    layer.geometry_type = Some(String::from("POINT"));
    let grid = Grid::web_mercator();
    let extent = Extent {
        minx: 821850.9,
        miny: 5909499.5,
        maxx: 860986.7,
        maxy: 5948635.3,
    };

    let ds = GdalDatasource::new("natural_earth.gpkg");
    let mut reccnt = 0;
    ds.retrieve_features(&layer, &extent, 10, &grid, |feat| {
        if reccnt == 0 {
            assert_eq!("Ok(Point(Point { x: -6438719.622820721, y: -4093437.7144101723, srid: Some(3857) }))",
                       &*format!("{:?}", feat.geometry()));
        }
        assert_eq!(3, feat.attributes().len());
        assert_eq!(feat.attributes()[0].key, "SCALERANK");
        assert_eq!(feat.attributes()[1].key, "NAME");
        assert_eq!(feat.attributes()[2].key, "POP_MAX");
        if reccnt == 0 {
            assert_eq!(feat.attributes()[0].value, FeatureAttrValType::Int(10));
            assert_eq!(feat.attributes()[1].value,
                       FeatureAttrValType::String("Colonia del Sacramento".to_string()));
            assert_eq!(feat.attributes()[2].value, FeatureAttrValType::Int(21714));
            assert_eq!(Some(10), feat.fid());
        }
        reccnt += 1;
    });
    assert_eq!(14644, reccnt);
}
<commit_msg>Convert all OGR geometry types<commit_after>//
// Copyright (c) Pirmin Kalberer. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//

use datasource::DatasourceInput;
use gdal;
use gdal::vector::{Dataset, Geometry, FieldValue};
use gdal_sys::ogr;
use core::feature::{Feature, FeatureAttr, FeatureAttrValType};
use core::geom::{self, GeometryType};
use core::grid::Extent;
use core::grid::Grid;
use core::layer::Layer;
use std::path::Path;

pub struct GdalDatasource {
    pub path: String,
}

impl GdalDatasource {
    pub fn new(path: &str) -> GdalDatasource {
        GdalDatasource { path: path.to_string() }
    }
}

trait ToGeo {
    fn to_geo(&self, srid: Option<i32>) -> GeometryType;
}

impl ToGeo for Geometry {
    /// Convert OGR geomtry to t-rex EWKB geometry type (XY only)
    fn to_geo(&self, srid: Option<i32>) -> GeometryType {
        let geometry_type = unsafe { ogr::OGR_G_GetGeometryType(self.c_geometry()) };

        let ring = |n: usize| {
            let ring = unsafe { self._get_geometry(n) };
            return match ring.to_geo(srid) {
                       GeometryType::LineString(r) => r,
                       _ => panic!("Expected to get a LineString"),
                   };
        };

        match geometry_type {
            ogr::WKB_POINT => {
                let (x, y, _) = self.get_point(0); //TODO: ZM support?
                GeometryType::Point(geom::Point {
                                        x: x,
                                        y: y,
                                        srid: srid,
                                    })
            }
            ogr::WKB_MULTIPOINT => {
                let point_count = unsafe { ogr::OGR_G_GetGeometryCount(self.c_geometry()) } as
                                  usize;
                let coords = (0..point_count)
                    .map(|n| match unsafe { self._get_geometry(n) }.to_geo(srid) {
                             GeometryType::Point(p) => p,
                             _ => panic!("Expected to get a Point"),
                         })
                    .collect();
                GeometryType::MultiPoint(geom::MultiPoint {
                                             points: coords,
                                             srid: srid,
                                         })
            }
            ogr::WKB_LINESTRING => {
                let coords = self.get_point_vec()
                    .iter()
                    .map(|&(x, y, _)| {
                             geom::Point {
                                 x: x,
                                 y: y,
                                 srid: srid,
                             }
                         })
                    .collect();
                GeometryType::LineString(geom::LineString {
                                             points: coords,
                                             srid: srid,
                                         })
            }
            ogr::WKB_MULTILINESTRING => {
                let string_count = unsafe { ogr::OGR_G_GetGeometryCount(self.c_geometry()) } as
                                   usize;
                let strings = (0..string_count)
                    .map(|n| match unsafe { self._get_geometry(n) }.to_geo(srid) {
                             GeometryType::LineString(s) => s,
                             _ => panic!("Expected to get a LineString"),
                         })
                    .collect();
                GeometryType::MultiLineString(geom::MultiLineString {
                                                  lines: strings,
                                                  srid: srid,
                                              })
            }
            ogr::WKB_POLYGON => {
                let ring_count = unsafe { ogr::OGR_G_GetGeometryCount(self.c_geometry()) } as usize;
                let rings = (0..ring_count).map(|n| ring(n)).collect();
                GeometryType::Polygon(geom::Polygon {
                                          rings: rings,
                                          srid: srid,
                                      })
            }
            ogr::WKB_MULTIPOLYGON => {
                let string_count = unsafe { ogr::OGR_G_GetGeometryCount(self.c_geometry()) } as
                                   usize;
                let strings = (0..string_count)
                    .map(|n| match unsafe { self._get_geometry(n) }.to_geo(srid) {
                             GeometryType::Polygon(s) => s,
                             _ => panic!("Expected to get a Polygon"),
                         })
                    .collect();
                GeometryType::MultiPolygon(geom::MultiPolygon {
                                               polygons: strings,
                                               srid: srid,
                                           })
            }
            /* TODO:
            ogr::WKB_GEOMETRYCOLLECTION => {
                let item_count = unsafe { ogr::OGR_G_GetGeometryCount(self.c_geometry()) } as usize;
                let geometry_list = (0..item_count)
                    .map(|n| unsafe { self._get_geometry(n) }.to_geo(srid))
                    .collect();
                GeometryType::GeometryCollection(geom::GeometryCollection {
                                                     geometries: geometry_list,
                                                 })
            }
            */
            _ => panic!("Unknown geometry type"),
        }
    }
}

struct VectorFeature<'a> {
    layer: &'a Layer,
    fields_defn: &'a Vec<gdal::vector::Field<'a>>,
    feature: &'a gdal::vector::Feature<'a>,
}

impl<'a> Feature for VectorFeature<'a> {
    fn fid(&self) -> Option<u64> {
        self.layer
            .fid_field
            .as_ref()
            .and_then(|fid| {
                          let field_value = self.feature.field(&fid);
                          match field_value {
                              Ok(FieldValue::IntegerValue(v)) => Some(v as u64),
                              _ => None,
                          }
                      })
    }
    fn attributes(&self) -> Vec<FeatureAttr> {
        let mut attrs = Vec::new();
        for (_i, field) in self.fields_defn.into_iter().enumerate() {
            let field_value = self.feature.field(&field.name()); //TODO: get by index
            let val = match field_value {
                Ok(FieldValue::StringValue(v)) => Some(FeatureAttrValType::String(v)),
                Ok(FieldValue::IntegerValue(v)) => Some(FeatureAttrValType::Int(v as i64)),
                Ok(FieldValue::RealValue(v)) => Some(FeatureAttrValType::Double(v)),
                Err(err) => {
                    warn!("Layer '{}' - skipping field '{}': {}",
                          self.layer.name,
                          field.name(),
                          err);
                    None
                }
            };
            // match field.field_type {
            //    OGRFieldType::OFTString => {
            if let Some(val) = val {
                let fattr = FeatureAttr {
                    key: field.name(),
                    value: val,
                };
                attrs.push(fattr);
            };
        }
        attrs
    }
    fn geometry(&self) -> Result<GeometryType, String> {
        let ogrgeom = self.feature.geometry(); //FIXME: support for multiple geometry columns
        Ok(ogrgeom.to_geo(self.layer.srid))
    }
}

impl DatasourceInput for GdalDatasource {
    fn retrieve_features<F>(&self,
                            layer: &Layer,
                            _extent: &Extent,
                            _zoom: u8,
                            _grid: &Grid,
                            mut read: F)
        where F: FnMut(&Feature)
    {
        let mut dataset = Dataset::open(Path::new(&self.path)).unwrap();
        let ogr_layer = dataset
            .layer_by_name(layer.table_name.as_ref().unwrap())
            .unwrap();
        let fields_defn = ogr_layer.defn().fields().collect::<Vec<_>>();
        for feature in ogr_layer.features() {
            let feat = VectorFeature {
                layer: layer,
                fields_defn: &fields_defn,
                feature: &feature,
            };
            read(&feat);
        }
    }
}

#[test]
fn test_gdal_api() {
    use std::path::Path;
    use gdal::vector::Dataset;

    let mut dataset = Dataset::open(Path::new("natural_earth.gpkg")).unwrap();
    let layer = dataset.layer_by_name("ne_10m_populated_places").unwrap();
    let feature = layer.features().next().unwrap();
    let name_field = feature.field("NAME").unwrap();
    let geometry = feature.geometry();
    assert_eq!(name_field.to_string(),
               Some("Colonia del Sacramento".to_string()));
    assert_eq!(geometry.wkt().unwrap(),
               "POINT (-6438719.62282072 -4093437.71441017)".to_string());
}

#[test]
fn test_gdal_retrieve_points() {
    let mut layer = Layer::new("points");
    layer.table_name = Some(String::from("ne_10m_populated_places"));
    layer.geometry_field = Some(String::from("geom"));
    layer.srid = Some(3857);
    layer.fid_field = Some(String::from("SCALERANK"));
    layer.geometry_type = Some(String::from("POINT"));
    let grid = Grid::web_mercator();
    let extent = Extent {
        minx: 821850.9,
        miny: 5909499.5,
        maxx: 860986.7,
        maxy: 5948635.3,
    };

    let ds = GdalDatasource::new("natural_earth.gpkg");
    let mut reccnt = 0;
    ds.retrieve_features(&layer, &extent, 10, &grid, |feat| {
        if reccnt == 0 {
            assert_eq!("Ok(Point(Point { x: -6438719.622820721, y: -4093437.7144101723, srid: Some(3857) }))",
                       &*format!("{:?}", feat.geometry()));
        }
        assert_eq!(3, feat.attributes().len());
        assert_eq!(feat.attributes()[0].key, "SCALERANK");
        assert_eq!(feat.attributes()[1].key, "NAME");
        assert_eq!(feat.attributes()[2].key, "POP_MAX");
        if reccnt == 0 {
            assert_eq!(feat.attributes()[0].value, FeatureAttrValType::Int(10));
            assert_eq!(feat.attributes()[1].value,
                       FeatureAttrValType::String("Colonia del Sacramento".to_string()));
            assert_eq!(feat.attributes()[2].value, FeatureAttrValType::Int(21714));
            assert_eq!(Some(10), feat.fid());
        }
        reccnt += 1;
    });
    assert_eq!(14644, reccnt);
}

#[test]
fn test_gdal_retrieve_multilines() {
    let mut layer = Layer::new("multilines");
    layer.table_name = Some(String::from("ne_10m_rivers_lake_centerlines"));
    layer.geometry_field = Some(String::from("geom"));
    layer.srid = Some(3857);
    layer.geometry_type = Some(String::from("MULTILINE"));
    let grid = Grid::web_mercator();
    let extent = Extent {
        minx: 821850.9,
        miny: 5909499.5,
        maxx: 860986.7,
        maxy: 5948635.3,
    };

    let ds = GdalDatasource::new("natural_earth.gpkg");
    let mut reccnt = 0;
    ds.retrieve_features(&layer, &extent, 10, &grid, |feat| {
        if reccnt == 1398 {
            assert_eq!("Ok(MultiLineString(MultiLineStringT { lines: [LineStringT { points: [Point { x: 524057.9769470511, y: 6406083.8740046825, srid: Some(3857) }, Point { x: 523360.4182889238, y: 6406083.8740046825, srid: Some(3857) }], srid: Some(3857) }], srid: Some(3857) }))",
                       &*format!("{:?}", feat.geometry()));
        }
        assert_eq!(2, feat.attributes().len());
        assert_eq!(feat.attributes()[0].key, "scalerank");
        assert_eq!(feat.attributes()[1].key, "name");
        if reccnt == 1398 {
            assert_eq!(feat.attributes()[0].value, FeatureAttrValType::Double(8.0));
            assert_eq!(feat.attributes()[1].value,
                       FeatureAttrValType::String("Meuse".to_string()));
            assert_eq!(None, feat.fid());
        }
        reccnt += 1;
    });
    assert_eq!(1404, reccnt);
}

#[test]
fn test_gdal_retrieve_multipolys() {
    let mut layer = Layer::new("multipolys");
    layer.table_name = Some(String::from("ne_110m_admin_0_countries"));
    layer.geometry_field = Some(String::from("geom"));
    layer.srid = Some(3857);
    layer.geometry_type = Some(String::from("MULTIPOLYGON"));
    let grid = Grid::web_mercator();
    let extent = Extent {
        minx: 821850.9,
        miny: 5909499.5,
        maxx: 860986.7,
        maxy: 5948635.3,
    };

    let ds = GdalDatasource::new("natural_earth.gpkg");
    let mut reccnt = 0;
    ds.retrieve_features(&layer, &extent, 10, &grid, |feat| {
        if reccnt == 97 {
            assert_eq!("Ok(MultiPolygon(MultiPolygonT { polygons: [PolygonT { rings: [LineStringT { points: [Point { x: 672711.8490145913, y: 6468481.737381289, srid: Some(3857) }, Point { x: 694939.8727280691, y: 6429360.233285289, srid: Some(3857) }, Point { x: 688658.0399394701, y: 6353928.606103209, srid: Some(3857) }, Point { x: 656535.5543245667, y: 6350309.278097487, srid: Some(3857) }, Point { x: 631632.5743412259, y: 6365185.930146941, srid: Some(3857) }, Point { x: 643695.764229205, y: 6461933.756740372, srid: Some(3857) }, Point { x: 672711.8490145913, y: 6468481.737381289, srid: Some(3857) }], srid: Some(3857) }], srid: Some(3857) }], srid: Some(3857) }))",
                       &*format!("{:?}", feat.geometry()));
        }
        assert_eq!(2, feat.attributes().len());
        assert_eq!(feat.attributes()[0].key, "name");
        assert_eq!(feat.attributes()[1].key, "iso_a3");
        if reccnt == 97 {
            assert_eq!(feat.attributes()[0].value, FeatureAttrValType::String("Luxembourg".to_string()));
            assert_eq!(feat.attributes()[1].value,
                       FeatureAttrValType::String("LUX".to_string()));
            assert_eq!(None, feat.fid());
        }
        reccnt += 1;
    });
    assert_eq!(177, reccnt);
}
<|endoftext|>


<commit_before>pub const TILES_PCS_W: usize = 128;
pub const TILES_PCS_H: usize = 128;

pub const TILE_SIZE: f32 = 48.0;
pub const TILE_WIDTH: f32 = TILE_SIZE * 2.0;

pub const Y_OFFSET: f32 = TILES_PCS_W as f32 / 2.0 * TILE_WIDTH;

pub const CHARACTER_BUF_LENGTH: usize = 224;

pub const RESOLUTION_X: u32 = 1600;
pub const RESOLUTION_Y: u32 = 900;

pub const ASPECT_RATIO: f32 = (RESOLUTION_X / RESOLUTION_Y) as f32;

pub const VIEW_DISTANCE: f32 = 300.0;

pub const CHARACTER_SHEET_TOTAL_WIDTH: f32 = 16_128f32;
pub const SPRITE_OFFSET: f32 = 2.0;

pub const ZOMBIE_SHEET_TOTAL_WIDTH: f32 = 9_184f32;

pub const BULLET_SPEED: f32 = 15.0;
pub const CHARACTER_X_SPEED: f32 = 3.0;
pub const CHARACTER_Y_SPEED: f32 = 3.0;

pub const GAME_TITLE: &str = "Hinterland";

//Assets
pub const ZOMBIE_JSON_PATH: &str = "assets/zombie.json";
pub const CHARACTER_JSON_PATH: &str = "assets/character.json";
pub const PISTOL_AUDIO_PATH: &str = "assets/audio/pistol.ogg";
pub const MAP_FILE_PATH: &str = "assets/maps/tilemap.tmx";

pub const RUN_SPRITE_OFFSET: usize = 64;
pub const ZOMBIE_STILL_SPRITE_OFFSET: usize = 32;
pub const NORMAL_DEATH_SPRITE_OFFSET: usize = 64;

// Object positions
pub const AMMO_POSITIONS: [[i32; 2]; 4] = [ [ -13, -12 ], [ -15, 8 ], [ 16, -8 ], [ 1, 14 ] ];
pub const HOUSE_POSITIONS: [[i32; 2]; 2] = [[1, 17], [10, 5]];
pub const TREE_POSITIONS: [[i32; 2]; 5] = [[-11, -5], [8, -8], [-14, -11], [-18, -2], [-14, 3]];

pub const TERRAIN_OBJECTS: [[i32; 2]; 13] = [
    [ 55, 54 ], [ 56, 54 ],   // House A
    [ 55, 55 ], [ 56, 55 ],   // House A
    [ 66, 57 ], [ 67, 57 ],   // House B
    [ 66, 56 ], [ 67, 56 ],   // House B
    [ 72, 65 ], [ 61, 73 ], [ 63, 77 ], [ 56, 70 ], [ 56, 74 ]  // Trees
];

pub const SMALL_HILLS: [[i32; 2]; 4] = [[4, 2], [19, -2], [-14, -24], [30, 43]];

pub const GAME_VERSION: &str = "v0.3.12";

pub const HUD_TEXTS: [&str; 15] = [GAME_VERSION, "Ammo 0", "Ammo 1", "Ammo 2", "Ammo 3",
  "Ammo 4", "Ammo 5", "Ammo 6",
  "Ammo 7", "Ammo 8", "Ammo 9", "Ammo 10",
  "Magazines 0/2", "Magazines 1/2", "Magazines 2/2"];

pub const CURRENT_AMMO_TEXT: &str = "Ammo 10";
pub const CURRENT_MAGAZINE_TEXT: &str = "Magazines 2/2";
<commit_msg>Adjust hills<commit_after>pub const TILES_PCS_W: usize = 128;
pub const TILES_PCS_H: usize = 128;

pub const TILE_SIZE: f32 = 48.0;
pub const TILE_WIDTH: f32 = TILE_SIZE * 2.0;

pub const Y_OFFSET: f32 = TILES_PCS_W as f32 / 2.0 * TILE_WIDTH;

pub const CHARACTER_BUF_LENGTH: usize = 224;

pub const RESOLUTION_X: u32 = 1600;
pub const RESOLUTION_Y: u32 = 900;

pub const ASPECT_RATIO: f32 = (RESOLUTION_X / RESOLUTION_Y) as f32;

pub const VIEW_DISTANCE: f32 = 300.0;

pub const CHARACTER_SHEET_TOTAL_WIDTH: f32 = 16_128f32;
pub const SPRITE_OFFSET: f32 = 2.0;

pub const ZOMBIE_SHEET_TOTAL_WIDTH: f32 = 9_184f32;

pub const BULLET_SPEED: f32 = 15.0;
pub const CHARACTER_X_SPEED: f32 = 3.0;
pub const CHARACTER_Y_SPEED: f32 = 3.0;

pub const GAME_TITLE: &str = "Hinterland";

//Assets
pub const ZOMBIE_JSON_PATH: &str = "assets/zombie.json";
pub const CHARACTER_JSON_PATH: &str = "assets/character.json";
pub const PISTOL_AUDIO_PATH: &str = "assets/audio/pistol.ogg";
pub const MAP_FILE_PATH: &str = "assets/maps/tilemap.tmx";

pub const RUN_SPRITE_OFFSET: usize = 64;
pub const ZOMBIE_STILL_SPRITE_OFFSET: usize = 32;
pub const NORMAL_DEATH_SPRITE_OFFSET: usize = 64;

// Object positions
pub const AMMO_POSITIONS: [[i32; 2]; 4] = [ [ -13, -12 ], [ -15, 8 ], [ 16, -8 ], [ 1, 14 ] ];
pub const HOUSE_POSITIONS: [[i32; 2]; 2] = [[1, 17], [10, 5]];
pub const TREE_POSITIONS: [[i32; 2]; 5] = [[-11, -5], [8, -8], [-14, -11], [-18, -2], [-14, 3]];

pub const TERRAIN_OBJECTS: [[i32; 2]; 13] = [
    [ 55, 54 ], [ 56, 54 ],   // House A
    [ 55, 55 ], [ 56, 55 ],   // House A
    [ 66, 57 ], [ 67, 57 ],   // House B
    [ 66, 56 ], [ 67, 56 ],   // House B
    [ 72, 65 ], [ 61, 73 ], [ 63, 77 ], [ 56, 70 ], [ 56, 74 ]  // Trees
];

pub const SMALL_HILLS: [[i32; 2]; 3] = [[4, 2], [20, -2], [-14, -6]];

pub const GAME_VERSION: &str = "v0.3.12";

pub const HUD_TEXTS: [&str; 15] = [GAME_VERSION, "Ammo 0", "Ammo 1", "Ammo 2", "Ammo 3",
  "Ammo 4", "Ammo 5", "Ammo 6",
  "Ammo 7", "Ammo 8", "Ammo 9", "Ammo 10",
  "Magazines 0/2", "Magazines 1/2", "Magazines 2/2"];

pub const CURRENT_AMMO_TEXT: &str = "Ammo 10";
pub const CURRENT_MAGAZINE_TEXT: &str = "Magazines 2/2";
<|endoftext|>


<commit_before>#![allow(unused_variables)]

use super::color::{White, Black};
use super::piece::{mod, Piece, WK, WR, BK, BR};
use super::square::{Square,File,Rank};
use super::moves::{Move,Plies};
use super::pos::{Position,Kingside,Queenside};

pub fn make_move(mut p: Position, m: &Move) -> Position {
    make_move_mut(&mut p, m);
    p
}

pub fn make_move_mut(p: &mut Position, m: &Move) {
    let from = m.from();
    let to = m.to();
    let curr_piece = p.at(from).unwrap();

    if m.is_capture() || m.is_en_passant() || curr_piece.piece_type() == piece::Type::Pawn {
        p.set_ply_count_mut(Plies(0));
    } else {
        let Plies(temp) = p.ply_count();
        p.set_ply_count_mut(Plies(temp+1));
    }

    if m.is_castle() {

        //no en passant
        p.set_en_passant_mut(None);

        let castle_color = match from.rank() {
            Rank(0) => White,
            Rank(7) => Black,
            _ => panic!(),
        };
        let castle_side = match to.file() {
            File(2) => Queenside,
            File(6) => Kingside,
            _ => panic!(),
        };

        let (rook_from, rook_to) = match (castle_color, castle_side) {
            (White, Kingside ) => (Square::new(File(7),Rank(0)), Square::new(File(5),Rank(0))),
            (White, Queenside) => (Square::new(File(0),Rank(0)), Square::new(File(3),Rank(0))),
            (Black, Kingside ) => (Square::new(File(7),Rank(7)), Square::new(File(5),Rank(7))),
            (Black, Queenside) => (Square::new(File(0),Rank(7)), Square::new(File(3),Rank(7))),
        };

        p.remove_at_mut(from);
        p.set_at_mut(to, curr_piece);
        let curr_rook = p.at(rook_from).unwrap();
        p.remove_at_mut(rook_from);
        p.set_at_mut(rook_to, curr_rook);

    } else if m.is_en_passant() {

        //no en passant after this
        p.set_en_passant_mut(None);

        let captured = Square::new(to.file(), from.rank());

        p.remove_at_mut(captured);
        p.remove_at_mut(from);
        p.set_at_mut(to, curr_piece);

    } else if m.is_promote() {
        //no en passant
        p.set_en_passant_mut(None);

        //change the board and promote
        if m.is_capture() {
            p.remove_at_mut(to);
        }
        p.remove_at_mut(from);
        p.set_at_mut(to, Piece::new(curr_piece.color(), m.promote().unwrap()));
    } else {
        //TODO set enpassant

        //change the board
        if m.is_capture() {
            p.remove_at_mut(to);
        }
        p.remove_at_mut(from);
        p.set_at_mut(to, curr_piece);
    }

    //castling
    if p.at(Square::new(File(4),Rank(0))) != Some(WK) {
        p.set_castle_mut(Queenside, White, false);
        p.set_castle_mut(Kingside , White, false);
    }
    if p.at(Square::new(File(0),Rank(0))) != Some(WR) {
        p.set_castle_mut(Queenside, White, false);
    }
    if p.at(Square::new(File(7),Rank(0))) != Some(WR) {
        p.set_castle_mut(Kingside , White, false);
    }
    if p.at(Square::new(File(4),Rank(7))) != Some(BK) {
        p.set_castle_mut(Queenside, Black, false);
        p.set_castle_mut(Kingside , Black, false);
    }
    if p.at(Square::new(File(0),Rank(7))) != Some(BR) {
        p.set_castle_mut(Queenside, Black, false);
    }
    if p.at(Square::new(File(7),Rank(7))) != Some(BR) {
        p.set_castle_mut(Kingside , Black, false);
    }

    let next_color = p.side_to_move().invert();
    p.set_side_to_move_mut(next_color);
}
<commit_msg>Set en passant status in normal moves.<commit_after>#![allow(unused_variables)]

use super::color::{White, Black};
use super::piece::{mod, Piece, WK, WR, BK, BR};
use super::square::{Square,File,Rank};
use super::moves::{Move,Plies};
use super::pos::{Position,Kingside,Queenside};

pub fn make_move(mut p: Position, m: &Move) -> Position {
    make_move_mut(&mut p, m);
    p
}

pub fn make_move_mut(p: &mut Position, m: &Move) {
    let from = m.from();
    let to = m.to();
    let curr_piece = p.at(from).unwrap();

    if m.is_capture() || m.is_en_passant() || curr_piece.piece_type() == piece::Type::Pawn {
        p.set_ply_count_mut(Plies(0));
    } else {
        let Plies(temp) = p.ply_count();
        p.set_ply_count_mut(Plies(temp+1));
    }

    if m.is_castle() {

        //no en passant
        p.set_en_passant_mut(None);

        let castle_color = match from.rank() {
            Rank(0) => White,
            Rank(7) => Black,
            _ => panic!(),
        };
        let castle_side = match to.file() {
            File(2) => Queenside,
            File(6) => Kingside,
            _ => panic!(),
        };

        let (rook_from, rook_to) = match (castle_color, castle_side) {
            (White, Kingside ) => (Square::new(File(7),Rank(0)), Square::new(File(5),Rank(0))),
            (White, Queenside) => (Square::new(File(0),Rank(0)), Square::new(File(3),Rank(0))),
            (Black, Kingside ) => (Square::new(File(7),Rank(7)), Square::new(File(5),Rank(7))),
            (Black, Queenside) => (Square::new(File(0),Rank(7)), Square::new(File(3),Rank(7))),
        };

        p.remove_at_mut(from);
        p.set_at_mut(to, curr_piece);
        let curr_rook = p.at(rook_from).unwrap();
        p.remove_at_mut(rook_from);
        p.set_at_mut(rook_to, curr_rook);

    } else if m.is_en_passant() {

        //no en passant after this
        p.set_en_passant_mut(None);

        let captured = Square::new(to.file(), from.rank());

        p.remove_at_mut(captured);
        p.remove_at_mut(from);
        p.set_at_mut(to, curr_piece);

    } else if m.is_promote() {
        //no en passant
        p.set_en_passant_mut(None);

        //change the board and promote
        if m.is_capture() {
            p.remove_at_mut(to);
        }
        p.remove_at_mut(from);
        p.set_at_mut(to, Piece::new(curr_piece.color(), m.promote().unwrap()));
    } else {

        if m.is_pawn_double_move() {
            p.set_en_passant_mut(Some(to.file()));
        } else {
            p.set_en_passant_mut(None);
        }

        //change the board
        if m.is_capture() {
            p.remove_at_mut(to);
        }
        p.remove_at_mut(from);
        p.set_at_mut(to, curr_piece);
    }

    //castling
    if p.at(Square::new(File(4),Rank(0))) != Some(WK) {
        p.set_castle_mut(Queenside, White, false);
        p.set_castle_mut(Kingside , White, false);
    }
    if p.at(Square::new(File(0),Rank(0))) != Some(WR) {
        p.set_castle_mut(Queenside, White, false);
    }
    if p.at(Square::new(File(7),Rank(0))) != Some(WR) {
        p.set_castle_mut(Kingside , White, false);
    }
    if p.at(Square::new(File(4),Rank(7))) != Some(BK) {
        p.set_castle_mut(Queenside, Black, false);
        p.set_castle_mut(Kingside , Black, false);
    }
    if p.at(Square::new(File(0),Rank(7))) != Some(BR) {
        p.set_castle_mut(Queenside, Black, false);
    }
    if p.at(Square::new(File(7),Rank(7))) != Some(BR) {
        p.set_castle_mut(Kingside , Black, false);
    }

    let next_color = p.side_to_move().invert();
    p.set_side_to_move_mut(next_color);
}
<|endoftext|>


<commit_before>use bullet;
use character;
use critter::CharacterSprite;
use game::constants::{CURRENT_AMMO_TEXT, HUD_TEXTS, VERSION_NUMBER_TEXT};
use gfx;
use gfx_app::{ColorFormat, DepthFormat};
use gfx_app::renderer::EncoderQueue;
use graphics::{DeltaTime, orientation::Stance};
use graphics::Drawables;
use hud;
use specs;
use specs::prelude::{Read, WriteStorage};
use std::time::Instant;
use terrain;
use terrain_object;
use terrain_object::TerrainTexture;
use zombie;

pub struct DrawSystem<D: gfx::Device> {
  render_target_view: gfx::handle::RenderTargetView<D::Resources, ColorFormat>,
  depth_stencil_view: gfx::handle::DepthStencilView<D::Resources, DepthFormat>,
  terrain_system: terrain::TerrainDrawSystem<D::Resources>,
  character_system: character::CharacterDrawSystem<D::Resources>,
  zombie_system: zombie::ZombieDrawSystem<D::Resources>,
  bullet_system: bullet::BulletDrawSystem<D::Resources>,
  terrain_object_system: [terrain_object::TerrainObjectDrawSystem<D::Resources>; 3],
  text_system: [hud::TextDrawSystem<D::Resources>; 3],
  encoder_queue: EncoderQueue<D>,
  game_time: Instant,
  frames: u32,
  cool_down: f64,
  run_cool_down: f64,
  fire_cool_down: f64,
}

impl<D: gfx::Device> DrawSystem<D> {
  pub fn new<F>(factory: &mut F,
                rtv: &gfx::handle::RenderTargetView<D::Resources, ColorFormat>,
                dsv: &gfx::handle::DepthStencilView<D::Resources, DepthFormat>,
                encoder_queue: EncoderQueue<D>)
                -> DrawSystem<D>
                where F: gfx::Factory<D::Resources> {
    DrawSystem {
      render_target_view: rtv.clone(),
      depth_stencil_view: dsv.clone(),
      terrain_system: terrain::TerrainDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      character_system: character::CharacterDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      zombie_system: zombie::ZombieDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      bullet_system: bullet::BulletDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      terrain_object_system: [
        terrain_object::TerrainObjectDrawSystem::new(factory, rtv.clone(), dsv.clone(), TerrainTexture::Ammo),
        terrain_object::TerrainObjectDrawSystem::new(factory, rtv.clone(), dsv.clone(), TerrainTexture::House),
        terrain_object::TerrainObjectDrawSystem::new(factory, rtv.clone(), dsv.clone(), TerrainTexture::Tree)
      ],
      text_system: [
        hud::TextDrawSystem::new(factory, &HUD_TEXTS, VERSION_NUMBER_TEXT, rtv.clone(), dsv.clone()),
        hud::TextDrawSystem::new(factory, &HUD_TEXTS, CURRENT_AMMO_TEXT, rtv.clone(), dsv.clone()),
        hud::TextDrawSystem::new(factory, &HUD_TEXTS, CURRENT_AMMO_TEXT, rtv.clone(), dsv.clone())
      ],
      encoder_queue,
      game_time: Instant::now(),
      frames: 0,
      cool_down: 1.0,
      run_cool_down: 1.0,
      fire_cool_down: 1.0,
    }
  }
}

impl<'a, D> specs::prelude::System<'a> for DrawSystem<D>
  where D: gfx::Device,
        D::CommandBuffer: Send {

  type SystemData = (WriteStorage<'a, terrain::TerrainDrawable>,
                     WriteStorage<'a, character::CharacterDrawable>,
                     WriteStorage<'a, CharacterSprite>,
                     WriteStorage<'a, hud::hud_objects::HudObjects>,
                     WriteStorage<'a, zombie::zombies::Zombies>,
                     WriteStorage<'a, bullet::bullets::Bullets>,
                     WriteStorage<'a, terrain_object::terrain_objects::TerrainObjects>,
                     Read<'a, DeltaTime>);

  fn run(&mut self, (mut terrain, mut character, mut character_sprite, mut hud_objects, mut zombies, mut bullets, mut terrain_objects, dt): Self::SystemData) {
    use specs::join::Join;
    let mut encoder = self.encoder_queue.receiver.recv().unwrap();

    let delta = dt.0;

    if self.cool_down == 0.0 {
      self.cool_down += 0.05;
    }
    if self.fire_cool_down == 0.0 {
      self.fire_cool_down += 0.2;
    }
    if self.run_cool_down == 0.0 {
      self.run_cool_down += 0.02;
    }
    self.cool_down = (self.cool_down - delta).max(0.0);
    self.run_cool_down = (self.run_cool_down - delta).max(0.0);
    self.fire_cool_down = (self.fire_cool_down - delta).max(0.0);

    let current_time = Instant::now();
    self.frames += 1;
    if cfg!(feature = "framerate") && (current_time.duration_since(self.game_time).as_secs()) >= 1 {
      println!("{:?} ms/frames", 1000.0 / f64::from(self.frames));
      self.frames = 0;
      self.game_time = Instant::now();
    }

    encoder.clear(&self.render_target_view, [16.0 / 256.0, 16.0 / 256.0, 20.0 / 256.0, 1.0]);
    encoder.clear_depth(&self.depth_stencil_view, 1.0);

    for (t, c, cs, hds, zs, bs, obj) in (&mut terrain, &mut character, &mut character_sprite, &mut hud_objects,
                                         &mut zombies, &mut bullets, &mut terrain_objects).join() {
      if c.stance == Stance::Firing {
        self.terrain_system.draw(1, t, &mut encoder);
      } else {
        self.terrain_system.draw(0, t, &mut encoder);
      }

      for hud in &mut hds.objects {
        self.text_system[0].draw(hud, &mut encoder);
        self.text_system[1].draw(hud, &mut encoder);
      }

      if self.cool_down == 0.0 {
        if c.stance == Stance::Walking {
          cs.update_run();
        }
        for mut z in &mut zs.zombies {
          match z.stance {
            Stance::NormalDeath => z.update_death_idx(5),
            Stance::CriticalDeath => z.update_death_idx(7),
            Stance::Walking => z.update_alive_idx(7),
            Stance::Still => z.update_alive_idx(3),
            _ => ()
          };
        }
      } else if self.fire_cool_down == 0.0 && c.stance == Stance::Firing {
        cs.update_fire();
      }

      if self.run_cool_down == 0.0 {
        for mut z in &mut zs.zombies {
          if let Stance::Running = z.stance {
            z.update_alive_idx(7)
          }
        }
      }

      let mut drawables: Vec<Drawables> = vec![];
      drawables.append(&mut bs.bullets.iter().map(|b| Drawables::Bullet(b)).collect());
      drawables.append(&mut zs.zombies.iter_mut().map(|z| Drawables::Zombie(z)).collect());

      for o in &obj.objects {
        match o.object_type {
          TerrainTexture::Ammo => drawables.push(Drawables::TerrainAmmo(o)),
          TerrainTexture::House => drawables.push(Drawables::TerrainHouse(o)),
          TerrainTexture::Tree => drawables.push(Drawables::TerrainTree(o)),
        };
      }

      drawables.push(Drawables::Character(c));

      drawables.sort_by(|a, b| {
        Drawables::get_y(b)
          .partial_cmp(&Drawables::get_y(a))
          .unwrap()
      });

      for mut e in &mut drawables {
        match *e {
          Drawables::Bullet(ref e) => { self.bullet_system.draw(e, &mut encoder) },
          Drawables::Zombie(ref mut e) => { self.zombie_system.draw(e, &mut encoder) },
          Drawables::TerrainAmmo(ref mut e) => { self.terrain_object_system[0].draw(e, &mut encoder) },
          Drawables::TerrainHouse(ref mut e) => { self.terrain_object_system[1].draw(e, &mut encoder) },
          Drawables::TerrainTree(ref mut e) => { self.terrain_object_system[2].draw(e, &mut encoder) },
          Drawables::Character(ref mut e) => { self.character_system.draw(e, cs, &mut encoder) },
        }
      }
    }

    self.encoder_queue.sender.send(encoder);
  }
}
<commit_msg>Remove PoC code<commit_after>use bullet;
use character;
use critter::CharacterSprite;
use game::constants::{CURRENT_AMMO_TEXT, HUD_TEXTS, VERSION_NUMBER_TEXT};
use gfx;
use gfx_app::{ColorFormat, DepthFormat};
use gfx_app::renderer::EncoderQueue;
use graphics::{DeltaTime, orientation::Stance};
use graphics::Drawables;
use hud;
use specs;
use specs::prelude::{Read, WriteStorage};
use std::time::Instant;
use terrain;
use terrain_object;
use terrain_object::TerrainTexture;
use zombie;

pub struct DrawSystem<D: gfx::Device> {
  render_target_view: gfx::handle::RenderTargetView<D::Resources, ColorFormat>,
  depth_stencil_view: gfx::handle::DepthStencilView<D::Resources, DepthFormat>,
  terrain_system: terrain::TerrainDrawSystem<D::Resources>,
  character_system: character::CharacterDrawSystem<D::Resources>,
  zombie_system: zombie::ZombieDrawSystem<D::Resources>,
  bullet_system: bullet::BulletDrawSystem<D::Resources>,
  terrain_object_system: [terrain_object::TerrainObjectDrawSystem<D::Resources>; 3],
  text_system: [hud::TextDrawSystem<D::Resources>; 3],
  encoder_queue: EncoderQueue<D>,
  game_time: Instant,
  frames: u32,
  cool_down: f64,
  run_cool_down: f64,
  fire_cool_down: f64,
}

impl<D: gfx::Device> DrawSystem<D> {
  pub fn new<F>(factory: &mut F,
                rtv: &gfx::handle::RenderTargetView<D::Resources, ColorFormat>,
                dsv: &gfx::handle::DepthStencilView<D::Resources, DepthFormat>,
                encoder_queue: EncoderQueue<D>)
                -> DrawSystem<D>
                where F: gfx::Factory<D::Resources> {
    DrawSystem {
      render_target_view: rtv.clone(),
      depth_stencil_view: dsv.clone(),
      terrain_system: terrain::TerrainDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      character_system: character::CharacterDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      zombie_system: zombie::ZombieDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      bullet_system: bullet::BulletDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      terrain_object_system: [
        terrain_object::TerrainObjectDrawSystem::new(factory, rtv.clone(), dsv.clone(), TerrainTexture::Ammo),
        terrain_object::TerrainObjectDrawSystem::new(factory, rtv.clone(), dsv.clone(), TerrainTexture::House),
        terrain_object::TerrainObjectDrawSystem::new(factory, rtv.clone(), dsv.clone(), TerrainTexture::Tree)
      ],
      text_system: [
        hud::TextDrawSystem::new(factory, &HUD_TEXTS, VERSION_NUMBER_TEXT, rtv.clone(), dsv.clone()),
        hud::TextDrawSystem::new(factory, &HUD_TEXTS, CURRENT_AMMO_TEXT, rtv.clone(), dsv.clone()),
        hud::TextDrawSystem::new(factory, &HUD_TEXTS, CURRENT_AMMO_TEXT, rtv.clone(), dsv.clone())
      ],
      encoder_queue,
      game_time: Instant::now(),
      frames: 0,
      cool_down: 1.0,
      run_cool_down: 1.0,
      fire_cool_down: 1.0,
    }
  }
}

impl<'a, D> specs::prelude::System<'a> for DrawSystem<D>
  where D: gfx::Device,
        D::CommandBuffer: Send {

  type SystemData = (WriteStorage<'a, terrain::TerrainDrawable>,
                     WriteStorage<'a, character::CharacterDrawable>,
                     WriteStorage<'a, CharacterSprite>,
                     WriteStorage<'a, hud::hud_objects::HudObjects>,
                     WriteStorage<'a, zombie::zombies::Zombies>,
                     WriteStorage<'a, bullet::bullets::Bullets>,
                     WriteStorage<'a, terrain_object::terrain_objects::TerrainObjects>,
                     Read<'a, DeltaTime>);

  fn run(&mut self, (mut terrain, mut character, mut character_sprite, mut hud_objects, mut zombies, mut bullets, mut terrain_objects, dt): Self::SystemData) {
    use specs::join::Join;
    let mut encoder = self.encoder_queue.receiver.recv().unwrap();

    let delta = dt.0;

    if self.cool_down == 0.0 {
      self.cool_down += 0.05;
    }
    if self.fire_cool_down == 0.0 {
      self.fire_cool_down += 0.2;
    }
    if self.run_cool_down == 0.0 {
      self.run_cool_down += 0.02;
    }
    self.cool_down = (self.cool_down - delta).max(0.0);
    self.run_cool_down = (self.run_cool_down - delta).max(0.0);
    self.fire_cool_down = (self.fire_cool_down - delta).max(0.0);

    let current_time = Instant::now();
    self.frames += 1;
    if cfg!(feature = "framerate") && (current_time.duration_since(self.game_time).as_secs()) >= 1 {
      println!("{:?} ms/frames", 1000.0 / f64::from(self.frames));
      self.frames = 0;
      self.game_time = Instant::now();
    }

    encoder.clear(&self.render_target_view, [16.0 / 256.0, 16.0 / 256.0, 20.0 / 256.0, 1.0]);
    encoder.clear_depth(&self.depth_stencil_view, 1.0);

    for (t, c, cs, hds, zs, bs, obj) in (&mut terrain, &mut character, &mut character_sprite, &mut hud_objects,
                                         &mut zombies, &mut bullets, &mut terrain_objects).join() {
      self.terrain_system.draw(t, &mut encoder);

      for hud in &mut hds.objects {
        self.text_system[0].draw(hud, &mut encoder);
        self.text_system[1].draw(hud, &mut encoder);
      }

      if self.cool_down == 0.0 {
        if c.stance == Stance::Walking {
          cs.update_run();
        }
        for mut z in &mut zs.zombies {
          match z.stance {
            Stance::NormalDeath => z.update_death_idx(5),
            Stance::CriticalDeath => z.update_death_idx(7),
            Stance::Walking => z.update_alive_idx(7),
            Stance::Still => z.update_alive_idx(3),
            _ => ()
          };
        }
      } else if self.fire_cool_down == 0.0 && c.stance == Stance::Firing {
        cs.update_fire();
      }

      if self.run_cool_down == 0.0 {
        for mut z in &mut zs.zombies {
          if let Stance::Running = z.stance {
            z.update_alive_idx(7)
          }
        }
      }

      let mut drawables: Vec<Drawables> = vec![];
      drawables.append(&mut bs.bullets.iter().map(|b| Drawables::Bullet(b)).collect());
      drawables.append(&mut zs.zombies.iter_mut().map(|z| Drawables::Zombie(z)).collect());

      for o in &obj.objects {
        match o.object_type {
          TerrainTexture::Ammo => drawables.push(Drawables::TerrainAmmo(o)),
          TerrainTexture::House => drawables.push(Drawables::TerrainHouse(o)),
          TerrainTexture::Tree => drawables.push(Drawables::TerrainTree(o)),
        };
      }

      drawables.push(Drawables::Character(c));

      drawables.sort_by(|a, b| {
        Drawables::get_y(b)
          .partial_cmp(&Drawables::get_y(a))
          .unwrap()
      });

      for mut e in &mut drawables {
        match *e {
          Drawables::Bullet(ref e) => { self.bullet_system.draw(e, &mut encoder) },
          Drawables::Zombie(ref mut e) => { self.zombie_system.draw(e, &mut encoder) },
          Drawables::TerrainAmmo(ref mut e) => { self.terrain_object_system[0].draw(e, &mut encoder) },
          Drawables::TerrainHouse(ref mut e) => { self.terrain_object_system[1].draw(e, &mut encoder) },
          Drawables::TerrainTree(ref mut e) => { self.terrain_object_system[2].draw(e, &mut encoder) },
          Drawables::Character(ref mut e) => { self.character_system.draw(e, cs, &mut encoder) },
        }
      }
    }

    self.encoder_queue.sender.send(encoder);
  }
}
<|endoftext|>


<commit_before>use std::{
  iter::FromIterator,
  net::TcpListener,
  process,
  sync::mpsc,
  thread,
  time::Duration
};
use std::convert::Infallible;
use std::net::{IpAddr, SocketAddr};

use futures::channel::oneshot::channel;
use hyper::server::Server;
use hyper::service::make_service_fn;
use log::*;
use maplit::*;
use serde_json::{self, json, Value};
use uuid::Uuid;
use webmachine_rust::*;
use webmachine_rust::context::*;
use webmachine_rust::headers::*;

use pact_matching::models::{RequestResponsePact, load_pact_from_json};
use pact_mock_server::mock_server::MockServerConfig;
use pact_mock_server::tls::TlsConfigBuilder;

use crate::{SERVER_MANAGER, SERVER_OPTIONS, ServerOpts};
use crate::verify;

fn json_error(error: String) -> String {
    let json_response = json!({ "error" : json!(error) });
    json_response.to_string()
}

fn get_next_port(base_port: Option<u16>) -> u16 {
  match base_port {
    None => 0,
    Some(p) => if p > 0 {
      let mut port = p;
      let mut listener = TcpListener::bind(("127.0.0.1", port));
      while listener.is_err() && port < p + 1000 {
        port += 1;
        listener = TcpListener::bind(("127.0.0.1", port));
      }
      match listener {
        Ok(listener) => listener.local_addr().unwrap().port(),
        Err(_) => 0
      }
    } else {
      0
    }
  }
}

fn start_provider(context: &mut WebmachineContext, options: ServerOpts) -> Result<bool, u16> {
  debug!("start_provider => {}", context.request.request_path);
  match context.request.body {
    Some(ref body) if !body.is_empty() => {
      match serde_json::from_slice(body) {
        Ok(ref json) => {
          let pact = load_pact_from_json(&context.request.request_path, json)
            .map_err(|err| {
              error!("Failed to parse Pact JSON - {}", err);
              422_u16
            })?;
          debug!("Loaded pact = {:?}", pact);
          let mock_server_id = Uuid::new_v4().to_string();
          let config = MockServerConfig {
            cors_preflight: query_param_set(context, "cors")
          };
          debug!("Mock server config = {:?}", config);

          let mut guard = SERVER_MANAGER.lock().unwrap();
          let result = if query_param_set(context, "tls") {
            debug!("Starting TLS mock server with id {}", &mock_server_id);
            let key = include_str!("self-signed.key");
            let cert = include_str!("self-signed.cert");
            TlsConfigBuilder::new()
              .key(key.as_bytes())
              .cert(cert.as_bytes())
              .build()
              .map_err(|err| {
                format!("Failed to setup TLS using self-signed certificate - {}", err)
              })
              .and_then(|tls_config| {
                guard.start_tls_mock_server(mock_server_id.clone(), pact, get_next_port(options.base_port), &tls_config, config)
              })
          } else {
            debug!("Starting mock server with id {}", &mock_server_id);
            guard.start_mock_server(mock_server_id.clone(), pact, get_next_port(options.base_port), config)
          };
          match result {
            Ok(mock_server) => {
              debug!("mock server started on port {}", mock_server);
              let mock_server_json = json!({
                "id" : json!(mock_server_id),
                "port" : json!(mock_server as i64),
              });
              let json_response = json!({ "mockServer" : mock_server_json });
              context.response.body = Some(json_response.to_string().into_bytes());
              context.response.add_header("Location",
                vec![HeaderValue::basic(format!("/mockserver/{}", mock_server_id).as_str())]);
              Ok(true)
            },
            Err(msg) => {
              context.response.body = Some(json_error(format!("Failed to start mock server - {}", msg)).into_bytes());
              Err(422)
            }
          }
        },
        Err(err) => {
            log::error!("Failed to parse json body - {}", err);
            context.response.body = Some(json_error(format!("Failed to parse json body - {}", err)).into_bytes());
            Err(422)
        }
      }
    },
    _ => {
      log::error!("No pact json was supplied");
      context.response.body = Some(json_error("No pact json was supplied".to_string()).into_bytes());
      Err(422)
    }
  }
}

fn query_param_set(context: &mut WebmachineContext, name: &str) -> bool {
  context.request.query.get(name)
    .unwrap_or(&vec![]).first().unwrap_or(&String::default())
    .eq("true")
}

pub fn verify_mock_server_request(context: &mut WebmachineContext) -> Result<bool, u16> {
  let id = context.metadata.get("id").cloned().unwrap_or_default();
  match verify::validate_id(&id, &SERVER_MANAGER) {
    Ok(ms) => {
      let mut map = btreemap!{ "mockServer" => ms.to_json() };
      let mismatches = ms.mismatches();
      if !mismatches.is_empty() {
        map.insert("mismatches", json!(mismatches.iter().map(|m| m.to_json()).collect()));
        context.response.body = Some(json!(map).to_string().into_bytes());
        Err(422)
      } else {
        let inner = SERVER_OPTIONS.lock().unwrap();
        let options = inner.borrow();
        match ms.write_pact(&options.output_path, false) {
          Ok(_) => Ok(true),
          Err(err) => {
            map.insert("error", json!(format!("Failed to write pact to file - {}", err)));
            context.response.body = Some(json!(map).to_string().into_bytes());
            Err(422)
          }
        }
      }
    },
    Err(_) => Err(422)
  }
}

fn shutdown_resource<'a>() -> WebmachineResource<'a> {
  WebmachineResource {
    allowed_methods: vec!["POST"],
    forbidden: callback(&|context, _| {
      let options = SERVER_OPTIONS.lock().unwrap();
      !context.request.has_header_value(&"Authorization".to_owned(), &format!("Bearer {}", options.borrow().server_key))
    }),
    process_post: callback(&|context, _| {
      let shutdown_period = match context.request.body {
        Some(ref body) if !body.is_empty() => {
          match serde_json::from_slice::<Value>(body) {
            Ok(ref json) => match json.get("period") {
              Some(val) => match val.clone() {
                Value::Number(n) => Ok(n.as_u64().unwrap_or(100)),
                _ => Ok(100)
              },
              None => Ok(100)
            },
            Err(err) => {
              error!("Failed to parse json body - {}", err);
              context.response.body = Some(json_error(format!("Failed to parse json body - {}", err)).into_bytes());
              Err(422)
            }
          }
        }
        _ => Ok(100)
      };

      match shutdown_period {
        Ok(period) => {
          // Need to work out how to do this as the webmachine has to have a static lifetime
          // shutdown.send(()).unwrap_or_default();
          thread::spawn(move || {
            info!("Scheduling master server to shutdown in {}ms", period);
            thread::sleep(Duration::from_millis(period));
            info!("Shutting down");
            process::exit(0);
          });
          Ok(true)
        }
        Err(err) => Err(err)
      }
    }),
    ..WebmachineResource::default()
  }
}

fn mock_server_resource<'a>() -> WebmachineResource<'a> {
  WebmachineResource {
    allowed_methods: vec!["OPTIONS", "GET", "HEAD", "POST", "DELETE"],
    resource_exists: callback(&|context, _| {
      debug!("mock_server_resource -> resource_exists");
      let paths: Vec<String> = context.request.request_path
        .split('/')
        .filter(|p| !p.is_empty())
        .map(|p| p.to_string())
        .collect();
      if !paths.is_empty() && paths.len() <= 2 {
        match verify::validate_id(&paths[0].clone(), &SERVER_MANAGER) {
          Ok(ms) => {
            context.metadata.insert("id".to_string(), ms.id.clone());
            context.metadata.insert("port".to_string(), ms.port.unwrap_or_default().to_string());
            if paths.len() > 1 {
              context.metadata.insert("subpath".to_string(), paths[1].clone());
              paths[1] == "verify"
            } else {
              true
            }
          }
          Err(_) => false
        }
      } else {
        false
      }
    }),
    render_response: callback(&|context, _| {
      debug!("mock_server_resource -> render_response");
      match context.metadata.get("subpath") {
        None => {
          let id = context.metadata.get("id").unwrap().clone();
          SERVER_MANAGER.lock().unwrap().find_mock_server_by_id(&id, &|ms| ms.to_json())
            .map(|json| json.to_string())
        }
        Some(_) => {
          context.response.status = 405;
          None
        }
      }
    }),
    process_post: callback(&|context, _| {
      debug!("mock_server_resource -> process_post");
      let subpath = context.metadata.get("subpath").unwrap().clone();
      if subpath == "verify" {
        verify_mock_server_request(context)
      } else {
        Err(422)
      }
    }),
    delete_resource: callback(&|context, _| {
      debug!("mock_server_resource -> delete_resource");
      match context.metadata.get("subpath") {
        None => {
          let id = context.metadata.get("id").unwrap().clone();
          thread::spawn(move || {
            if SERVER_MANAGER.lock().unwrap().shutdown_mock_server_by_id(id) {
              Ok(true)
            } else {
              Err(404)
            }
          }).join().expect("Could not spawn thread to shut down mock server")
        }
        Some(_) => Err(405)
      }
    }),
    ..WebmachineResource::default()
  }
}

fn dispatcher() -> WebmachineDispatcher<'static>  {
  WebmachineDispatcher {
    routes: btreemap! {
      "/" => WebmachineResource {
        allowed_methods: vec!["OPTIONS", "GET", "HEAD", "POST"],
        resource_exists: callback(&|context, _| {
          debug!("main_resource -> resource_exists");
          context.request.request_path == "/"
        }),
        render_response: callback(&|_, _| {
          debug!("main_resource -> render_response");
          let mock_servers = SERVER_MANAGER.lock().unwrap().map_mock_servers(&|ms| {
            ms.to_json()
          });
          let json_response = json!({ "mockServers" : json!(mock_servers) });
          Some(json_response.to_string())
        }),
        process_post: callback(&|context, _| {
          debug!("main_resource -> process_post");
          let (tx, rx) = mpsc::channel();
          let (tx2, rx2) = mpsc::channel();

          if let Err(err) = tx.send(context.clone()) {
            error!("Failed to send context to start new mock server - {:?}", err);
            return Err(500)
          }
          let start_fn = move || {
            let handle = thread::current();
            debug!("starting mock server on thread {}", handle.name().unwrap_or("<unknown>"));
            let inner = SERVER_OPTIONS.lock().unwrap();
            let options = inner.borrow().clone();
            let mut ctx = rx.recv().unwrap();
            let result = start_provider(&mut ctx, options);
            debug!("Result of starting mock server: {:?}", result.clone());
            match tx2.send(ctx) {
              Ok(_) => result,
              Err(err) => {
                error!("Failed to send result back to main resource - {:?}", err);
                Err(500)
              }
            }
          };

          match thread::spawn(start_fn).join() {
            Ok(res) => {
              debug!("Result of thread: {:?}", res);
              let ctx = rx2.recv().unwrap();
              context.response = ctx.response;
              res
            },
            Err(err) => {
              error!("Failed to spawn new thread to start new mock server - {:?}", err);
              Err(500)
            }
          }
        }),
        .. WebmachineResource::default()
      },
      "/mockserver" => mock_server_resource(),
      "/shutdown" => shutdown_resource()
    }
  }
}

pub async fn start_server(port: u16) -> Result<(), i32> {
  let addr = SocketAddr::new(IpAddr::from([0, 0, 0, 0]), port);
  let (shutdown_tx, shutdown_rx) = channel::<()>();

  let make_svc = make_service_fn(|_| async {
    Ok::<_, Infallible>(dispatcher())
  });
  match Server::try_bind(&addr) {
    Ok(server) => {
      let server = server.serve(make_svc);
      {
        let inner = SERVER_OPTIONS.lock().unwrap();
        let options = inner.borrow();
        info!("Master server started on port {}", server.local_addr().port());
        info!("Server key: '{}'", options.server_key);
      }
      server.with_graceful_shutdown(async { shutdown_rx.await.unwrap_or_default() }).await.map_err(|err| {
        error!("Received an error starting master server: {}", err);
        2
      })
    },
    Err(err) => {
      error!("could not start master server: {}", err);
      Err(1)
    }
  }
}
<commit_msg>fix: clippy violation - caused a compiler error<commit_after>use std::{
  iter::FromIterator,
  net::TcpListener,
  process,
  sync::mpsc,
  thread,
  time::Duration
};
use std::convert::Infallible;
use std::net::{IpAddr, SocketAddr};

use futures::channel::oneshot::channel;
use hyper::server::Server;
use hyper::service::make_service_fn;
use log::*;
use maplit::*;
use serde_json::{self, json, Value};
use uuid::Uuid;
use webmachine_rust::*;
use webmachine_rust::context::*;
use webmachine_rust::headers::*;

use pact_matching::models::{RequestResponsePact, load_pact_from_json};
use pact_mock_server::mock_server::MockServerConfig;
use pact_mock_server::tls::TlsConfigBuilder;

use crate::{SERVER_MANAGER, SERVER_OPTIONS, ServerOpts};
use crate::verify;

fn json_error(error: String) -> String {
    let json_response = json!({ "error" : json!(error) });
    json_response.to_string()
}

fn get_next_port(base_port: Option<u16>) -> u16 {
  match base_port {
    None => 0,
    Some(p) => if p > 0 {
      let mut port = p;
      let mut listener = TcpListener::bind(("127.0.0.1", port));
      while listener.is_err() && port < p + 1000 {
        port += 1;
        listener = TcpListener::bind(("127.0.0.1", port));
      }
      match listener {
        Ok(listener) => listener.local_addr().unwrap().port(),
        Err(_) => 0
      }
    } else {
      0
    }
  }
}

fn start_provider(context: &mut WebmachineContext, options: ServerOpts) -> Result<bool, u16> {
  debug!("start_provider => {}", context.request.request_path);
  match context.request.body {
    Some(ref body) if !body.is_empty() => {
      match serde_json::from_slice(body) {
        Ok(ref json) => {
          let pact = load_pact_from_json(&context.request.request_path, json)
            .map_err(|err| {
              error!("Failed to parse Pact JSON - {}", err);
              422_u16
            })?;
          debug!("Loaded pact = {:?}", pact);
          let mock_server_id = Uuid::new_v4().to_string();
          let config = MockServerConfig {
            cors_preflight: query_param_set(context, "cors")
          };
          debug!("Mock server config = {:?}", config);

          let mut guard = SERVER_MANAGER.lock().unwrap();
          let result = if query_param_set(context, "tls") {
            debug!("Starting TLS mock server with id {}", &mock_server_id);
            let key = include_str!("self-signed.key");
            let cert = include_str!("self-signed.cert");
            TlsConfigBuilder::new()
              .key(key.as_bytes())
              .cert(cert.as_bytes())
              .build()
              .map_err(|err| {
                format!("Failed to setup TLS using self-signed certificate - {}", err)
              })
              .and_then(|tls_config| {
                guard.start_tls_mock_server(mock_server_id.clone(), pact, get_next_port(options.base_port), &tls_config, config)
              })
          } else {
            debug!("Starting mock server with id {}", &mock_server_id);
            guard.start_mock_server(mock_server_id.clone(), pact, get_next_port(options.base_port), config)
          };
          match result {
            Ok(mock_server) => {
              debug!("mock server started on port {}", mock_server);
              let mock_server_json = json!({
                "id" : json!(mock_server_id),
                "port" : json!(mock_server as i64),
              });
              let json_response = json!({ "mockServer" : mock_server_json });
              context.response.body = Some(json_response.to_string().into_bytes());
              context.response.add_header("Location",
                vec![HeaderValue::basic(format!("/mockserver/{}", mock_server_id).as_str())]);
              Ok(true)
            },
            Err(msg) => {
              context.response.body = Some(json_error(format!("Failed to start mock server - {}", msg)).into_bytes());
              Err(422)
            }
          }
        },
        Err(err) => {
            log::error!("Failed to parse json body - {}", err);
            context.response.body = Some(json_error(format!("Failed to parse json body - {}", err)).into_bytes());
            Err(422)
        }
      }
    },
    _ => {
      log::error!("No pact json was supplied");
      context.response.body = Some(json_error("No pact json was supplied".to_string()).into_bytes());
      Err(422)
    }
  }
}

fn query_param_set(context: &mut WebmachineContext, name: &str) -> bool {
  context.request.query.get(name)
    .unwrap_or(&vec![]).first().unwrap_or(&String::default())
    .eq("true")
}

pub fn verify_mock_server_request(context: &mut WebmachineContext) -> Result<bool, u16> {
  let id = context.metadata.get("id").cloned().unwrap_or_default();
  match verify::validate_id(&id, &SERVER_MANAGER) {
    Ok(ms) => {
      let mut map = btreemap!{ "mockServer" => ms.to_json() };
      let mismatches = ms.mismatches();
      if !mismatches.is_empty() {
        map.insert("mismatches", json!(mismatches.iter()
          .map(|m| m.to_json()).collect::<Vec<Value>>()));
        context.response.body = Some(json!(map).to_string().into_bytes());
        Err(422)
      } else {
        let inner = SERVER_OPTIONS.lock().unwrap();
        let options = inner.borrow();
        match ms.write_pact(&options.output_path, false) {
          Ok(_) => Ok(true),
          Err(err) => {
            map.insert("error", json!(format!("Failed to write pact to file - {}", err)));
            context.response.body = Some(json!(map).to_string().into_bytes());
            Err(422)
          }
        }
      }
    },
    Err(_) => Err(422)
  }
}

fn shutdown_resource<'a>() -> WebmachineResource<'a> {
  WebmachineResource {
    allowed_methods: vec!["POST"],
    forbidden: callback(&|context, _| {
      let options = SERVER_OPTIONS.lock().unwrap();
      !context.request.has_header_value(&"Authorization".to_owned(), &format!("Bearer {}", options.borrow().server_key))
    }),
    process_post: callback(&|context, _| {
      let shutdown_period = match context.request.body {
        Some(ref body) if !body.is_empty() => {
          match serde_json::from_slice::<Value>(body) {
            Ok(ref json) => match json.get("period") {
              Some(val) => match val.clone() {
                Value::Number(n) => Ok(n.as_u64().unwrap_or(100)),
                _ => Ok(100)
              },
              None => Ok(100)
            },
            Err(err) => {
              error!("Failed to parse json body - {}", err);
              context.response.body = Some(json_error(format!("Failed to parse json body - {}", err)).into_bytes());
              Err(422)
            }
          }
        }
        _ => Ok(100)
      };

      match shutdown_period {
        Ok(period) => {
          // Need to work out how to do this as the webmachine has to have a static lifetime
          // shutdown.send(()).unwrap_or_default();
          thread::spawn(move || {
            info!("Scheduling master server to shutdown in {}ms", period);
            thread::sleep(Duration::from_millis(period));
            info!("Shutting down");
            process::exit(0);
          });
          Ok(true)
        }
        Err(err) => Err(err)
      }
    }),
    ..WebmachineResource::default()
  }
}

fn mock_server_resource<'a>() -> WebmachineResource<'a> {
  WebmachineResource {
    allowed_methods: vec!["OPTIONS", "GET", "HEAD", "POST", "DELETE"],
    resource_exists: callback(&|context, _| {
      debug!("mock_server_resource -> resource_exists");
      let paths: Vec<String> = context.request.request_path
        .split('/')
        .filter(|p| !p.is_empty())
        .map(|p| p.to_string())
        .collect();
      if !paths.is_empty() && paths.len() <= 2 {
        match verify::validate_id(&paths[0].clone(), &SERVER_MANAGER) {
          Ok(ms) => {
            context.metadata.insert("id".to_string(), ms.id.clone());
            context.metadata.insert("port".to_string(), ms.port.unwrap_or_default().to_string());
            if paths.len() > 1 {
              context.metadata.insert("subpath".to_string(), paths[1].clone());
              paths[1] == "verify"
            } else {
              true
            }
          }
          Err(_) => false
        }
      } else {
        false
      }
    }),
    render_response: callback(&|context, _| {
      debug!("mock_server_resource -> render_response");
      match context.metadata.get("subpath") {
        None => {
          let id = context.metadata.get("id").unwrap().clone();
          SERVER_MANAGER.lock().unwrap().find_mock_server_by_id(&id, &|ms| ms.to_json())
            .map(|json| json.to_string())
        }
        Some(_) => {
          context.response.status = 405;
          None
        }
      }
    }),
    process_post: callback(&|context, _| {
      debug!("mock_server_resource -> process_post");
      let subpath = context.metadata.get("subpath").unwrap().clone();
      if subpath == "verify" {
        verify_mock_server_request(context)
      } else {
        Err(422)
      }
    }),
    delete_resource: callback(&|context, _| {
      debug!("mock_server_resource -> delete_resource");
      match context.metadata.get("subpath") {
        None => {
          let id = context.metadata.get("id").unwrap().clone();
          thread::spawn(move || {
            if SERVER_MANAGER.lock().unwrap().shutdown_mock_server_by_id(id) {
              Ok(true)
            } else {
              Err(404)
            }
          }).join().expect("Could not spawn thread to shut down mock server")
        }
        Some(_) => Err(405)
      }
    }),
    ..WebmachineResource::default()
  }
}

fn dispatcher() -> WebmachineDispatcher<'static>  {
  WebmachineDispatcher {
    routes: btreemap! {
      "/" => WebmachineResource {
        allowed_methods: vec!["OPTIONS", "GET", "HEAD", "POST"],
        resource_exists: callback(&|context, _| {
          debug!("main_resource -> resource_exists");
          context.request.request_path == "/"
        }),
        render_response: callback(&|_, _| {
          debug!("main_resource -> render_response");
          let mock_servers = SERVER_MANAGER.lock().unwrap().map_mock_servers(&|ms| {
            ms.to_json()
          });
          let json_response = json!({ "mockServers" : json!(mock_servers) });
          Some(json_response.to_string())
        }),
        process_post: callback(&|context, _| {
          debug!("main_resource -> process_post");
          let (tx, rx) = mpsc::channel();
          let (tx2, rx2) = mpsc::channel();

          if let Err(err) = tx.send(context.clone()) {
            error!("Failed to send context to start new mock server - {:?}", err);
            return Err(500)
          }
          let start_fn = move || {
            let handle = thread::current();
            debug!("starting mock server on thread {}", handle.name().unwrap_or("<unknown>"));
            let inner = SERVER_OPTIONS.lock().unwrap();
            let options = inner.borrow().clone();
            let mut ctx = rx.recv().unwrap();
            let result = start_provider(&mut ctx, options);
            debug!("Result of starting mock server: {:?}", result.clone());
            match tx2.send(ctx) {
              Ok(_) => result,
              Err(err) => {
                error!("Failed to send result back to main resource - {:?}", err);
                Err(500)
              }
            }
          };

          match thread::spawn(start_fn).join() {
            Ok(res) => {
              debug!("Result of thread: {:?}", res);
              let ctx = rx2.recv().unwrap();
              context.response = ctx.response;
              res
            },
            Err(err) => {
              error!("Failed to spawn new thread to start new mock server - {:?}", err);
              Err(500)
            }
          }
        }),
        .. WebmachineResource::default()
      },
      "/mockserver" => mock_server_resource(),
      "/shutdown" => shutdown_resource()
    }
  }
}

pub async fn start_server(port: u16) -> Result<(), i32> {
  let addr = SocketAddr::new(IpAddr::from([0, 0, 0, 0]), port);
  let (shutdown_tx, shutdown_rx) = channel::<()>();

  let make_svc = make_service_fn(|_| async {
    Ok::<_, Infallible>(dispatcher())
  });
  match Server::try_bind(&addr) {
    Ok(server) => {
      let server = server.serve(make_svc);
      {
        let inner = SERVER_OPTIONS.lock().unwrap();
        let options = inner.borrow();
        info!("Master server started on port {}", server.local_addr().port());
        info!("Server key: '{}'", options.server_key);
      }
      server.with_graceful_shutdown(async { shutdown_rx.await.unwrap_or_default() }).await.map_err(|err| {
        error!("Received an error starting master server: {}", err);
        2
      })
    },
    Err(err) => {
      error!("could not start master server: {}", err);
      Err(1)
    }
  }
}
<|endoftext|>


<commit_before><commit_msg>Update tests for new function field<commit_after><|endoftext|>


<commit_before>use crate::SQLPOINTER;

/// Governs behaviour of EnvironmentAttribute
#[repr(i32)]
#[allow(non_camel_case_types)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum EnvironmentAttribute {
    SQL_ATTR_ODBC_VERSION = 200,
    SQL_ATTR_CONNECTION_POOLING = 201,
    SQL_ATTR_CP_MATCH = 202,
    // This attribute was commented out because there is no mention of it in the ODBC
    // specification nor does this attribute exist in unixODBC or iODBC implementations.
    // This attribute exists in Microsoft implementation only and it's usage is unclear.
    // For private driver manager
    //SQL_ATTR_APPLICATION_KEY = 203,
    SQL_ATTR_OUTPUT_NTS = 10001,
}
pub use EnvironmentAttribute::*;

/// ODBC verions
///
/// Possible values for `SQL_ATTR_ODBC_VERSION` attribute set with `SQLSetEnvAttr` to
/// declare ODBC version
#[allow(non_camel_case_types)]
#[repr(i32)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SQL_ATTR_ODBC_VERSION {
    SQL_OV_ODBC2 = 2,
    SQL_OV_ODBC3 = 3,
    #[cfg(feature = "odbc_version_3_80")]
    SQL_OV_ODBC3_80 = 380,
    #[cfg(feature = "odbc_version_4")]
    SQL_OV_ODBC4 = 400,
}
pub use SQL_ATTR_ODBC_VERSION::*;

impl From<SQL_ATTR_ODBC_VERSION> for SQLPOINTER {
    fn from(source: SQL_ATTR_ODBC_VERSION) -> SQLPOINTER {
        source as i32 as SQLPOINTER
    }
}

/// Connection pool configuration
///
/// Possible values for `SQL_ATTR_CONNECTION_POOLING` attribute set with `SQLSetEnvAttr` to define
/// which pooling scheme will be used
#[allow(non_camel_case_types)]
#[repr(u32)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SQL_ATTR_CONNECTION_POOLING {
    SQL_CP_OFF = 0,
    SQL_CP_ONE_PER_DRIVER = 1,
    SQL_CP_ONE_PER_HENV = 2,
    SQL_CP_DRIVER_AWARE = 3,
}
pub use SQL_ATTR_CONNECTION_POOLING::*;

/// Connection pool default configuration
pub const SQL_CP_DEFAULT: SQL_ATTR_CONNECTION_POOLING = SQL_ATTR_CONNECTION_POOLING::SQL_CP_OFF;

impl From<SQL_ATTR_CONNECTION_POOLING> for SQLPOINTER {
    fn from(source: SQL_ATTR_CONNECTION_POOLING) -> SQLPOINTER {
        source as u32 as SQLPOINTER
    }
}

/// Matching of pooled connections
///
/// Possible values for `SQL_ATTR_CP_MATCH` attribute set with `SQLSetEnvAttr` to define
/// which connection attributes must match for a connection returned from the pool
#[allow(non_camel_case_types)]
#[repr(u32)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SQL_ATTR_CP_MATCH {
    SQL_CP_STRICT_MATCH = 0,
    SQL_CP_RELAXED_MATCH = 1,
}
pub use SQL_ATTR_CP_MATCH::*;

/// Default matching for connections returned from the pool
pub const SQL_CP_MATCH_DEFAULT: SQL_ATTR_CP_MATCH = SQL_ATTR_CP_MATCH::SQL_CP_STRICT_MATCH;

impl From<SQL_ATTR_CP_MATCH> for SQLPOINTER {
    fn from(source: SQL_ATTR_CP_MATCH) -> SQLPOINTER {
        source as u32 as SQLPOINTER
    }
}
<commit_msg>Implement Default trait for enums with default value<commit_after>use crate::SQLPOINTER;

pub use EnvironmentAttribute::*;
pub use SQL_ATTR_CONNECTION_POOLING::*;
pub use SQL_ATTR_CP_MATCH::*;
pub use SQL_ATTR_ODBC_VERSION::*;

/// Governs behaviour of EnvironmentAttribute
#[repr(i32)]
#[allow(non_camel_case_types)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum EnvironmentAttribute {
    SQL_ATTR_ODBC_VERSION = 200,
    SQL_ATTR_CONNECTION_POOLING = 201,
    SQL_ATTR_CP_MATCH = 202,
    // This attribute was commented out because there is no mention of it in the ODBC
    // specification nor does this attribute exist in unixODBC or iODBC implementations.
    // This attribute exists in Microsoft implementation only and it's usage is unclear.
    // For private driver manager
    //SQL_ATTR_APPLICATION_KEY = 203,
    SQL_ATTR_OUTPUT_NTS = 10001,
}

/// ODBC verions
///
/// Possible values for `SQL_ATTR_ODBC_VERSION` attribute set with `SQLSetEnvAttr` to
/// declare ODBC version
#[repr(i32)]
#[allow(non_camel_case_types)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SQL_ATTR_ODBC_VERSION {
    // Not supported by this crate
    // SQL_OV_ODBC2 = 2,
    SQL_OV_ODBC3 = 3,
    #[cfg(feature = "odbc_version_3_80")]
    SQL_OV_ODBC3_80 = 380,
    #[cfg(feature = "odbc_version_4")]
    SQL_OV_ODBC4 = 400,
}

impl From<SQL_ATTR_ODBC_VERSION> for SQLPOINTER {
    fn from(source: SQL_ATTR_ODBC_VERSION) -> SQLPOINTER {
        source as i32 as SQLPOINTER
    }
}
/// Connection pool configuration
///
/// Possible values for `SQL_ATTR_CONNECTION_POOLING` attribute set with `SQLSetEnvAttr` to define
/// which pooling scheme will be used
#[repr(u32)]
#[allow(non_camel_case_types)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SQL_ATTR_CONNECTION_POOLING {
    SQL_CP_OFF = 0,
    SQL_CP_ONE_PER_DRIVER = 1,
    SQL_CP_ONE_PER_HENV = 2,
    SQL_CP_DRIVER_AWARE = 3,
}

/// Connection pool default configuration
pub const SQL_CP_DEFAULT: SQL_ATTR_CONNECTION_POOLING = SQL_ATTR_CONNECTION_POOLING::SQL_CP_OFF;

impl Default for SQL_ATTR_CONNECTION_POOLING {
    fn default() -> Self {
        SQL_CP_DEFAULT
    }
}

impl From<SQL_ATTR_CONNECTION_POOLING> for SQLPOINTER {
    fn from(source: SQL_ATTR_CONNECTION_POOLING) -> SQLPOINTER {
        source as u32 as SQLPOINTER
    }
}

/// Matching of pooled connections
///
/// Possible values for `SQL_ATTR_CP_MATCH` attribute set with `SQLSetEnvAttr` to define
/// which connection attributes must match for a connection returned from the pool
#[repr(u32)]
#[allow(non_camel_case_types)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SQL_ATTR_CP_MATCH {
    SQL_CP_STRICT_MATCH = 0,
    SQL_CP_RELAXED_MATCH = 1,
}

/// Default matching for connections returned from the pool
pub const SQL_CP_MATCH_DEFAULT: SQL_ATTR_CP_MATCH = SQL_ATTR_CP_MATCH::SQL_CP_STRICT_MATCH;

impl Default for SQL_ATTR_CP_MATCH {
    fn default() -> Self {
        SQL_CP_MATCH_DEFAULT
    }
}

impl From<SQL_ATTR_CP_MATCH> for SQLPOINTER {
    fn from(source: SQL_ATTR_CP_MATCH) -> SQLPOINTER {
        source as u32 as SQLPOINTER
    }
}
<|endoftext|>


<commit_before>use std::rand;
use std::rand::Rng;

static radius : f32 = 0.005;

pub struct BackgroundElement{
    pub shape: Vec<f32>,
    pub color: Vec<f32>,
    pub x: f32,
    pub y: f32
}

pub struct Background{
    num : uint,
    shape: Vec<f32>,
    stars: Vec<(f32, f32)>,
    color: Vec<f32>
}

impl Background{
    pub fn new() -> Background{
        Background {
            num: 20,
            shape: vec!(
                0.0, -radius,
                radius, 0.0,
                -radius, 0.0,

                -radius, 0.0,
                radius, 0.0,
                0.0, radius
            ),
            color: vec!(0.45, 0.45, 0.3),
            stars: vec!()
        }
    }

    pub fn get(&self) -> Vec<BackgroundElement>{
        let mut output = vec!();
        for &(x, y) in self.stars.iter(){
            output.push(BackgroundElement{
                x:x,
                y:y,
                color: self.color.clone(),
                shape: self.shape.clone()
            });
        }
        output
    }

    pub fn generate(&mut self, (cx, cy):(f32,f32)){

        let minX = cx as i32 - 4000;
        let maxX = cx as i32 + 4000;
        let minY = cy as i32 - 4000;
        let maxY = cy as i32 + 4000;

        while self.stars.len() < self.num {
            let x = rand::task_rng().gen_range(minX, maxX) as f32;
            let y = rand::task_rng().gen_range(minY, maxY) as f32;

            self.stars.push((x, y));
        }
    }

    pub fn offscreen_generate(&mut self, (cx, cy):(f32,f32)){
        let minX = cx as i32 - 4000;
        let maxX = cx as i32 + 4000;
        let minY = cy as i32 - 4000;
        let maxY = cy as i32 + 4000;
        let min_distance = 2600 * 2600; // square instead of sqrt on distance

        while self.stars.len() < self.num {
            let x = rand::task_rng().gen_range(minX, maxX) as f32;
            let y = rand::task_rng().gen_range(minY, maxY) as f32;

            let x_dis = (x - cx) as i32;
            let y_dis = (y - cy) as i32;
            let distance = x_dis * x_dis + y_dis * y_dis;

            if distance > min_distance {
                self.stars.push((x, y));
            }
        }
    }

    pub fn cleanup(&mut self, (cx, cy):(f32, f32)){
        let threshold = 4000.0 * 4000.0;
        let mut output = vec!();

        for &pos in self.stars.iter(){
            let (x, y) = pos;
            let x_distance = x - cx;
            let y_distance = y - cy;
            let distance = x_distance * x_distance + y_distance * y_distance;
            if distance <= threshold{
                output.push(pos);
            }
        }

        self.stars = output;
    }
}

<commit_msg>refined background<commit_after>use std::rand;
use std::rand::Rng;

static radius : f32 = 0.008;

pub struct BackgroundElement{
    pub shape: Vec<f32>,
    pub color: Vec<f32>,
    pub x: f32,
    pub y: f32
}

pub struct Background{
    num : uint,
    shape: Vec<f32>,
    stars: Vec<(f32, f32)>,
    color: Vec<f32>
}

impl Background{
    pub fn new() -> Background{
        Background {
            num: 20,
            shape: vec!(
                0.0, -radius,
                radius, 0.0,
                -radius, 0.0,

                -radius, 0.0,
                radius, 0.0,
                0.0, radius
            ),
            color: vec!(0.5, 0.5, 0.4),
            stars: vec!()
        }
    }

    pub fn get(&self) -> Vec<BackgroundElement>{
        let mut output = vec!();
        for &(x, y) in self.stars.iter(){
            output.push(BackgroundElement{
                x:x,
                y:y,
                color: self.color.clone(),
                shape: self.shape.clone()
            });
        }
        output
    }

    pub fn generate(&mut self, (cx, cy):(f32,f32)){

        let minX = cx as i32 - 8000;
        let maxX = cx as i32 + 8000;
        let minY = cy as i32 - 8000;
        let maxY = cy as i32 + 8000;

        while self.stars.len() < self.num {
            let x = rand::task_rng().gen_range(minX, maxX) as f32;
            let y = rand::task_rng().gen_range(minY, maxY) as f32;

            self.stars.push((x, y));
        }
    }

    pub fn offscreen_generate(&mut self, (cx, cy):(f32,f32)){
        let minX = cx as i32 - 8000;
        let maxX = cx as i32 + 8000;
        let minY = cy as i32 - 8000;
        let maxY = cy as i32 + 8000;
        let min_distance = 5500 * 5500; // square instead of sqrt on distance

        while self.stars.len() < self.num {
            let x = rand::task_rng().gen_range(minX, maxX) as f32;
            let y = rand::task_rng().gen_range(minY, maxY) as f32;

            let x_dis = (x - cx) as i32;
            let y_dis = (y - cy) as i32;
            let distance = x_dis * x_dis + y_dis * y_dis;

            if distance > min_distance {
                self.stars.push((x, y));
            }
        }
    }

    pub fn cleanup(&mut self, (cx, cy):(f32, f32)){

        let threshold = 8000.0 * 8000.0;
        let mut output = vec!();

        for &pos in self.stars.iter(){
            let (x, y) = pos;
            let x_distance = x - cx;
            let y_distance = y - cy;
            let distance = x_distance * x_distance + y_distance * y_distance;
            if distance <= threshold{
                output.push(pos);
            }
        }

        self.stars = output;
    }
}

<|endoftext|>