<commit_before>use super::{Mesh, PointId};
use crate::shapes::Scratchpad;

/// Sets the matrix of coordinates (transposed) Xᵀ given a list of point ids
///
/// # Panics
///
/// 1. Make sure `pad.kind.nnode() == points.len()`; otherwise a panic will occur
/// 2. This function does not check for bounds on point indices and dimensions
/// 3. Use [crate::mesh::check_all()] to capture (some) errors
#[inline]
pub fn set_xxt_from_points(pad: &mut Scratchpad, points: &Vec<PointId>, mesh: &Mesh) {
    let nnode = pad.kind.nnode();
    assert_eq!(nnode, points.len());
    for m in 0..nnode {
        for j in 0..mesh.ndim {
            pad.set_xx(m, j, mesh.points[points[m]].coords[j]);
        }
    }
}

/// Returns the (min,max) point coordinates in a mesh
#[inline]
pub fn get_mesh_limits(mesh: &Mesh) -> (Vec<f64>, Vec<f64>) {
    let mut min = vec![f64::MAX; mesh.ndim];
    let mut max = vec![f64::MIN; mesh.ndim];
    for point in &mesh.points {
        for i in 0..mesh.ndim {
            min[i] = f64::min(min[i], point.coords[i]);
            max[i] = f64::max(max[i], point.coords[i]);
        }
    }
    (min, max)
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use super::{get_mesh_limits, set_xxt_from_points};
    use crate::mesh::Samples;
    use crate::shapes::Scratchpad;
    use crate::StrError;

    #[test]
    fn set_xxt_from_points_works_2d() -> Result<(), StrError> {
        //  3--------2--------5
        //  |        |        |
        //  |        |        |
        //  |        |        |
        //  0--------1--------4
        let mesh = Samples::two_quads_horizontal();
        let cell = &mesh.cells[0];
        let mut pad = Scratchpad::new(mesh.ndim, cell.kind)?;
        set_xxt_from_points(&mut pad, &cell.points, &mesh);
        assert_eq!(
            format!("{}", pad.xxt),
            "┌         ┐\n\
             │ 0 1 1 0 │\n\
             │ 0 0 1 1 │\n\
             └         ┘"
        );
        let cell = &mesh.cells[1];
        let mut pad = Scratchpad::new(mesh.ndim, cell.kind)?;
        set_xxt_from_points(&mut pad, &cell.points, &mesh);
        assert_eq!(
            format!("{}", pad.xxt),
            "┌         ┐\n\
             │ 1 2 2 1 │\n\
             │ 0 0 1 1 │\n\
             └         ┘"
        );
        Ok(())
    }

    #[test]
    fn set_xxt_from_points_works_3d() -> Result<(), StrError> {
        //       8-------------11
        //      /.             /|
        //     / .            / |
        //    /  .           /  |
        //   /   .          /   |
        //  9-------------10    |
        //  |    .         |    |
        //  |    4---------|----7
        //  |   /.         |   /|
        //  |  / .         |  / |
        //  | /  .         | /  |
        //  |/   .         |/   |
        //  5--------------6    |
        //  |    .         |    |
        //  |    0---------|----3
        //  |   /          |   /
        //  |  /           |  /
        //  | /            | /
        //  |/             |/
        //  1--------------2
        let mesh = Samples::two_cubes_vertical();
        let cell = &mesh.cells[0];
        let mut pad = Scratchpad::new(mesh.ndim, cell.kind)?;
        set_xxt_from_points(&mut pad, &cell.points, &mesh);
        assert_eq!(
            format!("{}", pad.xxt),
            "┌                 ┐\n\
             │ 0 1 1 0 0 1 1 0 │\n\
             │ 0 0 1 1 0 0 1 1 │\n\
             │ 0 0 0 0 1 1 1 1 │\n\
             └                 ┘"
        );
        let cell = &mesh.cells[1];
        let mut pad = Scratchpad::new(mesh.ndim, cell.kind)?;
        set_xxt_from_points(&mut pad, &cell.points, &mesh);
        assert_eq!(
            format!("{}", pad.xxt),
            "┌                 ┐\n\
             │ 0 1 1 0 0 1 1 0 │\n\
             │ 0 0 1 1 0 0 1 1 │\n\
             │ 1 1 1 1 2 2 2 2 │\n\
             └                 ┘"
        );
        Ok(())
    }

    #[test]
    fn get_mesh_limits_works() {
        let mesh = &Samples::two_quads_horizontal();
        let (min, max) = get_mesh_limits(&mesh);
        assert_eq!(min, &[0.0, 0.0]);
        assert_eq!(max, &[2.0, 1.0]);

        let mesh = &Samples::two_cubes_vertical();
        let (min, max) = get_mesh_limits(&mesh);
        assert_eq!(min, &[0.0, 0.0, 0.0]);
        assert_eq!(max, &[1.0, 1.0, 2.0]);
    }
}
<commit_msg>Let set_xxt_from_points receive slice<commit_after>use super::{Mesh, PointId};
use crate::shapes::Scratchpad;

/// Sets the matrix of coordinates (transposed) Xᵀ given a list of point ids
///
/// # Panics
///
/// 1. Make sure `pad.kind.nnode() == points.len()`; otherwise a panic will occur
/// 2. This function does not check for bounds on point indices and dimensions
/// 3. Use [crate::mesh::check_all()] to capture (some) errors
#[inline]
pub fn set_xxt_from_points(pad: &mut Scratchpad, points: &[PointId], mesh: &Mesh) {
    let nnode = pad.kind.nnode();
    assert_eq!(nnode, points.len());
    for m in 0..nnode {
        for j in 0..mesh.ndim {
            pad.set_xx(m, j, mesh.points[points[m]].coords[j]);
        }
    }
}

/// Returns the (min,max) point coordinates in a mesh
#[inline]
pub fn get_mesh_limits(mesh: &Mesh) -> (Vec<f64>, Vec<f64>) {
    let mut min = vec![f64::MAX; mesh.ndim];
    let mut max = vec![f64::MIN; mesh.ndim];
    for point in &mesh.points {
        for i in 0..mesh.ndim {
            min[i] = f64::min(min[i], point.coords[i]);
            max[i] = f64::max(max[i], point.coords[i]);
        }
    }
    (min, max)
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use super::{get_mesh_limits, set_xxt_from_points};
    use crate::mesh::Samples;
    use crate::shapes::Scratchpad;
    use crate::StrError;

    #[test]
    fn set_xxt_from_points_works_2d() -> Result<(), StrError> {
        //  3--------2--------5
        //  |        |        |
        //  |        |        |
        //  |        |        |
        //  0--------1--------4
        let mesh = Samples::two_quads_horizontal();
        let cell = &mesh.cells[0];
        let mut pad = Scratchpad::new(mesh.ndim, cell.kind)?;
        set_xxt_from_points(&mut pad, &cell.points, &mesh);
        assert_eq!(
            format!("{}", pad.xxt),
            "┌         ┐\n\
             │ 0 1 1 0 │\n\
             │ 0 0 1 1 │\n\
             └         ┘"
        );
        let cell = &mesh.cells[1];
        let mut pad = Scratchpad::new(mesh.ndim, cell.kind)?;
        set_xxt_from_points(&mut pad, &cell.points, &mesh);
        assert_eq!(
            format!("{}", pad.xxt),
            "┌         ┐\n\
             │ 1 2 2 1 │\n\
             │ 0 0 1 1 │\n\
             └         ┘"
        );
        Ok(())
    }

    #[test]
    fn set_xxt_from_points_works_3d() -> Result<(), StrError> {
        //       8-------------11
        //      /.             /|
        //     / .            / |
        //    /  .           /  |
        //   /   .          /   |
        //  9-------------10    |
        //  |    .         |    |
        //  |    4---------|----7
        //  |   /.         |   /|
        //  |  / .         |  / |
        //  | /  .         | /  |
        //  |/   .         |/   |
        //  5--------------6    |
        //  |    .         |    |
        //  |    0---------|----3
        //  |   /          |   /
        //  |  /           |  /
        //  | /            | /
        //  |/             |/
        //  1--------------2
        let mesh = Samples::two_cubes_vertical();
        let cell = &mesh.cells[0];
        let mut pad = Scratchpad::new(mesh.ndim, cell.kind)?;
        set_xxt_from_points(&mut pad, &cell.points, &mesh);
        assert_eq!(
            format!("{}", pad.xxt),
            "┌                 ┐\n\
             │ 0 1 1 0 0 1 1 0 │\n\
             │ 0 0 1 1 0 0 1 1 │\n\
             │ 0 0 0 0 1 1 1 1 │\n\
             └                 ┘"
        );
        let cell = &mesh.cells[1];
        let mut pad = Scratchpad::new(mesh.ndim, cell.kind)?;
        set_xxt_from_points(&mut pad, &cell.points, &mesh);
        assert_eq!(
            format!("{}", pad.xxt),
            "┌                 ┐\n\
             │ 0 1 1 0 0 1 1 0 │\n\
             │ 0 0 1 1 0 0 1 1 │\n\
             │ 1 1 1 1 2 2 2 2 │\n\
             └                 ┘"
        );
        Ok(())
    }

    #[test]
    fn get_mesh_limits_works() {
        let mesh = &Samples::two_quads_horizontal();
        let (min, max) = get_mesh_limits(&mesh);
        assert_eq!(min, &[0.0, 0.0]);
        assert_eq!(max, &[2.0, 1.0]);

        let mesh = &Samples::two_cubes_vertical();
        let (min, max) = get_mesh_limits(&mesh);
        assert_eq!(min, &[0.0, 0.0, 0.0]);
        assert_eq!(max, &[1.0, 1.0, 2.0]);
    }
}
<|endoftext|>


<commit_before>use hir::{HasSource, InFile};
use ide_db::assists::{AssistId, AssistKind};
use syntax::{
    ast::{self, make},
    AstNode,
};

use crate::assist_context::{AssistContext, Assists};

// Assist: generate_enum_variant
//
// Adds a variant to an enum.
//
// ```
// enum Countries {
//     Ghana,
// }
//
// fn main() {
//     let country = Countries::Lesotho$0;
// }
// ```
// ->
// ```
// enum Countries {
//     Ghana,
//     Lesotho,
// }
//
// fn main() {
//     let country = Countries::Lesotho;
// }
// ```
pub(crate) fn generate_enum_variant(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
    let path_expr: ast::PathExpr = ctx.find_node_at_offset()?;
    let path = path_expr.path()?;

    if ctx.sema.resolve_path(&path).is_some() {
        // No need to generate anything if the path resolves
        return None;
    }

    let name_ref = path.segment()?.name_ref()?;
    if name_ref.text().starts_with(char::is_lowercase) {
        // Don't suggest generating variant if the name starts with a lowercase letter
        return None;
    }

    if let Some(hir::PathResolution::Def(hir::ModuleDef::Adt(hir::Adt::Enum(e)))) =
        ctx.sema.resolve_path(&path.qualifier()?)
    {
        let target = path.syntax().text_range();
        return add_variant_to_accumulator(acc, ctx, target, e, &name_ref);
    }

    None
}

fn add_variant_to_accumulator(
    acc: &mut Assists,
    ctx: &AssistContext<'_>,
    target: syntax::TextRange,
    adt: hir::Enum,
    name_ref: &ast::NameRef,
) -> Option<()> {
    let db = ctx.db();
    let InFile { file_id, value: enum_node } = adt.source(db)?.original_ast_node(db)?;

    let variant = make::variant(make::name(&name_ref.text()), None);
    acc.add(
        AssistId("generate_enum_variant", AssistKind::Generate),
        "Generate variant",
        target,
        |builder| {
            builder.edit_file(file_id.original_file(db));
            let node = builder.make_mut(enum_node);
            node.variant_list().map(|it| it.add_variant(variant.clone_for_update()));
        },
    )
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn generate_basic_enum_variant_in_empty_enum() {
        check_assist(
            generate_enum_variant,
            r"
enum Foo {}
fn main() {
    Foo::Bar$0
}
",
            r"
enum Foo {
    Bar,
}
fn main() {
    Foo::Bar
}
",
        )
    }

    #[test]
    fn generate_basic_enum_variant_in_non_empty_enum() {
        check_assist(
            generate_enum_variant,
            r"
enum Foo {
    Bar,
}
fn main() {
    Foo::Baz$0
}
",
            r"
enum Foo {
    Bar,
    Baz,
}
fn main() {
    Foo::Baz
}
",
        )
    }

    #[test]
    fn generate_basic_enum_variant_in_different_file() {
        check_assist(
            generate_enum_variant,
            r"
//- /main.rs
mod foo;
use foo::Foo;

fn main() {
    Foo::Baz$0
}

//- /foo.rs
enum Foo {
    Bar,
}
",
            r"
enum Foo {
    Bar,
    Baz,
}
",
        )
    }

    #[test]
    fn not_applicable_for_existing_variant() {
        check_assist_not_applicable(
            generate_enum_variant,
            r"
enum Foo {
    Bar,
}
fn main() {
    Foo::Bar$0
}
",
        )
    }

    #[test]
    fn not_applicable_for_lowercase() {
        check_assist_not_applicable(
            generate_enum_variant,
            r"
enum Foo {
    Bar,
}
fn main() {
    Foo::new$0
}
",
        )
    }

    #[test]
    fn indentation_level_is_correct() {
        check_assist(
            generate_enum_variant,
            r"
mod m {
    enum Foo {
        Bar,
    }
}
fn main() {
    m::Foo::Baz$0
}
",
            r"
mod m {
    enum Foo {
        Bar,
        Baz,
    }
}
fn main() {
    m::Foo::Baz
}
",
        )
    }
}
<commit_msg>Support tuple fields in generate_enum_variant<commit_after>use hir::{HasSource, HirDisplay, InFile};
use ide_db::assists::{AssistId, AssistKind};
use syntax::{
    ast::{self, make, HasArgList},
    AstNode,
};

use crate::assist_context::{AssistContext, Assists};

// Assist: generate_enum_variant
//
// Adds a variant to an enum.
//
// ```
// enum Countries {
//     Ghana,
// }
//
// fn main() {
//     let country = Countries::Lesotho$0;
// }
// ```
// ->
// ```
// enum Countries {
//     Ghana,
//     Lesotho,
// }
//
// fn main() {
//     let country = Countries::Lesotho;
// }
// ```
pub(crate) fn generate_enum_variant(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
    let path_expr: ast::PathExpr = ctx.find_node_at_offset()?;
    let path = path_expr.path()?;

    if ctx.sema.resolve_path(&path).is_some() {
        // No need to generate anything if the path resolves
        return None;
    }

    let name_ref = path.segment()?.name_ref()?;
    if name_ref.text().starts_with(char::is_lowercase) {
        // Don't suggest generating variant if the name starts with a lowercase letter
        return None;
    }

    if let Some(hir::PathResolution::Def(hir::ModuleDef::Adt(hir::Adt::Enum(e)))) =
        ctx.sema.resolve_path(&path.qualifier()?)
    {
        let target = path.syntax().text_range();
        return add_variant_to_accumulator(acc, ctx, target, e, &name_ref, &path);
    }

    None
}

fn add_variant_to_accumulator(
    acc: &mut Assists,
    ctx: &AssistContext<'_>,
    target: syntax::TextRange,
    adt: hir::Enum,
    name_ref: &ast::NameRef,
    path: &ast::Path,
) -> Option<()> {
    let db = ctx.db();
    let InFile { file_id, value: enum_node } = adt.source(db)?.original_ast_node(db)?;

    acc.add(
        AssistId("generate_enum_variant", AssistKind::Generate),
        "Generate variant",
        target,
        |builder| {
            builder.edit_file(file_id.original_file(db));
            let node = builder.make_mut(enum_node);
            let variant = make_variant(ctx, name_ref, &path);
            node.variant_list().map(|it| it.add_variant(variant.clone_for_update()));
        },
    )
}

fn make_variant(
    ctx: &AssistContext<'_>,
    name_ref: &ast::NameRef,
    path: &ast::Path,
) -> ast::Variant {
    let field_list = make_field_list(ctx, path);
    make::variant(make::name(&name_ref.text()), field_list)
}

fn make_field_list(ctx: &AssistContext<'_>, path: &ast::Path) -> Option<ast::FieldList> {
    let scope = ctx.sema.scope(&path.syntax())?;
    if let Some(call_expr) =
        path.syntax().parent().and_then(|it| it.parent()).and_then(ast::CallExpr::cast)
    {
        make_tuple_field_list(call_expr, ctx, &scope)
    } else {
        None
    }
}

fn make_tuple_field_list(
    call_expr: ast::CallExpr,
    ctx: &AssistContext<'_>,
    scope: &hir::SemanticsScope<'_>,
) -> Option<ast::FieldList> {
    let args = call_expr.arg_list()?.args();
    let tuple_fields = args.map(|arg| {
        let ty = expr_ty(ctx, arg, &scope);
        make::tuple_field(None, ty)
    });
    Some(make::tuple_field_list(tuple_fields).into())
}

fn expr_ty(ctx: &AssistContext<'_>, arg: ast::Expr, scope: &hir::SemanticsScope<'_>) -> ast::Type {
    let ty = ctx.sema.type_of_expr(&arg).map(|it| it.adjusted());
    let text = ty
        .and_then(|it| it.display_source_code(ctx.db(), scope.module().into()).ok())
        .unwrap_or_else(|| "_".to_string());
    make::ty(&text)
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn generate_basic_enum_variant_in_empty_enum() {
        check_assist(
            generate_enum_variant,
            r"
enum Foo {}
fn main() {
    Foo::Bar$0
}
",
            r"
enum Foo {
    Bar,
}
fn main() {
    Foo::Bar
}
",
        )
    }

    #[test]
    fn generate_basic_enum_variant_in_non_empty_enum() {
        check_assist(
            generate_enum_variant,
            r"
enum Foo {
    Bar,
}
fn main() {
    Foo::Baz$0
}
",
            r"
enum Foo {
    Bar,
    Baz,
}
fn main() {
    Foo::Baz
}
",
        )
    }

    #[test]
    fn generate_basic_enum_variant_in_different_file() {
        check_assist(
            generate_enum_variant,
            r"
//- /main.rs
mod foo;
use foo::Foo;

fn main() {
    Foo::Baz$0
}

//- /foo.rs
enum Foo {
    Bar,
}
",
            r"
enum Foo {
    Bar,
    Baz,
}
",
        )
    }

    #[test]
    fn not_applicable_for_existing_variant() {
        check_assist_not_applicable(
            generate_enum_variant,
            r"
enum Foo {
    Bar,
}
fn main() {
    Foo::Bar$0
}
",
        )
    }

    #[test]
    fn not_applicable_for_lowercase() {
        check_assist_not_applicable(
            generate_enum_variant,
            r"
enum Foo {
    Bar,
}
fn main() {
    Foo::new$0
}
",
        )
    }

    #[test]
    fn indentation_level_is_correct() {
        check_assist(
            generate_enum_variant,
            r"
mod m {
    enum Foo {
        Bar,
    }
}
fn main() {
    m::Foo::Baz$0
}
",
            r"
mod m {
    enum Foo {
        Bar,
        Baz,
    }
}
fn main() {
    m::Foo::Baz
}
",
        )
    }

    #[test]
    fn associated_single_element_tuple() {
        check_assist(
            generate_enum_variant,
            r"
enum Foo {}
fn main() {
    Foo::Bar$0(true)
}
",
            r"
enum Foo {
    Bar(bool),
}
fn main() {
    Foo::Bar(true)
}
",
        )
    }

    #[test]
    fn associated_single_element_tuple_unknown_type() {
        check_assist(
            generate_enum_variant,
            r"
enum Foo {}
fn main() {
    Foo::Bar$0(x)
}
",
            r"
enum Foo {
    Bar(_),
}
fn main() {
    Foo::Bar(x)
}
",
        )
    }

    #[test]
    fn associated_multi_element_tuple() {
        check_assist(
            generate_enum_variant,
            r"
struct Struct {}
enum Foo {}
fn main() {
    Foo::Bar$0(true, x, Struct {})
}
",
            r"
struct Struct {}
enum Foo {
    Bar(bool, _, Struct),
}
fn main() {
    Foo::Bar(true, x, Struct {})
}
",
        )
    }
}
<|endoftext|>


<commit_before>extern crate cc;

fn main() {
    let target_os = std::env::var("CARGO_CFG_TARGET_OS");
    let is_macos = target_os.is_ok() && target_os.unwrap() == "macos";

    let mut build = cc::Build::new();
    build.cpp(true);

    let compiler = build.try_get_compiler();
    let is_clang = compiler.is_ok() && compiler.unwrap().is_like_clang();

    if is_macos && is_clang {
        build.flag("-std=c++14").cpp_set_stdlib("c++");
    } else {
        build.flag_if_supported("-std=c++14");
    }

    build
        .file("src/wrapper.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_cfg.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_cross.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_cross_parsed_ir.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_parser.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_cross_util.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_glsl.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_hlsl.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_msl.cpp")
        .compile("spirv-cross-rust-wrapper");
}
<commit_msg>Conditionally include GLSL/HLSL/MSL in build step<commit_after>extern crate cc;

fn main() {
    let target_os = std::env::var("CARGO_CFG_TARGET_OS");
    let is_macos = target_os.is_ok() && target_os.unwrap() == "macos";

    let mut build = cc::Build::new();
    build.cpp(true);

    let compiler = build.try_get_compiler();
    let is_clang = compiler.is_ok() && compiler.unwrap().is_like_clang();

    if is_macos && is_clang {
        build.flag("-std=c++14").cpp_set_stdlib("c++");
    } else {
        build.flag_if_supported("-std=c++14");
    }

    build
        .file("src/wrapper.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_cfg.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_cross.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_cross_parsed_ir.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_parser.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_cross_util.cpp");

    #[cfg(feature = "glsl")]
    build.file("src/vendor/SPIRV-Cross/spirv_glsl.cpp");

    #[cfg(feature = "hlsl")]
    build.file("src/vendor/SPIRV-Cross/spirv_hlsl.cpp");

    #[cfg(feature = "msl")]
    build.file("src/vendor/SPIRV-Cross/spirv_msl.cpp");

    build.compile("spirv-cross-rust-wrapper");
}
<|endoftext|>


<commit_before>use bullet;
use gfx_app::{Window, GameStatus};
use gfx_app::renderer::{DeviceRenderer, EncoderQueue};
use gfx_app::system::DrawSystem;
use gfx;
use std::time;
use std::sync::mpsc;
use terrain;
use specs;
use specs::{World};
use specs::DispatcherBuilder;
use graphics::{Dimensions, DeltaTime};
use gfx_app::controls::TilemapControls;
use gfx_app::mouse_controls::{MouseControlSystem, MouseInputState};
use graphics::camera::CameraControlSystem;
use character::controls::CharacterControlSystem;
use critter::{CharacterSprite, ZombieSprite};
use character;
use zombie;
use graphics;

pub fn run<W, D, F>(window: &mut W) -> GameStatus
  where W: Window<D, F>,
        D: gfx::Device + 'static,
        F: gfx::Factory<D::Resources>,
        D::CommandBuffer: Send {
  let (mut device_renderer, enc_queue) = DeviceRenderer::new(window.create_buffers(2));

  let mut w = specs::World::new();
  setup_world(&mut w, window.get_viewport_size());
  dispatch_loop(window, &mut device_renderer, &mut w, enc_queue)
}

fn setup_world(world: &mut World, viewport_size: (u32, u32)) {
  let view_matrix = Dimensions::get_view_matrix();
  world.register::<terrain::TerrainDrawable>();
  world.register::<graphics::camera::CameraInputState>();
  world.register::<character::CharacterDrawable>();
  world.register::<zombie::ZombieDrawable>();
  world.register::<bullet::BulletDrawable>();
  world.register::<CharacterSprite>();
  world.register::<ZombieSprite>();
  world.register::<character::controls::CharacterInputState>();
  world.register::<MouseInputState>();

  world.add_resource(terrain::tilemap::generate());
  world.add_resource(Dimensions::new(viewport_size.0, viewport_size.1));
  world.add_resource(graphics::camera::CameraInputState::new());
  world.add_resource(character::controls::CharacterInputState::new());
  world.add_resource(MouseInputState::new());
  world.add_resource(bullet::BulletDrawable::new());
  world.add_resource(character::CharacterDrawable::new(view_matrix));
  world.add_resource(zombie::ZombieDrawable::new(view_matrix));
  world.add_resource(zombie::ZombieDrawable::new(view_matrix));
  world.add_resource(CharacterSprite::new());
  world.add_resource(ZombieSprite::new());
  world.add_resource(DeltaTime(0.0));
  world.create_entity()
    .with(terrain::TerrainDrawable::new(view_matrix))
    .with(character::CharacterDrawable::new(view_matrix))
    .with(zombie::ZombieDrawable::new(view_matrix))
    .with(bullet::BulletDrawable::new())
    .with(CharacterSprite::new())
    .with(ZombieSprite::new())
    .with(graphics::camera::CameraInputState::new())
    .with(character::controls::CharacterInputState::new())
    .with(MouseInputState::new()).build();
}

fn dispatch_loop<W, D, F>(window: &mut W,
                          device_renderer: &mut DeviceRenderer<D>,
                          w: &mut World,
                          encoder_queue: EncoderQueue<D>) -> GameStatus
  where W: Window<D, F>,
        D: gfx::Device + 'static,
        F: gfx::Factory<D::Resources>,
        D::CommandBuffer: Send {

  let draw = {
    let rtv = window.get_render_target_view();
    let dsv = window.get_depth_stencil_view();
    DrawSystem::new(window.get_factory(), &rtv, &dsv, encoder_queue)
  };

  let (_, game_state) = mpsc::channel::<GameStatus>();

  let (terrain_system, terrain_control) = CameraControlSystem::new();
  let (character_system, character_control) = CharacterControlSystem::new();
  let (mouse_system, mouse_control) = MouseControlSystem::new();
  let controls = TilemapControls::new(terrain_control, character_control, mouse_control);

  let mut dispatcher = DispatcherBuilder::new()
    .add(draw, "drawing", &[])
    .add(terrain::PreDrawSystem::new(), "draw-prep-terrain", &["drawing"])
    .add(character::PreDrawSystem::new(), "draw-prep-character", &["drawing"])
    .add(zombie::PreDrawSystem::new(), "draw-prep-zombie", &["drawing"])
    .add(bullet::PreDrawSystem::new(), "draw-prep-bullet", &["drawing"])
    .add(terrain_system, "terrain-system", &[])
    .add(character_system, "character-system", &[])
    .add(mouse_system, "mouse-system", &[])
    .build();

  window.set_controls(controls);

  let mut last_time = time::Instant::now();
  loop {
    let elapsed = last_time.elapsed();
    let delta = f64::from(elapsed.subsec_nanos()) / 1e9 + elapsed.as_secs() as f64;
    last_time = time::Instant::now();

    dispatcher.dispatch(&w.res);
    w.maintain();

    *w.write_resource::<DeltaTime>() = DeltaTime(delta);

    device_renderer.draw(window.get_device());
    window.swap_window();

    if let Some(quit_status) = window.poll_events() {
      return quit_status;
    }

    if let Ok(quit_status) = game_state.try_recv() {
      return quit_status;
    }
  }
}
<commit_msg>Remove unnecessary resources<commit_after>use bullet;
use gfx_app::{Window, GameStatus};
use gfx_app::renderer::{DeviceRenderer, EncoderQueue};
use gfx_app::system::DrawSystem;
use gfx;
use std::time;
use std::sync::mpsc;
use terrain;
use specs;
use specs::{World};
use specs::DispatcherBuilder;
use graphics::{Dimensions, DeltaTime};
use gfx_app::controls::TilemapControls;
use gfx_app::mouse_controls::{MouseControlSystem, MouseInputState};
use graphics::camera::CameraControlSystem;
use character::controls::CharacterControlSystem;
use critter::{CharacterSprite, ZombieSprite};
use character;
use zombie;
use graphics;

pub fn run<W, D, F>(window: &mut W) -> GameStatus
  where W: Window<D, F>,
        D: gfx::Device + 'static,
        F: gfx::Factory<D::Resources>,
        D::CommandBuffer: Send {
  let (mut device_renderer, enc_queue) = DeviceRenderer::new(window.create_buffers(2));

  let mut w = specs::World::new();
  setup_world(&mut w, window.get_viewport_size());
  dispatch_loop(window, &mut device_renderer, &mut w, enc_queue)
}

fn setup_world(world: &mut World, viewport_size: (u32, u32)) {
  let view_matrix = Dimensions::get_view_matrix();
  world.register::<terrain::TerrainDrawable>();
  world.register::<graphics::camera::CameraInputState>();
  world.register::<character::CharacterDrawable>();
  world.register::<zombie::ZombieDrawable>();
  world.register::<bullet::BulletDrawable>();
  world.register::<CharacterSprite>();
  world.register::<ZombieSprite>();
  world.register::<character::controls::CharacterInputState>();
  world.register::<MouseInputState>();

  world.add_resource(terrain::tilemap::generate());
  world.add_resource(Dimensions::new(viewport_size.0, viewport_size.1));
  world.add_resource(graphics::camera::CameraInputState::new());
  world.add_resource(character::controls::CharacterInputState::new());
  world.add_resource(MouseInputState::new());
  world.add_resource(DeltaTime(0.0));
  world.create_entity()
    .with(terrain::TerrainDrawable::new(view_matrix))
    .with(character::CharacterDrawable::new(view_matrix))
    .with(zombie::ZombieDrawable::new(view_matrix))
    .with(bullet::BulletDrawable::new())
    .with(CharacterSprite::new())
    .with(ZombieSprite::new())
    .with(graphics::camera::CameraInputState::new())
    .with(character::controls::CharacterInputState::new())
    .with(MouseInputState::new()).build();
}

fn dispatch_loop<W, D, F>(window: &mut W,
                          device_renderer: &mut DeviceRenderer<D>,
                          w: &mut World,
                          encoder_queue: EncoderQueue<D>) -> GameStatus
  where W: Window<D, F>,
        D: gfx::Device + 'static,
        F: gfx::Factory<D::Resources>,
        D::CommandBuffer: Send {

  let draw = {
    let rtv = window.get_render_target_view();
    let dsv = window.get_depth_stencil_view();
    DrawSystem::new(window.get_factory(), &rtv, &dsv, encoder_queue)
  };

  let (_, game_state) = mpsc::channel::<GameStatus>();

  let (terrain_system, terrain_control) = CameraControlSystem::new();
  let (character_system, character_control) = CharacterControlSystem::new();
  let (mouse_system, mouse_control) = MouseControlSystem::new();
  let controls = TilemapControls::new(terrain_control, character_control, mouse_control);

  let mut dispatcher = DispatcherBuilder::new()
    .add(draw, "drawing", &[])
    .add(terrain::PreDrawSystem::new(), "draw-prep-terrain", &["drawing"])
    .add(character::PreDrawSystem::new(), "draw-prep-character", &["drawing"])
    .add(zombie::PreDrawSystem::new(), "draw-prep-zombie", &["drawing"])
    .add(bullet::PreDrawSystem::new(), "draw-prep-bullet", &["drawing"])
    .add(terrain_system, "terrain-system", &[])
    .add(character_system, "character-system", &[])
    .add(mouse_system, "mouse-system", &[])
    .build();

  window.set_controls(controls);

  let mut last_time = time::Instant::now();
  loop {
    let elapsed = last_time.elapsed();
    let delta = f64::from(elapsed.subsec_nanos()) / 1e9 + elapsed.as_secs() as f64;
    last_time = time::Instant::now();

    dispatcher.dispatch(&w.res);
    w.maintain();

    *w.write_resource::<DeltaTime>() = DeltaTime(delta);

    device_renderer.draw(window.get_device());
    window.swap_window();

    if let Some(quit_status) = window.poll_events() {
      return quit_status;
    }

    if let Ok(quit_status) = game_state.try_recv() {
      return quit_status;
    }
  }
}
<|endoftext|>


<commit_before>
use std::sync::{Barrier, RwLock, Arc, RwLockWriteGuard};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::atomic::Ordering as AtOrd;
extern crate rand;
use rand::{ThreadRng, Rng};
use rand::distributions::{IndependentSample, Range};

extern crate gr;
use gr::{GI, width_box, split_box, midpoint_box, eps_tol};

extern crate gelpia_utils;
use gelpia_utils::{Quple, INF, NINF, Flt, Parameters};

extern crate function;
use function::FuncObj;

#[derive(Clone)]
pub struct Individual {
    pub solution: Vec<GI>,
    pub fitness: Flt,
}

pub fn ea(x_e: Vec<GI>,
          param: Parameters,
          population: Arc<RwLock<Vec<Individual>>>,
          f_bestag: Arc<RwLock<Flt>>,
          x_bestbb: Arc<RwLock<Vec<GI>>>,
          b1: Arc<Barrier>,
          b2: Arc<Barrier>,
          stop: Arc<AtomicBool>,
          sync: Arc<AtomicBool>,
          fo_c: FuncObj) -> (Flt, Vec<GI>, bool) {

    let input = ea_core(&x_e, &param, &stop, &sync, &b1, &b2, &f_bestag,
                        &x_bestbb, population, &fo_c);
    let ans = fo_c.call(&input).upper();

    (ans, input, true)
}

fn ea_core(x_e: &Vec<GI>, param: &Parameters, stop: &Arc<AtomicBool>,
           sync: &Arc<AtomicBool>, b1: &Arc<Barrier>, b2: &Arc<Barrier>,
           f_bestag: &Arc<RwLock<Flt>>,
           x_bestbb: &Arc<RwLock<Vec<GI>>>,
           population: Arc<RwLock<Vec<Individual>>>, fo_c: &FuncObj)
           -> (Vec<GI>) {
    let mut rng = rand::thread_rng();
    let dimension = Range::new(0, x_e.len());
    let mut ranges = Vec::new();
    for g in x_e {
        ranges.push(Range::new(g.lower(), g.upper()));
    }

    while !stop.load(AtOrd::Acquire) {
        if sync.load(AtOrd::Acquire) {
            b1.wait();
            b2.wait();
        }
        let ref mut population = *population.write().unwrap();
        sample(param.population, population, fo_c, &ranges, &mut rng);

        population.sort_by(|a, b| b.fitness.partial_cmp(&a.fitness).unwrap());

        for iteration in 0..100 {
            population.truncate(param.elitism);

            for _ in 0..param.selection {
                population.push(rand_individual(fo_c, &ranges, &mut rng));
            }

            next_generation(param.population, population, fo_c, param.mutation,
                            param.crossover, &dimension, &ranges, &mut rng);
            population.sort_by(|a, b| b.fitness.partial_cmp(&a.fitness).unwrap());

            // Report fittest of the fit.
            {
                let mut fbest = f_bestag.write().unwrap();

                *fbest =
                    if *fbest < population[0].fitness { population[0].fitness }
                else { *fbest };
            }

            // Kill worst of the worst
            let mut ftg = Vec::new();
            {
                let bestbb = x_bestbb.read().unwrap();
                // From The Gods
                for i in 0..bestbb.len() {
                    ftg.push(Range::new(bestbb[i].lower(), bestbb[i].upper()));
                }
            }
            let worst_ind = population.len() - 1;
            population[worst_ind] = rand_individual(fo_c,
                                                    &ftg,
                                                    &mut rng);
            population.sort_by(|a, b| b.fitness.partial_cmp(&a.fitness).unwrap());
        }
    }
    let ref population = *population.read().unwrap();
    let result = population[0].solution.clone();

    result
}

fn sample(population_size: usize, population: &mut Vec<Individual>,
          fo_c: &FuncObj, ranges: &Vec<Range<f64>>, rng: &mut ThreadRng)
          -> () {
    for _ in 0..population_size-population.len() {
        population.push(rand_individual(fo_c, ranges, rng));
    }

    ()
}

fn rand_individual(fo_c: &FuncObj, ranges: &Vec<Range<f64>>, rng: &mut ThreadRng)
                   -> (Individual) {
    let mut new_sol = Vec::new();
    for r in ranges {
        new_sol.push(GI::new_p(r.ind_sample(rng)));
    }
    let fitness = fo_c.call(&new_sol).lower();

    Individual{solution:new_sol, fitness:fitness}
}

fn next_generation(population_size:usize, population: &mut Vec<Individual>,
                   fo_c: &FuncObj, mut_rate: f64, crossover: f64,
                   dimension: &Range<usize>, ranges: &Vec<Range<f64>>,
                   rng: &mut ThreadRng)
                   -> () {

    let elites = population.clone();

    for _ in 0..population_size-population.len() {
        if rng.gen::<f64>() < crossover {
            population.push(breed(rng.choose(&elites).unwrap(),
                                  rng.choose(&elites).unwrap(),
                                  fo_c,
                                  dimension, rng));
        } else {
            population.push(mutate(rng.choose(&elites).unwrap(), fo_c, mut_rate,
                                   dimension, ranges, rng));
        }
    }

    ()
}

fn mutate(input: &Individual, fo_c: &FuncObj, mut_rate: f64,
          dimension: &Range<usize>, ranges: &Vec<Range<f64>>, rng: &mut ThreadRng)
          -> (Individual) {
    let mut output_sol = Vec::new();

    for (r, &ind) in ranges.iter().zip(input.solution.iter()) {
        output_sol.push(
            if rng.gen::<f64>() < mut_rate {
                ind
            } else {
                GI::new_p(r.ind_sample(rng))
            });
    }

    let fitness = fo_c.call(&output_sol).lower();

    Individual{solution: output_sol, fitness: fitness}
}

fn breed(parent1: &Individual, parent2: &Individual, fo_c: &FuncObj,
         dimention: &Range<usize>, rng: &mut ThreadRng) -> (Individual) {
    let mut child = parent1.clone();
    let crossover_point = dimention.ind_sample(rng);
    child.solution.truncate(crossover_point);
    let mut rest = parent2.clone().solution.split_off(crossover_point);
    child.solution.append(&mut rest);
    child.fitness = fo_c.call(&child.solution).lower();
    child
}
<commit_msg>Added check from gaRedo branch<commit_after>use std::sync::{Barrier, RwLock, Arc, RwLockWriteGuard};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::atomic::Ordering as AtOrd;
extern crate rand;
use rand::{ThreadRng, Rng};
use rand::distributions::{IndependentSample, Range};

extern crate gr;
use gr::{GI, width_box, split_box, midpoint_box, eps_tol};

extern crate gelpia_utils;
use gelpia_utils::{Quple, INF, NINF, Flt, Parameters};

extern crate function;
use function::FuncObj;

#[derive(Clone)]
pub struct Individual {
    pub solution: Vec<GI>,
    pub fitness: Flt,
}

pub fn ea(x_e: Vec<GI>,
          param: Parameters,
          population: Arc<RwLock<Vec<Individual>>>,
          f_bestag: Arc<RwLock<Flt>>,
          x_bestbb: Arc<RwLock<Vec<GI>>>,
          b1: Arc<Barrier>,
          b2: Arc<Barrier>,
          stop: Arc<AtomicBool>,
          sync: Arc<AtomicBool>,
          fo_c: FuncObj) -> (Flt, Vec<GI>, bool) {
    // Constant function
    if x_e.len() == 0 {
        return (0, x_e, true);
    }
    let input = ea_core(&x_e, &param, &stop, &sync, &b1, &b2, &f_bestag,
                        &x_bestbb, population, &fo_c);
    let ans = fo_c.call(&input).upper();

    (ans, input, true)
}

fn ea_core(x_e: &Vec<GI>, param: &Parameters, stop: &Arc<AtomicBool>,
           sync: &Arc<AtomicBool>, b1: &Arc<Barrier>, b2: &Arc<Barrier>,
           f_bestag: &Arc<RwLock<Flt>>,
           x_bestbb: &Arc<RwLock<Vec<GI>>>,
           population: Arc<RwLock<Vec<Individual>>>, fo_c: &FuncObj)
           -> (Vec<GI>) {
    let mut rng = rand::thread_rng();
    let dimension = Range::new(0, x_e.len());
    let mut ranges = Vec::new();
    for g in x_e {
        ranges.push(Range::new(g.lower(), g.upper()));
    }

    while !stop.load(AtOrd::Acquire) {
        if sync.load(AtOrd::Acquire) {
            b1.wait();
            b2.wait();
        }
        let ref mut population = *population.write().unwrap();
        sample(param.population, population, fo_c, &ranges, &mut rng);

        population.sort_by(|a, b| b.fitness.partial_cmp(&a.fitness).unwrap());

        for iteration in 0..100 {
            population.truncate(param.elitism);

            for _ in 0..param.selection {
                population.push(rand_individual(fo_c, &ranges, &mut rng));
            }

            next_generation(param.population, population, fo_c, param.mutation,
                            param.crossover, &dimension, &ranges, &mut rng);
            population.sort_by(|a, b| b.fitness.partial_cmp(&a.fitness).unwrap());

            // Report fittest of the fit.
            {
                let mut fbest = f_bestag.write().unwrap();

                *fbest =
                    if *fbest < population[0].fitness { population[0].fitness }
                else { *fbest };
            }

            // Kill worst of the worst
            let mut ftg = Vec::new();
            {
                let bestbb = x_bestbb.read().unwrap();
                // From The Gods
                for i in 0..bestbb.len() {
                    ftg.push(Range::new(bestbb[i].lower(), bestbb[i].upper()));
                }
            }
            let worst_ind = population.len() - 1;
            population[worst_ind] = rand_individual(fo_c,
                                                    &ftg,
                                                    &mut rng);
            population.sort_by(|a, b| b.fitness.partial_cmp(&a.fitness).unwrap());
        }
    }
    let ref population = *population.read().unwrap();
    let result = population[0].solution.clone();

    result
}

fn sample(population_size: usize, population: &mut Vec<Individual>,
          fo_c: &FuncObj, ranges: &Vec<Range<f64>>, rng: &mut ThreadRng)
          -> () {
    for _ in 0..population_size-population.len() {
        population.push(rand_individual(fo_c, ranges, rng));
    }

    ()
}

fn rand_individual(fo_c: &FuncObj, ranges: &Vec<Range<f64>>, rng: &mut ThreadRng)
                   -> (Individual) {
    let mut new_sol = Vec::new();
    for r in ranges {
        new_sol.push(GI::new_p(r.ind_sample(rng)));
    }
    let fitness = fo_c.call(&new_sol).lower();

    Individual{solution:new_sol, fitness:fitness}
}

fn next_generation(population_size:usize, population: &mut Vec<Individual>,
                   fo_c: &FuncObj, mut_rate: f64, crossover: f64,
                   dimension: &Range<usize>, ranges: &Vec<Range<f64>>,
                   rng: &mut ThreadRng)
                   -> () {

    let elites = population.clone();

    for _ in 0..population_size-population.len() {
        if rng.gen::<f64>() < crossover {
            population.push(breed(rng.choose(&elites).unwrap(),
                                  rng.choose(&elites).unwrap(),
                                  fo_c,
                                  dimension, rng));
        } else {
            population.push(mutate(rng.choose(&elites).unwrap(), fo_c, mut_rate,
                                   dimension, ranges, rng));
        }
    }

    ()
}

fn mutate(input: &Individual, fo_c: &FuncObj, mut_rate: f64,
          dimension: &Range<usize>, ranges: &Vec<Range<f64>>, rng: &mut ThreadRng)
          -> (Individual) {
    let mut output_sol = Vec::new();

    for (r, &ind) in ranges.iter().zip(input.solution.iter()) {
        output_sol.push(
            if rng.gen::<f64>() < mut_rate {
                ind
            } else {
                GI::new_p(r.ind_sample(rng))
            });
    }

    let fitness = fo_c.call(&output_sol).lower();

    Individual{solution: output_sol, fitness: fitness}
}

fn breed(parent1: &Individual, parent2: &Individual, fo_c: &FuncObj,
         dimension: &Range<usize>, rng: &mut ThreadRng) -> (Individual) {
    let mut child = parent1.clone();
    let crossover_point = dimension.ind_sample(rng);
    child.solution.truncate(crossover_point);
    let mut rest = parent2.clone().solution.split_off(crossover_point);
    child.solution.append(&mut rest);
    child.fitness = fo_c.call(&child.solution).lower();
    child
}
<|endoftext|>


<commit_before>#![cfg(feature = "use_std")]

use std::collections::HashMap;
use std::hash::Hash;
use std::iter::Iterator;

/// Creates a new `GroupingMap` from `iter`
pub fn new<I, K, V>(iter: I) -> GroupingMap<I>
where
    I: Iterator<Item = (K, V)>,
    K: Hash + Eq,
{
    GroupingMap { iter }
}

/// `GroupingMap` is an intermediate struct for efficient group-and-fold operations.
/// It groups elements by their key and at the same time fold each group
/// using some aggregating operation.
///
/// No method on this struct performs temporary allocations.
pub struct GroupingMap<I> {
    iter: I,
}

impl<I, K, V> GroupingMap<I>
where
    I: Iterator<Item = (K, V)>,
    K: Hash + Eq,
{
    /// This is the generic way to perform any operations on a `GroupingMap`.
    /// It's suggested to use this method only to implement custom operations
    /// when the already provided ones are not enough.
    ///
    /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
    /// of each group sequentially, passing the previously accumulated value, a reference to the key
    /// and the current element as arguments, and stores the results in an `HashMap`.
    ///
    /// The `operation` function is invoked on each element with the following parameters:
    ///  - the current value of the accumulator of the group if there is currently one;
    ///  - a reference to the key of the group this element belongs to;
    ///  - the element from the source being aggregated;
    /// If `operation` returns `Some(element)` then the accumulator is updated with `element`,
    /// otherwise the previous accumulation is discarded.
    ///
    /// Return a `HashMap` associating the key of each group with the result of aggregation of the group elements.
    /// If there's no result then there won't be an entry associated to that key.
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let data = vec![10, 5, 7, 9, 0, 4, 2];
    /// let lookup = data.into_iter()
    ///     .map(|n| (n % 4, n))
    ///     .into_grouping_map()
    ///     .aggregate(|acc, _, val| {
    ///         match val {
    ///             0 | 2 => None,
    ///             _ => Some(acc.unwrap_or(0) + val)
    ///         }
    ///     });
    ///
    /// assert_eq!(lookup[&0], 4);
    /// assert_eq!(lookup[&1], 14);
    /// assert!(!lookup.contains_key(&2));
    /// assert_eq!(lookup[&3], 7);
    /// ```
    pub fn aggregate<FO, R>(self, mut operation: FO) -> HashMap<K, R>
    where
        FO: FnMut(Option<R>, &K, V) -> Option<R>,
    {
        let mut destination_map = HashMap::new();

        for (key, val) in self.iter {
            let acc = destination_map.remove(&key);
            if let Some(op_res) = operation(acc, &key, val) {
                destination_map.insert(key, op_res);
            }
        }

        destination_map
    }

    /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
    /// of each group sequentially, passing the previously accumulated value, a reference to the key
    /// and the current element as arguments, and stores the results in a new map.
    ///
    /// `init` is the value from which will be cloned the initial value of each accumulator.
    ///
    /// `operation` is a function that is invoked on each element with the following parameters:
    ///  - the current value of the accumulator of the group;
    ///  - a reference to the key of the group this element belongs to;
    ///  - the element from the source being accumulated.
    ///
    /// Return a `HashMap` associating the key of each group with the result of folding the group elements.
    pub fn fold<FO, R>(self, init: R, mut operation: FO) -> HashMap<K, R>
    where
        R: Clone,
        FO: FnMut(R, &K, V) -> R,
    {
        self.aggregate(|acc, key, val| {
            let acc = acc.unwrap_or_else(|| init.clone());
            Some(operation(acc, key, val))
        })
    }

    /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
    /// of each group sequentially, passing the previously accumulated value, a reference to the key
    /// and the current element as arguments, and stores the results in a new map.
    ///
    /// This is similar to [`fold`] but the initial value of the accumulator is the first element of the group.
    ///
    /// `operation` is a function that is invoked on each element with the following parameters:
    ///  - the current value of the accumulator of the group;
    ///  - a reference to the key of the group this element belongs to;
    ///  - the element from the source being accumulated.
    ///
    /// Return a `HashMap` associating the key of each group with the result of folding the group elements.
    ///
    /// [`fold`]: #tymethod.fold
    pub fn fold_first<FO>(self, mut operation: FO) -> HashMap<K, V>
    where
        FO: FnMut(V, &K, V) -> V,
    {
        self.aggregate(|acc, key, val| {
            Some(match acc {
                Some(acc) => operation(acc, key, val),
                None => val,
            })
        })
    }

    /// Groups elements from the `GroupingMap` source by key and collects the elements of each group in
    /// an instance of `C`. The iteration order is preserved when inserting elements.
    ///
    /// Return a `HashMap` associating the key of each group with the collection containing the elements of that group.
    pub fn collect<C>(self) -> HashMap<K, C>
    where
        C: Default + Extend<V>,
    {
        self.aggregate(|acc, _, v| {
            let mut acc = acc.unwrap_or_else(C::default);
            acc.extend(Some(v));
            Some(acc)
        })
    }

    /// Groups elements from the `GroupingMap` source by key and counts them.
    ///
    /// Return a `HashMap` associating the key of each group with the number of elements in that group.
    pub fn count(self) -> HashMap<K, usize> {
        self.fold(0, |acc, _, _| acc + 1)
    }
}
<commit_msg>Added doctest for GroupingMap::fold<commit_after>#![cfg(feature = "use_std")]

use std::collections::HashMap;
use std::hash::Hash;
use std::iter::Iterator;

/// Creates a new `GroupingMap` from `iter`
pub fn new<I, K, V>(iter: I) -> GroupingMap<I>
where
    I: Iterator<Item = (K, V)>,
    K: Hash + Eq,
{
    GroupingMap { iter }
}

/// `GroupingMap` is an intermediate struct for efficient group-and-fold operations.
/// It groups elements by their key and at the same time fold each group
/// using some aggregating operation.
///
/// No method on this struct performs temporary allocations.
pub struct GroupingMap<I> {
    iter: I,
}

impl<I, K, V> GroupingMap<I>
where
    I: Iterator<Item = (K, V)>,
    K: Hash + Eq,
{
    /// This is the generic way to perform any operations on a `GroupingMap`.
    /// It's suggested to use this method only to implement custom operations
    /// when the already provided ones are not enough.
    ///
    /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
    /// of each group sequentially, passing the previously accumulated value, a reference to the key
    /// and the current element as arguments, and stores the results in an `HashMap`.
    ///
    /// The `operation` function is invoked on each element with the following parameters:
    ///  - the current value of the accumulator of the group if there is currently one;
    ///  - a reference to the key of the group this element belongs to;
    ///  - the element from the source being aggregated;
    /// If `operation` returns `Some(element)` then the accumulator is updated with `element`,
    /// otherwise the previous accumulation is discarded.
    ///
    /// Return a `HashMap` associating the key of each group with the result of aggregation of the group elements.
    /// If there's no result then there won't be an entry associated to that key.
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let data = vec![10, 5, 7, 9, 0, 4, 2];
    /// let lookup = data.into_iter()
    ///     .map(|n| (n % 4, n))
    ///     .into_grouping_map()
    ///     .aggregate(|acc, _, val| {
    ///         match val {
    ///             0 | 2 => None,
    ///             _ => Some(acc.unwrap_or(0) + val)
    ///         }
    ///     });
    ///
    /// assert_eq!(lookup[&0], 4);
    /// assert_eq!(lookup[&1], 14);
    /// assert!(!lookup.contains_key(&2));
    /// assert_eq!(lookup[&3], 7);
    /// ```
    pub fn aggregate<FO, R>(self, mut operation: FO) -> HashMap<K, R>
    where
        FO: FnMut(Option<R>, &K, V) -> Option<R>,
    {
        let mut destination_map = HashMap::new();

        for (key, val) in self.iter {
            let acc = destination_map.remove(&key);
            if let Some(op_res) = operation(acc, &key, val) {
                destination_map.insert(key, op_res);
            }
        }

        destination_map
    }

    /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
    /// of each group sequentially, passing the previously accumulated value, a reference to the key
    /// and the current element as arguments, and stores the results in a new map.
    ///
    /// `init` is the value from which will be cloned the initial value of each accumulator.
    ///
    /// `operation` is a function that is invoked on each element with the following parameters:
    ///  - the current value of the accumulator of the group;
    ///  - a reference to the key of the group this element belongs to;
    ///  - the element from the source being accumulated.
    ///
    /// Return a `HashMap` associating the key of each group with the result of folding the group elements.
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let lookup = (1..=7)
    ///     .map(|n| (n % 3, n))
    ///     .into_grouping_map()
    ///     .fold(0, |acc, _, val| acc + val);
    ///
    /// assert_eq!(lookup[&0], 9);
    /// assert_eq!(lookup[&1], 12);
    /// assert_eq!(lookup[&2], 7);
    /// assert_eq!(lookup.len(), 3);
    /// ```
    pub fn fold<FO, R>(self, init: R, mut operation: FO) -> HashMap<K, R>
    where
        R: Clone,
        FO: FnMut(R, &K, V) -> R,
    {
        self.aggregate(|acc, key, val| {
            let acc = acc.unwrap_or_else(|| init.clone());
            Some(operation(acc, key, val))
        })
    }

    /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
    /// of each group sequentially, passing the previously accumulated value, a reference to the key
    /// and the current element as arguments, and stores the results in a new map.
    ///
    /// This is similar to [`fold`] but the initial value of the accumulator is the first element of the group.
    ///
    /// `operation` is a function that is invoked on each element with the following parameters:
    ///  - the current value of the accumulator of the group;
    ///  - a reference to the key of the group this element belongs to;
    ///  - the element from the source being accumulated.
    ///
    /// Return a `HashMap` associating the key of each group with the result of folding the group elements.
    ///
    /// [`fold`]: #tymethod.fold
    pub fn fold_first<FO>(self, mut operation: FO) -> HashMap<K, V>
    where
        FO: FnMut(V, &K, V) -> V,
    {
        self.aggregate(|acc, key, val| {
            Some(match acc {
                Some(acc) => operation(acc, key, val),
                None => val,
            })
        })
    }

    /// Groups elements from the `GroupingMap` source by key and collects the elements of each group in
    /// an instance of `C`. The iteration order is preserved when inserting elements.
    ///
    /// Return a `HashMap` associating the key of each group with the collection containing the elements of that group.
    pub fn collect<C>(self) -> HashMap<K, C>
    where
        C: Default + Extend<V>,
    {
        self.aggregate(|acc, _, v| {
            let mut acc = acc.unwrap_or_else(C::default);
            acc.extend(Some(v));
            Some(acc)
        })
    }

    /// Groups elements from the `GroupingMap` source by key and counts them.
    ///
    /// Return a `HashMap` associating the key of each group with the number of elements in that group.
    pub fn count(self) -> HashMap<K, usize> {
        self.fold(0, |acc, _, _| acc + 1)
    }
}
<|endoftext|>


<commit_before>extern mod std;
extern mod extra;

struct ChildNode {
    pixel: Pixel,
    parent: ParentNode
}

impl ChildNode {

}

struct Edge {
    source: &ChildNode,
    dest: &ChildNode,
    weight: int
}

impl Edge {
    fn new(source: @ChildNode, dest: @ChildNode)-> Edge {
        Edge {
            source: source,
            dest: dest,
            weight: 0
        }
    }
}

struct ParentNode {
    edges: @[Edge]
}

struct Pixel {
    r: int,
    g: int,
    b: int
}

fn main() {
 //   let pixels: ~[Pixel] = processImage();
 return 1;
}
<commit_msg>change to points (remember we originally wanted to use childnodes for source and dest) and trying to use lifetimes correctly.<commit_after>extern mod std;
extern mod extra;

struct ChildNode<'self> {
    pixel: Pixel,
    parent: &'self ParentNode
}

impl<'self> ChildNode {
     fn new(pixel: Pixel) -> ChildNode {
     	let edgelist = ~[];
	ChildNode {
		  pixel: pixel,
		  parent: ParentNode {
		  	  edges: edgelist
		 }
	}
     }
}

struct ParentNode<'self> {
    edges: &'self [Edge]
}

struct Point {
       x: int,
       y: int
}

//the source and dest
struct Edge<'self> {
    source: Point,
    dest: Point,
    weight: int
}

impl<'self> Edge {
    fn new<'e>(source: Point, dest: &'e Point)-> &'e Edge {
        Edge {
            source: source,
            dest: dest,
            weight: 0
        }
    }
}

struct Pixel {
    r: int,
    g: int,
    b: int
}

fn main() {
 //   let pixels: ~[Pixel] = processImage();
 return 1;
}
<|endoftext|>


<commit_before>//! Decode pixel data using GDCM when the default features are enabled.

use crate::*;
use dicom_encoding::adapters::DecodeError;
use dicom_encoding::transfer_syntax::TransferSyntaxIndex;
use dicom_transfer_syntax_registry::TransferSyntaxRegistry;
use gdcm_rs::{decode_single_frame_compressed, GDCMPhotometricInterpretation, GDCMTransferSyntax};
use std::convert::TryFrom;
use std::str::FromStr;

impl<D> PixelDecoder for FileDicomObject<InMemDicomObject<D>>
where
    D: DataDictionary + Clone,
{
    fn decode_pixel_data(&self) -> Result<DecodedPixelData> {
        use super::attribute::*;

        let pixel_data = pixel_data(self).context(GetAttributeSnafu)?;
        let cols = cols(self).context(GetAttributeSnafu)?;
        let rows = rows(self).context(GetAttributeSnafu)?;

        let photometric_interpretation =
            photometric_interpretation(self).context(GetAttributeSnafu)?;
        let pi_type = GDCMPhotometricInterpretation::from_str(photometric_interpretation.as_str())
            .map_err(|_| {
                UnsupportedPhotometricInterpretationSnafu {
                    pi: photometric_interpretation.clone(),
                }
                .build()
            })?;

        let transfer_syntax = &self.meta().transfer_syntax;
        let registry =
            TransferSyntaxRegistry
                .get(&&transfer_syntax)
                .context(UnknownTransferSyntaxSnafu {
                    ts_uid: transfer_syntax,
                })?;
        let ts_type = GDCMTransferSyntax::from_str(&registry.uid()).map_err(|_| {
            UnsupportedTransferSyntaxSnafu {
                ts: transfer_syntax.clone(),
            }
            .build()
        })?;

        let samples_per_pixel = samples_per_pixel(self).context(GetAttributeSnafu)?;
        let bits_allocated = bits_allocated(self).context(GetAttributeSnafu)?;
        let bits_stored = bits_stored(self).context(GetAttributeSnafu)?;
        let high_bit = high_bit(self).context(GetAttributeSnafu)?;
        let pixel_representation = pixel_representation(self).context(GetAttributeSnafu)?;
        let rescale_intercept = rescale_intercept(self);
        let rescale_slope = rescale_slope(self);
        let number_of_frames = number_of_frames(self).context(GetAttributeSnafu)?;
        let voi_lut_function = voi_lut_function(self).context(GetAttributeSnafu)?;
        let voi_lut_function = voi_lut_function.and_then(|v| VoiLutFunction::try_from(&*v).ok());

        let decoded_pixel_data = match pixel_data.value() {
            Value::PixelSequence {
                fragments,
                offset_table: _,
            } => {
                if fragments.len() > 1 {
                    // Bundle fragments and decode multi-frame dicoms
                    UnsupportedMultiFrameSnafu.fail()?
                }
                let decoded_frame = decode_single_frame_compressed(
                    &fragments[0],
                    cols.into(),
                    rows.into(),
                    pi_type,
                    ts_type,
                    samples_per_pixel,
                    bits_allocated,
                    bits_stored,
                    high_bit,
                    pixel_representation as u16,
                )
                .map_err(|source| InnerError::DecodePixelData {
                    source: DecodeError::Custom {
                        message: "Could not decode frame via GDCM".to_string(),
                        source: Some(Box::new(source) as Box<_>),
                    },
                })?;
                decoded_frame.to_vec()
            }
            Value::Primitive(p) => {
                // Non-encoded, just return the pixel data of the first frame
                let total_bytes = rows as usize
                    * cols as usize
                    * samples_per_pixel as usize
                    * (bits_allocated as usize / 8);
                p.to_bytes()[0..total_bytes].to_vec()
            }
            Value::Sequence { items: _, size: _ } => InvalidPixelDataSnafu.fail()?,
        };

        // pixels are already interpreted,
        // set new photometric interpretation
        let new_pi = match samples_per_pixel {
            1 => PhotometricInterpretation::Monochrome2,
            3 => PhotometricInterpretation::Rgb,
            _ => photometric_interpretation,
        };

        let window = if let Some(window_center) = window_center(self).context(GetAttributeSnafu)? {
            let window_width = window_width(self).context(GetAttributeSnafu)?;

            window_width.map(|width| WindowLevel {
                center: window_center,
                width,
            })
        } else {
            None
        };

        Ok(DecodedPixelData {
            data: Cow::from(decoded_pixel_data),
            cols: cols.into(),
            rows: rows.into(),
            number_of_frames,
            photometric_interpretation: new_pi,
            samples_per_pixel,
            planar_configuration: PlanarConfiguration::Standard,
            bits_allocated,
            bits_stored,
            high_bit,
            pixel_representation,
            rescale_intercept,
            rescale_slope,
            voi_lut_function,
            window,
        })
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use dicom_object::open_file;
    use dicom_test_files;
    use rstest::rstest;
    use std::fs;
    use std::path::Path;

    #[rstest(value => [
        "pydicom/693_J2KI.dcm",
        "pydicom/693_J2KR.dcm",
        "pydicom/693_UNCI.dcm",
        "pydicom/693_UNCR.dcm",
        "pydicom/CT_small.dcm",
        "pydicom/JPEG-lossy.dcm",
        "pydicom/JPEG2000.dcm",
        "pydicom/JPEG2000_UNC.dcm",
        "pydicom/JPGLosslessP14SV1_1s_1f_8b.dcm",
        "pydicom/MR_small.dcm",
        "pydicom/MR_small_RLE.dcm",
        "pydicom/MR_small_implicit.dcm",
        "pydicom/MR_small_jp2klossless.dcm",
        "pydicom/MR_small_jpeg_ls_lossless.dcm",
        "pydicom/explicit_VR-UN.dcm",
        "pydicom/MR_small_bigendian.dcm",
        "pydicom/MR_small_expb.dcm",
        "pydicom/SC_rgb.dcm",
        "pydicom/SC_rgb_16bit.dcm",
        "pydicom/SC_rgb_dcmtk_+eb+cr.dcm",
        "pydicom/SC_rgb_expb.dcm",
        "pydicom/SC_rgb_expb_16bit.dcm",
        "pydicom/SC_rgb_gdcm2k_uncompressed.dcm",
        "pydicom/SC_rgb_gdcm_KY.dcm",
        "pydicom/SC_rgb_jpeg_gdcm.dcm",
        "pydicom/SC_rgb_jpeg_lossy_gdcm.dcm",
        "pydicom/SC_rgb_rle.dcm",
        "pydicom/SC_rgb_rle_16bit.dcm",
        "pydicom/color-pl.dcm",
        "pydicom/color-px.dcm",
        "pydicom/SC_ybr_full_uncompressed.dcm",
])]
    fn test_parse_dicom_pixel_data(value: &str) {
        let test_file = dicom_test_files::path(value).unwrap();
        println!("Parsing pixel data for {}", test_file.display());
        let obj = open_file(test_file).unwrap();
        let pixel_data = obj.decode_pixel_data().unwrap();
        let output_dir =
            Path::new("../target/dicom_test_files/_out/test_gdcm_parse_dicom_pixel_data");
        fs::create_dir_all(output_dir).unwrap();

        for i in 0..pixel_data.number_of_frames {
            let image = pixel_data.to_dynamic_image(i).unwrap();
            let image_path = output_dir.join(format!(
                "{}-{}.png",
                Path::new(value).file_stem().unwrap().to_str().unwrap(),
                i,
            ));
            image.save(image_path).unwrap();
        }
    }

    #[test]
    fn test_to_ndarray_signed_word() {
        let test_file = dicom_test_files::path("pydicom/JPEG2000.dcm").unwrap();
        let obj = open_file(test_file).unwrap();
        let ndarray = obj
            .decode_pixel_data()
            .unwrap()
            .to_ndarray::<i16>()
            .unwrap();
        assert_eq!(ndarray.shape(), &[1, 1024, 256, 1]);
        assert_eq!(ndarray.len(), 262144);
        assert_eq!(ndarray[[0, 260, 0, 0]], -3);
    }
}
<commit_msg>[pixeldata] fix gdcm test<commit_after>//! Decode pixel data using GDCM when the default features are enabled.

use crate::*;
use dicom_encoding::adapters::DecodeError;
use dicom_encoding::transfer_syntax::TransferSyntaxIndex;
use dicom_transfer_syntax_registry::TransferSyntaxRegistry;
use gdcm_rs::{decode_single_frame_compressed, GDCMPhotometricInterpretation, GDCMTransferSyntax};
use std::convert::TryFrom;
use std::str::FromStr;

impl<D> PixelDecoder for FileDicomObject<InMemDicomObject<D>>
where
    D: DataDictionary + Clone,
{
    fn decode_pixel_data(&self) -> Result<DecodedPixelData> {
        use super::attribute::*;

        let pixel_data = pixel_data(self).context(GetAttributeSnafu)?;
        let cols = cols(self).context(GetAttributeSnafu)?;
        let rows = rows(self).context(GetAttributeSnafu)?;

        let photometric_interpretation =
            photometric_interpretation(self).context(GetAttributeSnafu)?;
        let pi_type = GDCMPhotometricInterpretation::from_str(photometric_interpretation.as_str())
            .map_err(|_| {
                UnsupportedPhotometricInterpretationSnafu {
                    pi: photometric_interpretation.clone(),
                }
                .build()
            })?;

        let transfer_syntax = &self.meta().transfer_syntax;
        let registry =
            TransferSyntaxRegistry
                .get(&&transfer_syntax)
                .context(UnknownTransferSyntaxSnafu {
                    ts_uid: transfer_syntax,
                })?;
        let ts_type = GDCMTransferSyntax::from_str(&registry.uid()).map_err(|_| {
            UnsupportedTransferSyntaxSnafu {
                ts: transfer_syntax.clone(),
            }
            .build()
        })?;

        let samples_per_pixel = samples_per_pixel(self).context(GetAttributeSnafu)?;
        let bits_allocated = bits_allocated(self).context(GetAttributeSnafu)?;
        let bits_stored = bits_stored(self).context(GetAttributeSnafu)?;
        let high_bit = high_bit(self).context(GetAttributeSnafu)?;
        let pixel_representation = pixel_representation(self).context(GetAttributeSnafu)?;
        let rescale_intercept = rescale_intercept(self);
        let rescale_slope = rescale_slope(self);
        let number_of_frames = number_of_frames(self).context(GetAttributeSnafu)?;
        let voi_lut_function = voi_lut_function(self).context(GetAttributeSnafu)?;
        let voi_lut_function = voi_lut_function.and_then(|v| VoiLutFunction::try_from(&*v).ok());

        let decoded_pixel_data = match pixel_data.value() {
            Value::PixelSequence {
                fragments,
                offset_table: _,
            } => {
                if fragments.len() > 1 {
                    // Bundle fragments and decode multi-frame dicoms
                    UnsupportedMultiFrameSnafu.fail()?
                }
                let decoded_frame = decode_single_frame_compressed(
                    &fragments[0],
                    cols.into(),
                    rows.into(),
                    pi_type,
                    ts_type,
                    samples_per_pixel,
                    bits_allocated,
                    bits_stored,
                    high_bit,
                    pixel_representation as u16,
                )
                .map_err(|source| InnerError::DecodePixelData {
                    source: DecodeError::Custom {
                        message: "Could not decode frame via GDCM".to_string(),
                        source: Some(Box::new(source) as Box<_>),
                    },
                })?;
                decoded_frame.to_vec()
            }
            Value::Primitive(p) => {
                // Non-encoded, just return the pixel data of the first frame
                let total_bytes = rows as usize
                    * cols as usize
                    * samples_per_pixel as usize
                    * (bits_allocated as usize / 8);
                p.to_bytes()[0..total_bytes].to_vec()
            }
            Value::Sequence { items: _, size: _ } => InvalidPixelDataSnafu.fail()?,
        };

        // pixels are already interpreted,
        // set new photometric interpretation
        let new_pi = match samples_per_pixel {
            1 => PhotometricInterpretation::Monochrome2,
            3 => PhotometricInterpretation::Rgb,
            _ => photometric_interpretation,
        };

        let window = if let Some(window_center) = window_center(self).context(GetAttributeSnafu)? {
            let window_width = window_width(self).context(GetAttributeSnafu)?;

            window_width.map(|width| WindowLevel {
                center: window_center,
                width,
            })
        } else {
            None
        };

        Ok(DecodedPixelData {
            data: Cow::from(decoded_pixel_data),
            cols: cols.into(),
            rows: rows.into(),
            number_of_frames,
            photometric_interpretation: new_pi,
            samples_per_pixel,
            planar_configuration: PlanarConfiguration::Standard,
            bits_allocated,
            bits_stored,
            high_bit,
            pixel_representation,
            rescale_intercept,
            rescale_slope,
            voi_lut_function,
            window,
        })
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use dicom_object::open_file;
    use dicom_test_files;
    use rstest::rstest;
    use std::fs;
    use std::path::Path;

    #[rstest(value => [
        "pydicom/693_J2KI.dcm",
        "pydicom/693_J2KR.dcm",
        "pydicom/693_UNCI.dcm",
        "pydicom/693_UNCR.dcm",
        "pydicom/CT_small.dcm",
        "pydicom/JPEG-lossy.dcm",
        "pydicom/JPEG2000.dcm",
        "pydicom/JPEG2000_UNC.dcm",
        "pydicom/JPGLosslessP14SV1_1s_1f_8b.dcm",
        "pydicom/MR_small.dcm",
        "pydicom/MR_small_RLE.dcm",
        "pydicom/MR_small_implicit.dcm",
        "pydicom/MR_small_jp2klossless.dcm",
        "pydicom/MR_small_jpeg_ls_lossless.dcm",
        "pydicom/explicit_VR-UN.dcm",
        "pydicom/MR_small_bigendian.dcm",
        "pydicom/MR_small_expb.dcm",
        "pydicom/SC_rgb.dcm",
        "pydicom/SC_rgb_16bit.dcm",
        "pydicom/SC_rgb_dcmtk_+eb+cr.dcm",
        "pydicom/SC_rgb_expb.dcm",
        "pydicom/SC_rgb_expb_16bit.dcm",
        "pydicom/SC_rgb_gdcm2k_uncompressed.dcm",
        "pydicom/SC_rgb_gdcm_KY.dcm",
        "pydicom/SC_rgb_jpeg_gdcm.dcm",
        "pydicom/SC_rgb_jpeg_lossy_gdcm.dcm",
        "pydicom/SC_rgb_rle.dcm",
        "pydicom/SC_rgb_rle_16bit.dcm",
        "pydicom/color-pl.dcm",
        "pydicom/color-px.dcm",
        "pydicom/SC_ybr_full_uncompressed.dcm",
])]
    fn test_parse_dicom_pixel_data(value: &str) {
        let test_file = dicom_test_files::path(value).unwrap();
        println!("Parsing pixel data for {}", test_file.display());
        let obj = open_file(test_file).unwrap();
        let pixel_data = obj.decode_pixel_data().unwrap();
        let output_dir =
            Path::new("../target/dicom_test_files/_out/test_gdcm_parse_dicom_pixel_data");
        fs::create_dir_all(output_dir).unwrap();

        for i in 0..pixel_data.number_of_frames {
            let image = pixel_data.to_dynamic_image(i).unwrap();
            let image_path = output_dir.join(format!(
                "{}-{}.png",
                Path::new(value).file_stem().unwrap().to_str().unwrap(),
                i,
            ));
            image.save(image_path).unwrap();
        }
    }

    #[test]
    fn test_to_ndarray_signed_word_no_lut() {
        let test_file = dicom_test_files::path("pydicom/JPEG2000.dcm").unwrap();
        let obj = open_file(test_file).unwrap();
        let options = ConvertOptions::new()
            .with_modality_lut(ModalityLutOption::None);
        let ndarray = obj
            .decode_pixel_data()
            .unwrap()
            .to_ndarray_with_options::<i16>(&options)
            .unwrap();
        assert_eq!(ndarray.shape(), &[1, 1024, 256, 1]);
        assert_eq!(ndarray.len(), 262144);
        assert_eq!(ndarray[[0, 260, 0, 0]], -3);
    }
}
<|endoftext|>


<commit_before>//! A midi sequence describes an expected sequence to be played.

use editdistancewf;
use Result;
use note::Note;

/// A vector of notes that are expected to be played linearly.  The notes can be played legato.
/// The inner vector holds notes that should be played simultaneously, such as with both hands.
#[derive(Debug)]
pub struct ScaleSeq(pub Vec<Vec<Note>>);

impl ScaleSeq {
    /// Generate the sequence for the described scale.
    pub fn from_scale(scale: &Scale) -> Result<ScaleSeq> {
        let base = Note::from_str(&scale.base)?;
        // println!("base: {:?}", base);

        // Build up the notes based on the interval.
        let mut first = base;
        let mut last = base;
        let mut notes = vec![base];
        for _ in 0 .. scale.octaves {
            for ch in scale.intervals.chars() {
                let next = match ch {
                    'H' => 1,
                    'W' => 2,
                    'm' => 3,
                    'M' => 4,
                    '4' => 5,
                    _ => return Err(format!("Invalid interval: {:?}", scale.intervals).into()),
                };
                let next = last + next;
                notes.push(next);
                last = next;
            }
            if first + 12 != last {
                return Err(format!("Scale is not exactly one octave: {:?}", scale.intervals).into());
            }
            first = last;
        }

        // Generate the appropriate scale type.
        match scale.style.as_str() {
            "updown" => {
                // Reflect the scale back on itself, except eliminate the duplicate note.
                let mut other = notes.clone();
                other.reverse();
                notes.extend(other.iter().skip(1));
            }
            style => return Err(format!("Unknown scale style: {:?}", style).into()),
        }

        // Build the note vectors out of the notes.
        let notes: Vec<_> = notes.iter().map(|&n| {
            let mut each = vec![n];
            for i in 1..scale.hands {
                each.push(n + (12 * i) as i8);
            }
            each
        }).collect();

        Ok(ScaleSeq(notes))
    }

    /// Convert an input voicing into a sequence.  This is very straightforward, as the voicing
    /// exercises are generated before entering into the database.
    pub fn from_voicing(voicing: &Voicing) -> Result<ScaleSeq> {
        Ok(ScaleSeq(voicing.chords.iter().map(|chord| {
            chord.iter().map(|note| Note(*note)).collect()
        }).collect()))
    }

    /// Convert an input lick into a sequence.  This is also very straightforward.
    pub fn from_lick(lick: &Lick) -> Result<ScaleSeq> {
        Ok(ScaleSeq(lick.notes.iter().map(|chord| {
            chord.iter().map(|note| Note(*note)).collect()
        }).collect()))
    }

    /// Scales can be played in a different octave than requested.  Compare the first note the user
    /// played with the note given.  If they are off by some number of octaves, adjust all of the
    /// notes in the ScaleSeq.  Returns true if the first note matches and a possible adjustment
    /// has been made.  Return false if there are either no notes, or the first not is not the
    /// right note.
    pub fn adjust_octave(&mut self, played: &[Vec<Note>]) -> bool {
        let my_first = match self.0.first() {
            None => return false,
            Some(v) => {
                match v.first() {
                    None => return false,
                    Some(&v) => v,
                }
            }
        };
        let played_first = match played.first() {
            None => return false,
            Some(v) => {
                match v.first() {
                    None => return false,
                    Some(&v) => v,
                }
            }
        };

        if my_first == played_first {
            return true;
        }

        let shift = played_first.0 as i32 - my_first.0 as i32;
        if shift % 12 == 0 {
            for me in &mut self.0 {
                for n in me.iter_mut() {
                    *n = *n + shift as i8;
                }
            }
            true
        } else {
            false
        }
    }

    /// Determine how different what the user played is from what is given.
    pub fn differences(&self, played: &[Vec<Note>]) -> usize {
        // println!("Compare: {:?} and\n         {:?}", self.0, played);
        editdistancewf::distance(ChordNoteIter::new(&self.0),
            ChordNoteIter::new(played))
    }
}

// An iterator that spreads the notes out of a chord, and inserts a separator between them.  Since
// MIDI notes can only have the value 0-127, we can just use something like 128 as the chord
// marker.
struct ChordNoteIter<'a> {
    // The chords we're iterating over.  If the slice is empty, we're done.
    chords: &'a [Vec<Note>],
    // The position within the first chord.  If this is past the end of the chords, we're
    // generating the separator.
    pos: usize,
}

impl<'a> ChordNoteIter<'a> {
    fn new(chords: &[Vec<Note>]) -> ChordNoteIter {
        ChordNoteIter {
            chords: chords,
            pos: 0,
        }
    }
}

impl<'a> Iterator for ChordNoteIter<'a> {
    type Item = Note;

    fn next(&mut self) -> Option<Self::Item> {
        let chord = match self.chords.first() {
            None => return None,
            Some(ch) => ch,
        };

        if self.pos >= chord.len() {
            self.chords = &self.chords[1..];
            self.pos = 0;
            Some(Note(128))
        } else {
            let result = chord[self.pos];
            self.pos += 1;
            Some(result)
        }
    }
}

/// A structure mapping to the json data that is the input for a scale.
#[derive(Debug, Deserialize)]
pub struct Scale {
    pub base: String,
    pub intervals: String,
    pub hands: u32,
    pub octaves: u32,
    pub style: String,
}

/// A structure mapping to the json data that is the input for a voicing.
#[derive(Debug, Deserialize)]
pub struct Voicing {
    chords: Vec<Vec<u8>>,
}

/// A structure mapping to the json data that is the input for a lick.
#[derive(Debug, Deserialize)]
pub struct Lick {
    notes: Vec<Vec<u8>>,
}
<commit_msg>Implement a "3up" scale type<commit_after>//! A midi sequence describes an expected sequence to be played.

use editdistancewf;
use Result;
use note::Note;

/// A vector of notes that are expected to be played linearly.  The notes can be played legato.
/// The inner vector holds notes that should be played simultaneously, such as with both hands.
#[derive(Debug)]
pub struct ScaleSeq(pub Vec<Vec<Note>>);

impl ScaleSeq {
    /// Generate the sequence for the described scale.
    pub fn from_scale(scale: &Scale) -> Result<ScaleSeq> {
        let base = Note::from_str(&scale.base)?;
        // println!("base: {:?}", base);

        // Build up the notes based on the interval.
        let mut first = base;
        let mut last = base;
        let mut notes = vec![base];
        // For the '3up' exercise, extend by 2 octaves to generate the other notes.
        let octaves = if scale.style == "3up" {
            scale.octaves + 2
        } else {
            scale.octaves
        };
        for _ in 0 .. octaves {
            for ch in scale.intervals.chars() {
                let next = match ch {
                    'H' => 1,
                    'W' => 2,
                    'm' => 3,
                    'M' => 4,
                    '4' => 5,
                    _ => return Err(format!("Invalid interval: {:?}", scale.intervals).into()),
                };
                let next = last + next;
                notes.push(next);
                last = next;
            }
            if first + 12 != last {
                return Err(format!("Scale is not exactly one octave: {:?}", scale.intervals).into());
            }
            first = last;
        }

        // Generate the appropriate scale type.
        match scale.style.as_str() {
            "updown" => {
                // Reflect the scale back on itself, except eliminate the duplicate note.
                let mut other = notes.clone();
                other.reverse();
                notes.extend(other.iter().skip(1));
            }
            "3up" => {
                // Go up and down in broken thirds going up.
                // We need to extend the scale by one note in each direction.
                let orig = notes;
                let per_octave = (orig.len() - 1) / octaves as usize;
                notes = vec![];
                for i in per_octave .. 2 * per_octave {
                    notes.push(orig[i]);
                    notes.push(orig[i + 2]);
                }
                for i in (per_octave - 1 .. 2 * per_octave + 1).rev() {
                    notes.push(orig[i]);
                    notes.push(orig[i + 2]);
                }
                // End with the starting note.
                notes.push(orig[per_octave]);
            }
            style => return Err(format!("Unknown scale style: {:?}", style).into()),
        }

        // Build the note vectors out of the notes.
        let notes: Vec<_> = notes.iter().map(|&n| {
            let mut each = vec![n];
            for i in 1..scale.hands {
                each.push(n + (12 * i) as i8);
            }
            each
        }).collect();

        Ok(ScaleSeq(notes))
    }

    /// Convert an input voicing into a sequence.  This is very straightforward, as the voicing
    /// exercises are generated before entering into the database.
    pub fn from_voicing(voicing: &Voicing) -> Result<ScaleSeq> {
        Ok(ScaleSeq(voicing.chords.iter().map(|chord| {
            chord.iter().map(|note| Note(*note)).collect()
        }).collect()))
    }

    /// Convert an input lick into a sequence.  This is also very straightforward.
    pub fn from_lick(lick: &Lick) -> Result<ScaleSeq> {
        Ok(ScaleSeq(lick.notes.iter().map(|chord| {
            chord.iter().map(|note| Note(*note)).collect()
        }).collect()))
    }

    /// Scales can be played in a different octave than requested.  Compare the first note the user
    /// played with the note given.  If they are off by some number of octaves, adjust all of the
    /// notes in the ScaleSeq.  Returns true if the first note matches and a possible adjustment
    /// has been made.  Return false if there are either no notes, or the first not is not the
    /// right note.
    pub fn adjust_octave(&mut self, played: &[Vec<Note>]) -> bool {
        let my_first = match self.0.first() {
            None => return false,
            Some(v) => {
                match v.first() {
                    None => return false,
                    Some(&v) => v,
                }
            }
        };
        let played_first = match played.first() {
            None => return false,
            Some(v) => {
                match v.first() {
                    None => return false,
                    Some(&v) => v,
                }
            }
        };

        if my_first == played_first {
            return true;
        }

        let shift = played_first.0 as i32 - my_first.0 as i32;
        if shift % 12 == 0 {
            for me in &mut self.0 {
                for n in me.iter_mut() {
                    *n = *n + shift as i8;
                }
            }
            true
        } else {
            false
        }
    }

    /// Determine how different what the user played is from what is given.
    pub fn differences(&self, played: &[Vec<Note>]) -> usize {
        // println!("Compare: {:?} and\n         {:?}", self.0, played);
        editdistancewf::distance(ChordNoteIter::new(&self.0),
            ChordNoteIter::new(played))
    }
}

// An iterator that spreads the notes out of a chord, and inserts a separator between them.  Since
// MIDI notes can only have the value 0-127, we can just use something like 128 as the chord
// marker.
struct ChordNoteIter<'a> {
    // The chords we're iterating over.  If the slice is empty, we're done.
    chords: &'a [Vec<Note>],
    // The position within the first chord.  If this is past the end of the chords, we're
    // generating the separator.
    pos: usize,
}

impl<'a> ChordNoteIter<'a> {
    fn new(chords: &[Vec<Note>]) -> ChordNoteIter {
        ChordNoteIter {
            chords: chords,
            pos: 0,
        }
    }
}

impl<'a> Iterator for ChordNoteIter<'a> {
    type Item = Note;

    fn next(&mut self) -> Option<Self::Item> {
        let chord = match self.chords.first() {
            None => return None,
            Some(ch) => ch,
        };

        if self.pos >= chord.len() {
            self.chords = &self.chords[1..];
            self.pos = 0;
            Some(Note(128))
        } else {
            let result = chord[self.pos];
            self.pos += 1;
            Some(result)
        }
    }
}

/// A structure mapping to the json data that is the input for a scale.
#[derive(Debug, Deserialize)]
pub struct Scale {
    pub base: String,
    pub intervals: String,
    pub hands: u32,
    pub octaves: u32,
    pub style: String,
}

/// A structure mapping to the json data that is the input for a voicing.
#[derive(Debug, Deserialize)]
pub struct Voicing {
    chords: Vec<Vec<u8>>,
}

/// A structure mapping to the json data that is the input for a lick.
#[derive(Debug, Deserialize)]
pub struct Lick {
    notes: Vec<Vec<u8>>,
}
<|endoftext|>