<commit_before>// dune-multiscale
// Copyright Holders: Patrick Henning, Rene Milk
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#include "common.hh"

#include <dune/multiscale/msfem/algorithm.hh>
#include <dune/multiscale/problems/elliptic/selector.hh>

int main(int argc, char** argv) {
  try {
    init(argc, argv);
    using namespace Dune::Multiscale;
    using namespace Dune::Multiscale::MsFEM;

    //!TODO include base in config
    DSC_PROFILER.startTiming("msfem.all");

    const std::string datadir = DSC_CONFIG_GET("global.datadir", "data/");

    // generate directories for data output
    DSC::testCreateDirectory(datadir);

    DSC_LOG_INFO << boost::format("Data will be saved under: %s\nLogs will be saved under: %s/%s/ms.log.log\n")
                            % datadir % datadir % DSC_CONFIG_GET("logging.dir", "log");

    // syntax: info_from_par_file / default  / validation of the value

    // coarse_grid_level denotes the (starting) grid refinement level for the global coarse scale problem, i.e. it describes 'H'
    int coarse_grid_level_ = DSC_CONFIG_GETV( "msfem.coarse_grid_level", 4, DSC::ValidateLess< int >( -1 ) );

    // syntax: info_from_par_file / default
    int number_of_layers_ = DSC_CONFIG_GET("msfem.oversampling_layers", 4);

    switch ( DSC_CONFIG_GET( "msfem.oversampling_strategy", 1 ) )
    {
      case 1: break;
      case 2: break;
      default: DUNE_THROW(Dune::InvalidStateException, "Oversampling Strategy must be 1 or 2.");
    }
      //if (!( (DSC_CONFIG_GET( "msfem.oversampling_strategy", 1 ) == 1) || (DSC_CONFIG_GET( "msfem.oversampling_strategy", 1 ) == 2) ))

    // data for the model problem; the information manager
    // (see 'problem_specification.hh' for details)
    const Problem::ModelProblemData info;

    // total_refinement_level denotes the (starting) grid refinement level for the global fine scale problem, i.e. it describes 'h'
    int total_refinement_level_
      = DSC_CONFIG_GETV( "msfem.fine_grid_level", 4, DSC::ValidateLess< int >(coarse_grid_level_-1) );

    // name of the grid file that describes the macro-grid:
    const std::string macroGridName = info.getMacroGridFile();

    DSC_LOG_INFO << "Error File for Elliptic Model Problem " << Dune::Stuff::Common::getTypename(info)
              << " with epsilon = " << DSC_CONFIG_GET("problem.epsilon", 1.0f) << "." << std::endl << std::endl;
    if (DSC_CONFIG_GET("msfem.uniform", true)) {
      if ( DSC_CONFIG_GET("msfem.petrov_galerkin", true) )
        DSC_LOG_INFO << "Use MsFEM in Petrov-Galerkin formulation with an uniform computation, i.e.:" << std::endl;
      else
        DSC_LOG_INFO << "Use MsFEM in classical (symmetric) formulation with an uniform computation, i.e.:" << std::endl;
      DSC_LOG_INFO << "Uniformly refined coarse and fine mesh and" << std::endl;
      DSC_LOG_INFO << "the same number of layers for each (oversampled) local grid computation." << std::endl << std::endl;
      DSC_LOG_INFO << "Computations were made for:" << std::endl << std::endl;
      DSC_LOG_INFO << "Refinement Level for (uniform) Fine Grid = " << total_refinement_level_ << std::endl;
      DSC_LOG_INFO << "Refinement Level for (uniform) Coarse Grid = " << coarse_grid_level_ << std::endl;
      DSC_LOG_INFO << "Oversampling Strategy = " << DSC_CONFIG_GET( "msfem.oversampling_strategy", 1 ) << std::endl;
      DSC_LOG_INFO << "Number of layers for oversampling = " << number_of_layers_ << std::endl;
      if ( DSC_CONFIG_GET("msfem.fem_comparison",false) )
       { DSC_LOG_INFO << std::endl << "Comparison with standard FEM computation on the MsFEM Fine Grid, i.e. on Refinement Level " << total_refinement_level_ << std::endl; }
      DSC_LOG_INFO << std::endl << std::endl;
    } else {
      if ( DSC_CONFIG_GET("msfem.petrov_galerkin", true) )
        DSC_LOG_INFO << "Use MsFEM in Petrov-Galerkin formulation with an adaptive computation, i.e.:" << std::endl;
      else
        DSC_LOG_INFO << "Use MsFEM in classical (symmetric) formulation with an adaptive computation, i.e.:" << std::endl;
      DSC_LOG_INFO << "Starting with a uniformly refined coarse and fine mesh and" << std::endl;
      DSC_LOG_INFO << "the same number of layers for each (oversampled) local grid computation." << std::endl << std::endl;
      DSC_LOG_INFO << "Error tolerance = " << DSC_CONFIG_GET("msfem.error_tolerance", 1e-6) << std::endl << std::endl;
      DSC_LOG_INFO << "Computations were made for:" << std::endl << std::endl;
      DSC_LOG_INFO << "(Starting) Refinement Level for (uniform) Fine Grid = " << total_refinement_level_ << std::endl;
      DSC_LOG_INFO << "(Starting) Refinement Level for (uniform) Coarse Grid = " << coarse_grid_level_ << std::endl;
      DSC_LOG_INFO << "Oversampling Strategy = " << DSC_CONFIG_GET( "msfem.oversampling_strategy", 1 ) << std::endl;
      DSC_LOG_INFO << "(Starting) Number of layers for oversampling = " << number_of_layers_ << std::endl;
      if ( DSC_CONFIG_GET("msfem.fem_comparison",false) )
      { DSC_LOG_INFO << std::endl << "Comparison with a standard FEM computation on the MsFEM Fine Grid." << std::endl; }
      DSC_LOG_INFO << std::endl << std::endl;
    }

    //! ---------------------- local error indicators --------------------------------
    // ----- local error indicators (for each coarse grid element T) -------------
    const int max_loop_number = 10;
    // local coarse residual, i.e. H ||f||_{L^2(T)}
    CommonTraits::RangeVectorVector loc_coarse_residual_(max_loop_number);
    // local coarse grid jumps (contribute to the total coarse residual)
    CommonTraits::RangeVectorVector loc_coarse_grid_jumps_(max_loop_number);
    // local projection error (we project to get a globaly continous approximation)
    CommonTraits::RangeVectorVector loc_projection_error_(max_loop_number);
    // local jump in the conservative flux
    CommonTraits::RangeVectorVector loc_conservative_flux_jumps_(max_loop_number);
    // local approximation error
    CommonTraits::RangeVectorVector loc_approximation_error_(max_loop_number);
    // local sum over the fine grid jumps (for a fixed subgrid that cooresponds with a coarse entity T)
    CommonTraits::RangeVectorVector loc_fine_grid_jumps_(max_loop_number);

    CommonTraits::RangeVector total_coarse_residual_(max_loop_number);
    CommonTraits::RangeVector total_projection_error_(max_loop_number);
    CommonTraits::RangeVector total_coarse_grid_jumps_(max_loop_number);
    CommonTraits::RangeVector total_conservative_flux_jumps_(max_loop_number);
    CommonTraits::RangeVector total_approximation_error_(max_loop_number);
    CommonTraits::RangeVector total_fine_grid_jumps_(max_loop_number);
    CommonTraits::RangeVector total_estimated_H1_error_(max_loop_number);

    //! TODO put these into something like a named tuple/class
    std::vector<CommonTraits::RangeVectorVector*> locals = {{ &loc_coarse_residual_, &loc_coarse_grid_jumps_,
                                                             &loc_projection_error_, &loc_conservative_flux_jumps_,
                                                             &loc_approximation_error_, &loc_fine_grid_jumps_}};
    std::vector<CommonTraits::RangeVector*> totals = {{&total_coarse_residual_, &total_projection_error_,
                                                      &total_coarse_grid_jumps_, &total_conservative_flux_jumps_,
                                                      &total_approximation_error_, &total_fine_grid_jumps_ }};

    unsigned int loop_number = 0;
    while (algorithm(macroGridName, loop_number++, total_refinement_level_, coarse_grid_level_,
                     number_of_layers_, locals, totals, total_estimated_H1_error_))
    {}

    // the reference problem generaly has a 'refinement_difference_for_referenceproblem' higher resolution than the
    //normal
    // macro problem

    const auto cpu_time = DSC_PROFILER.stopTiming("msfem.all");
    DSC_LOG_INFO << "Total runtime of the program: " << cpu_time << "ms" << std::endl;
    DSC_PROFILER.outputTimings("profiler");
    return 0;
  } catch (Dune::Exception& e) {
    std::cerr << e.what() << std::endl;
  } catch (const std::exception& ex) {
    std::cerr << "Caught std::exception: " << ex.what() << "\n";
  } catch (const std::string& ex) {
    std::cerr << "Caught string-type exception: " << ex << "\n";
  } catch (...) {
    std::cerr << "Exception of non-known type thrown!\n";
  }
  return 1;
} // main
<commit_msg>Better timing output in parallel runs<commit_after>// dune-multiscale
// Copyright Holders: Patrick Henning, Rene Milk
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#include "common.hh"

#include <dune/multiscale/msfem/algorithm.hh>
#include <dune/multiscale/problems/elliptic/selector.hh>

int main(int argc, char** argv) {
  try {
    init(argc, argv);
    using namespace Dune::Multiscale;
    using namespace Dune::Multiscale::MsFEM;

    //!TODO include base in config
    DSC_PROFILER.startTiming("msfem.all");

    const std::string datadir = DSC_CONFIG_GET("global.datadir", "data/");

    // generate directories for data output
    DSC::testCreateDirectory(datadir);

    DSC_LOG_INFO << boost::format("Data will be saved under: %s\nLogs will be saved under: %s/%s/ms.log.log\n")
                            % datadir % datadir % DSC_CONFIG_GET("logging.dir", "log");

    // syntax: info_from_par_file / default  / validation of the value

    // coarse_grid_level denotes the (starting) grid refinement level for the global coarse scale problem, i.e. it describes 'H'
    int coarse_grid_level_ = DSC_CONFIG_GETV( "msfem.coarse_grid_level", 4, DSC::ValidateLess< int >( -1 ) );

    // syntax: info_from_par_file / default
    int number_of_layers_ = DSC_CONFIG_GET("msfem.oversampling_layers", 4);

    switch ( DSC_CONFIG_GET( "msfem.oversampling_strategy", 1 ) )
    {
      case 1: break;
      case 2: break;
      default: DUNE_THROW(Dune::InvalidStateException, "Oversampling Strategy must be 1 or 2.");
    }
      //if (!( (DSC_CONFIG_GET( "msfem.oversampling_strategy", 1 ) == 1) || (DSC_CONFIG_GET( "msfem.oversampling_strategy", 1 ) == 2) ))

    // data for the model problem; the information manager
    // (see 'problem_specification.hh' for details)
    const Problem::ModelProblemData info;

    // total_refinement_level denotes the (starting) grid refinement level for the global fine scale problem, i.e. it describes 'h'
    int total_refinement_level_
      = DSC_CONFIG_GETV( "msfem.fine_grid_level", 4, DSC::ValidateLess< int >(coarse_grid_level_-1) );

    // name of the grid file that describes the macro-grid:
    const std::string macroGridName = info.getMacroGridFile();

    DSC_LOG_INFO << "Error File for Elliptic Model Problem " << Dune::Stuff::Common::getTypename(info)
              << " with epsilon = " << DSC_CONFIG_GET("problem.epsilon", 1.0f) << "." << std::endl << std::endl;
    if (DSC_CONFIG_GET("msfem.uniform", true)) {
      if ( DSC_CONFIG_GET("msfem.petrov_galerkin", true) )
        DSC_LOG_INFO << "Use MsFEM in Petrov-Galerkin formulation with an uniform computation, i.e.:" << std::endl;
      else
        DSC_LOG_INFO << "Use MsFEM in classical (symmetric) formulation with an uniform computation, i.e.:" << std::endl;
      DSC_LOG_INFO << "Uniformly refined coarse and fine mesh and" << std::endl;
      DSC_LOG_INFO << "the same number of layers for each (oversampled) local grid computation." << std::endl << std::endl;
      DSC_LOG_INFO << "Computations were made for:" << std::endl << std::endl;
      DSC_LOG_INFO << "Refinement Level for (uniform) Fine Grid = " << total_refinement_level_ << std::endl;
      DSC_LOG_INFO << "Refinement Level for (uniform) Coarse Grid = " << coarse_grid_level_ << std::endl;
      DSC_LOG_INFO << "Oversampling Strategy = " << DSC_CONFIG_GET( "msfem.oversampling_strategy", 1 ) << std::endl;
      DSC_LOG_INFO << "Number of layers for oversampling = " << number_of_layers_ << std::endl;
      if ( DSC_CONFIG_GET("msfem.fem_comparison",false) )
       { DSC_LOG_INFO << std::endl << "Comparison with standard FEM computation on the MsFEM Fine Grid, i.e. on Refinement Level " << total_refinement_level_ << std::endl; }
      DSC_LOG_INFO << std::endl << std::endl;
    } else {
      if ( DSC_CONFIG_GET("msfem.petrov_galerkin", true) )
        DSC_LOG_INFO << "Use MsFEM in Petrov-Galerkin formulation with an adaptive computation, i.e.:" << std::endl;
      else
        DSC_LOG_INFO << "Use MsFEM in classical (symmetric) formulation with an adaptive computation, i.e.:" << std::endl;
      DSC_LOG_INFO << "Starting with a uniformly refined coarse and fine mesh and" << std::endl;
      DSC_LOG_INFO << "the same number of layers for each (oversampled) local grid computation." << std::endl << std::endl;
      DSC_LOG_INFO << "Error tolerance = " << DSC_CONFIG_GET("msfem.error_tolerance", 1e-6) << std::endl << std::endl;
      DSC_LOG_INFO << "Computations were made for:" << std::endl << std::endl;
      DSC_LOG_INFO << "(Starting) Refinement Level for (uniform) Fine Grid = " << total_refinement_level_ << std::endl;
      DSC_LOG_INFO << "(Starting) Refinement Level for (uniform) Coarse Grid = " << coarse_grid_level_ << std::endl;
      DSC_LOG_INFO << "Oversampling Strategy = " << DSC_CONFIG_GET( "msfem.oversampling_strategy", 1 ) << std::endl;
      DSC_LOG_INFO << "(Starting) Number of layers for oversampling = " << number_of_layers_ << std::endl;
      if ( DSC_CONFIG_GET("msfem.fem_comparison",false) )
      { DSC_LOG_INFO << std::endl << "Comparison with a standard FEM computation on the MsFEM Fine Grid." << std::endl; }
      DSC_LOG_INFO << std::endl << std::endl;
    }

    //! ---------------------- local error indicators --------------------------------
    // ----- local error indicators (for each coarse grid element T) -------------
    const int max_loop_number = 10;
    // local coarse residual, i.e. H ||f||_{L^2(T)}
    CommonTraits::RangeVectorVector loc_coarse_residual_(max_loop_number);
    // local coarse grid jumps (contribute to the total coarse residual)
    CommonTraits::RangeVectorVector loc_coarse_grid_jumps_(max_loop_number);
    // local projection error (we project to get a globaly continous approximation)
    CommonTraits::RangeVectorVector loc_projection_error_(max_loop_number);
    // local jump in the conservative flux
    CommonTraits::RangeVectorVector loc_conservative_flux_jumps_(max_loop_number);
    // local approximation error
    CommonTraits::RangeVectorVector loc_approximation_error_(max_loop_number);
    // local sum over the fine grid jumps (for a fixed subgrid that cooresponds with a coarse entity T)
    CommonTraits::RangeVectorVector loc_fine_grid_jumps_(max_loop_number);

    CommonTraits::RangeVector total_coarse_residual_(max_loop_number);
    CommonTraits::RangeVector total_projection_error_(max_loop_number);
    CommonTraits::RangeVector total_coarse_grid_jumps_(max_loop_number);
    CommonTraits::RangeVector total_conservative_flux_jumps_(max_loop_number);
    CommonTraits::RangeVector total_approximation_error_(max_loop_number);
    CommonTraits::RangeVector total_fine_grid_jumps_(max_loop_number);
    CommonTraits::RangeVector total_estimated_H1_error_(max_loop_number);

    //! TODO put these into something like a named tuple/class
    std::vector<CommonTraits::RangeVectorVector*> locals = {{ &loc_coarse_residual_, &loc_coarse_grid_jumps_,
                                                             &loc_projection_error_, &loc_conservative_flux_jumps_,
                                                             &loc_approximation_error_, &loc_fine_grid_jumps_}};
    std::vector<CommonTraits::RangeVector*> totals = {{&total_coarse_residual_, &total_projection_error_,
                                                      &total_coarse_grid_jumps_, &total_conservative_flux_jumps_,
                                                      &total_approximation_error_, &total_fine_grid_jumps_ }};

    unsigned int loop_number = 0;
    while (algorithm(macroGridName, loop_number++, total_refinement_level_, coarse_grid_level_,
                     number_of_layers_, locals, totals, total_estimated_H1_error_))
    {}

    // the reference problem generaly has a 'refinement_difference_for_referenceproblem' higher resolution than the
    //normal
    // macro problem

    auto cpu_time = DSC_PROFILER.stopTiming("msfem.all");
    auto max_cpu_time = Dune::MPIManager::comm().max(cpu_time);
    if (Dune::MPIManager::rank()==0) {
      DSC_LOG_INFO << "Maximum total runtime of the program over all processes: "
                   << max_cpu_time
                   << "ms" << std::endl;
      DSC_PROFILER.outputTimings("profiler");
    }
    return 0;
  } catch (Dune::Exception& e) {
    std::cerr << e.what() << std::endl;
  } catch (const std::exception& ex) {
    std::cerr << "Caught std::exception: " << ex.what() << "\n";
  } catch (const std::string& ex) {
    std::cerr << "Caught string-type exception: " << ex << "\n";
  } catch (...) {
    std::cerr << "Exception of non-known type thrown!\n";
  }
  return 1;
} // main
<|endoftext|>


<commit_before>#include "catch.hpp"

// mapnik vector tile tile class
#include "vector_tile_tile.hpp"

TEST_CASE("Vector tile base class")
{
    mapnik::box2d<double> global_extent(-20037508.342789,-20037508.342789,20037508.342789,20037508.342789);

    SECTION("default constructed")
    {
        mapnik::vector_tile_impl::tile default_tile(global_extent);

        CHECK(default_tile.size() == 0);
        CHECK(default_tile.data()[0] == '\0');
        CHECK(std::abs(default_tile.scale() - 9783.9396205024) < 0.00001);

        std::string str;
        default_tile.serialize_to_string(str);
        CHECK(str == "");
        CHECK(default_tile.is_painted() == false);
        CHECK(default_tile.is_empty() == true);

        CHECK(default_tile.extent() == global_extent);
        CHECK(default_tile.get_buffered_extent() == global_extent);
        CHECK(default_tile.tile_size() == 4096);

        CHECK(default_tile.get_painted_layers().empty() == true);
        CHECK(default_tile.get_empty_layers().empty() == true);
        CHECK(default_tile.get_layers().empty() == true);
        CHECK(default_tile.get_layers_set().empty() == true);

        CHECK(default_tile.has_layer("anything") == false);

        vector_tile::Tile t;
        t = default_tile.get_tile();
        CHECK(t.layers_size() == 0);
    }

    SECTION("construction with zero tile_size")
    {
        mapnik::vector_tile_impl::tile zero_size_tile(global_extent, 0);

        CHECK(zero_size_tile.tile_size() == 0);
        CHECK(std::abs(zero_size_tile.scale() - 40075016.6855780035) < 0.00001);
        CHECK(zero_size_tile.get_buffered_extent() == global_extent);
    }

    SECTION("construction with negative tile_size")
    {
        mapnik::vector_tile_impl::tile negative_size_tile(global_extent, -1);

        CHECK(negative_size_tile.tile_size() == 4294967295);
        CHECK(std::abs(negative_size_tile.scale() - 0.0093306919) < 0.0000001);
        CHECK(negative_size_tile.get_buffered_extent() == global_extent);
    }

    SECTION("construction with positive buffer size")
    {
        mapnik::vector_tile_impl::tile positive_buffer_tile(global_extent, 4096, 10);

        mapnik::box2d<double> buffered_extent(-20135347.7389940246939659,-20135347.7389940246939659,20135347.7389940246939659,20135347.7389940246939659);
        CHECK(positive_buffer_tile.get_buffered_extent() == buffered_extent);
        CHECK(positive_buffer_tile.buffer_size() == 10);
    }

    SECTION("construction with very negative buffer size")
    {
        mapnik::vector_tile_impl::tile negative_buffer_tile(global_extent, 4096, -4000);
        mapnik::box2d<double> buffered_extent(0.0, 0.0, 0.0, 0.0);
        CHECK(negative_buffer_tile.get_buffered_extent() == buffered_extent);
        CHECK(negative_buffer_tile.buffer_size() == -4000);
    }

    SECTION("add bogus layer buffer")
    {
        mapnik::vector_tile_impl::tile tile(global_extent);
        std::string bogus_layer_buffer = "blahblah";

        tile.append_layer_buffer(bogus_layer_buffer.data(), bogus_layer_buffer.length(), "bogus");

        const std::set<std::string> expected_set{"bogus"};
        const std::set<std::string> empty_set;
        const std::vector<std::string> expected_vec{"bogus"};

        CHECK(tile.get_painted_layers() == expected_set);
        CHECK(tile.get_empty_layers() == empty_set);
        CHECK(tile.get_layers() == expected_vec);
        CHECK(tile.get_layers_set() == expected_set);
        CHECK(tile.has_layer("bogus") == true);
        CHECK(tile.is_painted() == true);
        CHECK(tile.is_empty() == false);

        CHECK(tile.size() == 10);

        std::string str;
        tile.serialize_to_string(str);
        CHECK(str == "\32\10blahblah");

        std::string buffer(tile.data());

        // Check the buffer itself
        protozero::pbf_reader read_back(buffer);
        if (read_back.next(3))
        {
            std::string blah_blah = read_back.get_string();
            CHECK(blah_blah == "blahblah");
        }

        // Check the provided reader
        protozero::pbf_reader tile_reader = tile.get_reader();
        if (tile_reader.next(3))
        {
            std::string blah_blah = tile_reader.get_string();
            CHECK(blah_blah == "blahblah");
        }

        protozero::pbf_reader layer_reader;
        CHECK_THROWS_AS(tile.layer_reader("bogus", layer_reader), protozero::end_of_buffer_exception);

        protozero::pbf_reader layer_reader_by_index;
        bool status = tile.layer_reader(0, layer_reader_by_index);

        CHECK(status == true);
        CHECK_THROWS_AS(layer_reader_by_index.next(1), protozero::end_of_buffer_exception);

        vector_tile::Tile bogus_tile = tile.get_tile();
        CHECK(bogus_tile.layers_size() == 1);
        vector_tile::Tile_Layer bogus_layer = bogus_tile.layers(0);
        CHECK(bogus_layer.version() == 1);
        CHECK(bogus_layer.name() == "");
        CHECK(bogus_layer.features_size() == 0);
        CHECK(bogus_layer.keys_size() == 0);
        CHECK(bogus_layer.values_size() == 0);
        CHECK(bogus_layer.extent() == 4096);
    }

    SECTION("Add valid layer")
    {
        mapnik::vector_tile_impl::tile tile(global_extent);

        // Create layer
        vector_tile::Tile_Layer layer;
        layer.set_version(2);
        layer.set_name("valid");

        std::string layer_buffer;
        layer.SerializePartialToString(&layer_buffer);
        tile.append_layer_buffer(layer_buffer.data(), layer_buffer.length(), "valid");

        const std::set<std::string> expected_set{"valid"};
        const std::set<std::string> empty_set;
        const std::vector<std::string> expected_vec{"valid"};

        CHECK(tile.get_painted_layers() == expected_set);
        CHECK(tile.get_empty_layers() == empty_set);
        CHECK(tile.get_layers() == expected_vec);
        CHECK(tile.get_layers_set() == expected_set);
        CHECK(tile.has_layer("valid") == true);
        CHECK(tile.is_painted() == true);
        CHECK(tile.is_empty() == false);

        protozero::pbf_reader layer_reader_by_name;
        bool status_by_name = tile.layer_reader("valid", layer_reader_by_name);
        CHECK(status_by_name == true);
        if(layer_reader_by_name.next(1))
        {
            CHECK(layer_reader_by_name.get_string() == "valid");
        }

        protozero::pbf_reader layer_reader_by_index;
        bool status_by_index = tile.layer_reader(0, layer_reader_by_index);
        CHECK(status_by_index == true);
        if(layer_reader_by_index.next(1))
        {
            CHECK(layer_reader_by_index.get_string() == "valid");
        }

        vector_tile::Tile parsed_tile = tile.get_tile();
        CHECK(parsed_tile.layers_size() == 1);
        vector_tile::Tile_Layer parsed_layer = parsed_tile.layers(0);
        CHECK(parsed_layer.version() == 2);
        CHECK(parsed_layer.name() == "valid");
    }

    SECTION("layer_reader by name works by name in buffer")
    {
        mapnik::vector_tile_impl::tile tile(global_extent);

        // Create layer
        vector_tile::Tile_Layer layer;
        layer.set_version(2);
        layer.set_name("buffer name");

        std::string layer_buffer;
        layer.SerializePartialToString(&layer_buffer);
        tile.append_layer_buffer(layer_buffer.data(), layer_buffer.length(), "layer name");

        const std::set<std::string> expected_set{"layer name"};
        const std::set<std::string> empty_set;
        const std::vector<std::string> expected_vec{"layer name"};

        CHECK(tile.get_painted_layers() == expected_set);
        CHECK(tile.get_layers() == expected_vec);
        CHECK(tile.get_layers_set() == expected_set);
        CHECK(tile.has_layer("layer name") == true);
        CHECK(tile.has_layer("buffer name") == false);

        protozero::pbf_reader layer_reader_by_buffer_name;
        bool status_by_buffer_name = tile.layer_reader("buffer name", layer_reader_by_buffer_name);
        CHECK(status_by_buffer_name == true);
        if(layer_reader_by_buffer_name.next(1))
        {
            CHECK(layer_reader_by_buffer_name.get_string() == "buffer name");
        }

        protozero::pbf_reader layer_reader_by_name;
        bool status_by_layer_name = tile.layer_reader("layer name", layer_reader_by_name);
        CHECK(status_by_layer_name == false);
    }
}
<commit_msg>Add deterministic layer ordering test<commit_after>#include "catch.hpp"

// mapnik vector tile tile class
#include "vector_tile_tile.hpp"

TEST_CASE("Vector tile base class")
{
    mapnik::box2d<double> global_extent(-20037508.342789,-20037508.342789,20037508.342789,20037508.342789);

    SECTION("default constructed")
    {
        mapnik::vector_tile_impl::tile default_tile(global_extent);

        CHECK(default_tile.size() == 0);
        CHECK(default_tile.data()[0] == '\0');
        CHECK(std::abs(default_tile.scale() - 9783.9396205024) < 0.00001);

        std::string str;
        default_tile.serialize_to_string(str);
        CHECK(str == "");
        CHECK(default_tile.is_painted() == false);
        CHECK(default_tile.is_empty() == true);

        CHECK(default_tile.extent() == global_extent);
        CHECK(default_tile.get_buffered_extent() == global_extent);
        CHECK(default_tile.tile_size() == 4096);

        CHECK(default_tile.get_painted_layers().empty() == true);
        CHECK(default_tile.get_empty_layers().empty() == true);
        CHECK(default_tile.get_layers().empty() == true);
        CHECK(default_tile.get_layers_set().empty() == true);

        CHECK(default_tile.has_layer("anything") == false);

        vector_tile::Tile t;
        t = default_tile.get_tile();
        CHECK(t.layers_size() == 0);
    }

    SECTION("construction with zero tile_size")
    {
        mapnik::vector_tile_impl::tile zero_size_tile(global_extent, 0);

        CHECK(zero_size_tile.tile_size() == 0);
        CHECK(std::abs(zero_size_tile.scale() - 40075016.6855780035) < 0.00001);
        CHECK(zero_size_tile.get_buffered_extent() == global_extent);
    }

    SECTION("construction with negative tile_size")
    {
        mapnik::vector_tile_impl::tile negative_size_tile(global_extent, -1);

        CHECK(negative_size_tile.tile_size() == 4294967295);
        CHECK(std::abs(negative_size_tile.scale() - 0.0093306919) < 0.0000001);
        CHECK(negative_size_tile.get_buffered_extent() == global_extent);
    }

    SECTION("construction with positive buffer size")
    {
        mapnik::vector_tile_impl::tile positive_buffer_tile(global_extent, 4096, 10);

        mapnik::box2d<double> buffered_extent(-20135347.7389940246939659,-20135347.7389940246939659,20135347.7389940246939659,20135347.7389940246939659);
        CHECK(positive_buffer_tile.get_buffered_extent() == buffered_extent);
        CHECK(positive_buffer_tile.buffer_size() == 10);
    }

    SECTION("construction with very negative buffer size")
    {
        mapnik::vector_tile_impl::tile negative_buffer_tile(global_extent, 4096, -4000);
        mapnik::box2d<double> buffered_extent(0.0, 0.0, 0.0, 0.0);
        CHECK(negative_buffer_tile.get_buffered_extent() == buffered_extent);
        CHECK(negative_buffer_tile.buffer_size() == -4000);
    }

    SECTION("add bogus layer buffer")
    {
        mapnik::vector_tile_impl::tile tile(global_extent);
        std::string bogus_layer_buffer = "blahblah";

        tile.append_layer_buffer(bogus_layer_buffer.data(), bogus_layer_buffer.length(), "bogus");

        const std::set<std::string> expected_set{"bogus"};
        const std::set<std::string> empty_set;
        const std::vector<std::string> expected_vec{"bogus"};

        CHECK(tile.get_painted_layers() == expected_set);
        CHECK(tile.get_empty_layers() == empty_set);
        CHECK(tile.get_layers() == expected_vec);
        CHECK(tile.get_layers_set() == expected_set);
        CHECK(tile.has_layer("bogus") == true);
        CHECK(tile.is_painted() == true);
        CHECK(tile.is_empty() == false);

        CHECK(tile.size() == 10);

        std::string str;
        tile.serialize_to_string(str);
        CHECK(str == "\32\10blahblah");

        std::string buffer(tile.data());

        // Check the buffer itself
        protozero::pbf_reader read_back(buffer);
        if (read_back.next(3))
        {
            std::string blah_blah = read_back.get_string();
            CHECK(blah_blah == "blahblah");
        }

        // Check the provided reader
        protozero::pbf_reader tile_reader = tile.get_reader();
        if (tile_reader.next(3))
        {
            std::string blah_blah = tile_reader.get_string();
            CHECK(blah_blah == "blahblah");
        }

        protozero::pbf_reader layer_reader;
        CHECK_THROWS_AS(tile.layer_reader("bogus", layer_reader), protozero::end_of_buffer_exception);

        protozero::pbf_reader layer_reader_by_index;
        bool status = tile.layer_reader(0, layer_reader_by_index);

        CHECK(status == true);
        CHECK_THROWS_AS(layer_reader_by_index.next(1), protozero::end_of_buffer_exception);

        vector_tile::Tile bogus_tile = tile.get_tile();
        CHECK(bogus_tile.layers_size() == 1);
        vector_tile::Tile_Layer bogus_layer = bogus_tile.layers(0);
        CHECK(bogus_layer.version() == 1);
        CHECK(bogus_layer.name() == "");
        CHECK(bogus_layer.features_size() == 0);
        CHECK(bogus_layer.keys_size() == 0);
        CHECK(bogus_layer.values_size() == 0);
        CHECK(bogus_layer.extent() == 4096);
    }

    SECTION("Add valid layer")
    {
        mapnik::vector_tile_impl::tile tile(global_extent);

        // Create layer
        vector_tile::Tile_Layer layer;
        layer.set_version(2);
        layer.set_name("valid");

        std::string layer_buffer;
        layer.SerializePartialToString(&layer_buffer);
        tile.append_layer_buffer(layer_buffer.data(), layer_buffer.length(), "valid");

        const std::set<std::string> expected_set{"valid"};
        const std::set<std::string> empty_set;
        const std::vector<std::string> expected_vec{"valid"};

        CHECK(tile.get_painted_layers() == expected_set);
        CHECK(tile.get_empty_layers() == empty_set);
        CHECK(tile.get_layers() == expected_vec);
        CHECK(tile.get_layers_set() == expected_set);
        CHECK(tile.has_layer("valid") == true);
        CHECK(tile.is_painted() == true);
        CHECK(tile.is_empty() == false);

        protozero::pbf_reader layer_reader_by_name;
        bool status_by_name = tile.layer_reader("valid", layer_reader_by_name);
        CHECK(status_by_name == true);
        if(layer_reader_by_name.next(1))
        {
            CHECK(layer_reader_by_name.get_string() == "valid");
        }

        protozero::pbf_reader layer_reader_by_index;
        bool status_by_index = tile.layer_reader(0, layer_reader_by_index);
        CHECK(status_by_index == true);
        if(layer_reader_by_index.next(1))
        {
            CHECK(layer_reader_by_index.get_string() == "valid");
        }

        vector_tile::Tile parsed_tile = tile.get_tile();
        CHECK(parsed_tile.layers_size() == 1);
        vector_tile::Tile_Layer parsed_layer = parsed_tile.layers(0);
        CHECK(parsed_layer.version() == 2);
        CHECK(parsed_layer.name() == "valid");
    }

    SECTION("layer_reader by name works by name in buffer")
    {
        // Note - if the names of the layer are different
        // between the layer in the buffer and in the
        // tile object, `has_layer` will use the one
        // in the tile object, but `layer_reader` will
        // use the name in the buffer
        mapnik::vector_tile_impl::tile tile(global_extent);

        // Create layer
        vector_tile::Tile_Layer layer;
        layer.set_version(2);
        layer.set_name("buffer name");

        // Add layer to tile
        std::string layer_buffer;
        layer.SerializePartialToString(&layer_buffer);
        tile.append_layer_buffer(layer_buffer.data(), layer_buffer.length(), "layer name");

        const std::set<std::string> expected_set{"layer name"};
        const std::vector<std::string> expected_vec{"layer name"};

        // Confirm the use of "layer name" in these methods
        CHECK(tile.get_painted_layers() == expected_set);
        CHECK(tile.get_layers() == expected_vec);
        CHECK(tile.get_layers_set() == expected_set);
        CHECK(tile.has_layer("layer name") == true);
        CHECK(tile.has_layer("buffer name") == false);

        // Confirm the use of "buffer name" in this method
        protozero::pbf_reader layer_reader_by_buffer_name;
        bool status_by_buffer_name = tile.layer_reader("buffer name", layer_reader_by_buffer_name);
        CHECK(status_by_buffer_name == true);
        if(layer_reader_by_buffer_name.next(1))
        {
            CHECK(layer_reader_by_buffer_name.get_string() == "buffer name");
        }

        protozero::pbf_reader layer_reader_by_name;
        bool status_by_layer_name = tile.layer_reader("layer name", layer_reader_by_name);
        CHECK(status_by_layer_name == false);
    }

    SECTION("layer ordering is deterministic")
    {
        // Newly added layers from buffers are added to the end of
        // the tile, and are read from the tile in the same order
        // as they are added
        mapnik::vector_tile_impl::tile tile(global_extent);

        // Create layers
        vector_tile::Tile_Layer layer1, layer2;
        layer1.set_version(2);
        layer1.set_name("layer1");

        layer2.set_version(2);
        layer2.set_name("layer2");

        std::string layer1_buffer, layer2_buffer;
        layer1.SerializePartialToString(&layer1_buffer);
        tile.append_layer_buffer(layer1_buffer.data(), layer1_buffer.length(), "layer1");

        layer2.SerializePartialToString(&layer2_buffer);
        tile.append_layer_buffer(layer2_buffer.data(), layer2_buffer.length(), "layer2");

        const std::vector<std::string> expected_vec{"layer1", "layer2"};

        // Both of the layers are here, in order
        CHECK(tile.get_layers() == expected_vec);
        CHECK(tile.has_layer("layer1") == true);
        CHECK(tile.has_layer("layer2") == true);

        // layer_reader reads them in the same order
        protozero::pbf_reader layer_reader1, layer_reader2;
        bool status1 = tile.layer_reader(0, layer_reader1);
        CHECK(status1 == true);
        if(layer_reader1.next(1))
        {
            CHECK(layer_reader1.get_string() == "layer1");
        }

        bool status2 = tile.layer_reader(0, layer_reader2);
        CHECK(status2 == true);
        if(layer_reader2.next(1))
        {
            CHECK(layer_reader2.get_string() == "layer1");
        }
    }
}
<|endoftext|>


<commit_before>/******************************************************************************
 *
 * Project:  integrating laszip into liblas - http://liblas.org -
 * Purpose:
 * Author:   Martin Isenburg
 *           isenburg at cs.unc.edu
 *
 ******************************************************************************
 * Copyright (c) 2010, Martin Isenburg
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Licence as published
 * by the Free Software Foundation.
 *
 * See the COPYING file for more information.
 *
 ****************************************************************************/

/*
===============================================================================

  FILE:  bytestreamin_istream.hpp

  CONTENTS:

  PROGRAMMERS:

    martin isenburg@cs.unc.edu

  COPYRIGHT:

    copyright (C) 2010  martin isenburg@cs.unc.edu

    This software is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

  CHANGE HISTORY:

    12 December 2010 -- created from ByteStreamOutFile after Howard got pushy (-;

===============================================================================
*/
#ifndef BYTE_STREAM_IN_ISTREAM_H
#define BYTE_STREAM_IN_ISTREAM_H

#include "bytestreamin.hpp"

#if _MSC_VER < 1300
#include <istream.h>
#else
#include <fstream>
#endif

using namespace std;

class ByteStreamInIstream : public ByteStreamIn
{
public:
  ByteStreamInIstream(istream* stream);
/* read a single byte                                        */
  unsigned int getByte();
/* read an array of bytes                                    */
  bool getBytes(unsigned char* bytes, unsigned int num_bytes);
/* returns how many bytes were read since last reset         */
  unsigned int byteCount() const;
/* reset byte counter                                        */
  void resetCount();
/* destructor                                                */
  ~ByteStreamInIstream(){};
private:
  istream* stream;
  ios::off_type start;
};

inline ByteStreamInIstream::ByteStreamInIstream(istream* stream)
{
  this->stream = stream;
  resetCount();
}

inline unsigned int ByteStreamInIstream::getByte()
{
  int byte = stream->get();
  if (stream->bad())
  {
    byte = 0;
  }
  return (unsigned int)byte;
}

inline bool ByteStreamInIstream::getBytes(unsigned char* bytes, unsigned int num_bytes)
{
    // http://stackoverflow.com/questions/604431/c-reading-unsigned-char-from-file-stream
    // std::ifstream only provides a specialization for char, not unsigned char.

    // WARNING, unsafe cast!!! -- hobu

  stream->read( (char*)bytes, num_bytes);
  return !!(stream->good());
}

unsigned int ByteStreamInIstream::byteCount() const
{
  ios::pos_type end = stream->tellg();
  ios::off_type size = end - start;
  return static_cast<unsigned int>(size);
}

void ByteStreamInIstream::resetCount()
{
  start = stream->tellg();
}

#endif
<commit_msg>eof instead of bad<commit_after>/******************************************************************************
 *
 * Project:  integrating laszip into liblas - http://liblas.org -
 * Purpose:
 * Author:   Martin Isenburg
 *           isenburg at cs.unc.edu
 *
 ******************************************************************************
 * Copyright (c) 2010, Martin Isenburg
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Licence as published
 * by the Free Software Foundation.
 *
 * See the COPYING file for more information.
 *
 ****************************************************************************/

/*
===============================================================================

  FILE:  bytestreamin_istream.hpp

  CONTENTS:

  PROGRAMMERS:

    martin isenburg@cs.unc.edu

  COPYRIGHT:

    copyright (C) 2010  martin isenburg@cs.unc.edu

    This software is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

  CHANGE HISTORY:

    12 December 2010 -- created from ByteStreamOutFile after Howard got pushy (-;

===============================================================================
*/
#ifndef BYTE_STREAM_IN_ISTREAM_H
#define BYTE_STREAM_IN_ISTREAM_H

#include "bytestreamin.hpp"

#if _MSC_VER < 1300
#include <istream.h>
#else
#include <fstream>
#endif

using namespace std;

class ByteStreamInIstream : public ByteStreamIn
{
public:
  ByteStreamInIstream(istream* stream);
/* read a single byte                                        */
  unsigned int getByte();
/* read an array of bytes                                    */
  bool getBytes(unsigned char* bytes, unsigned int num_bytes);
/* returns how many bytes were read since last reset         */
  unsigned int byteCount() const;
/* reset byte counter                                        */
  void resetCount();
/* destructor                                                */
  ~ByteStreamInIstream(){};
private:
  istream* stream;
  ios::off_type start;
};

inline ByteStreamInIstream::ByteStreamInIstream(istream* stream)
{
  this->stream = stream;
  resetCount();
}

inline unsigned int ByteStreamInIstream::getByte()
{
  int byte = stream->get();
  if (stream->eof())
  {
    byte = 0;
  }
  return (unsigned int)byte;
}

inline bool ByteStreamInIstream::getBytes(unsigned char* bytes, unsigned int num_bytes)
{
    // http://stackoverflow.com/questions/604431/c-reading-unsigned-char-from-file-stream
    // std::ifstream only provides a specialization for char, not unsigned char.

    // WARNING, unsafe cast!!! -- hobu

  stream->read( (char*)bytes, num_bytes);
  return !!(stream->good());
}

unsigned int ByteStreamInIstream::byteCount() const
{
  ios::pos_type end = stream->tellg();
  ios::off_type size = end - start;
  return static_cast<unsigned int>(size);
}

void ByteStreamInIstream::resetCount()
{
  start = stream->tellg();
}

#endif
<|endoftext|>


<commit_before>#include <stdio.h>
#include <climits>

#include "engine/engine.hpp"

#include "engine/pathfinding/astar.hpp"
#include "engine/pathfinding/path.hpp"

namespace qrw
{
	Engine::Engine()
	:	board(0),
		status(EES_UNDEFINED)
	{
		players[0].setName("Player The First");
		players[0].setId(0);
		players[1].setName("Player The Second");
		players[1].setId(1);

		pathfinder = new AStar();
	}

	Engine::~Engine()
	{
		delete pathfinder;
	}

	void Engine::init(int boardwidth, int boardheight)
	{
		delete board;
		board = new Board(boardwidth, boardheight);
		pathfinder->setBoard(board);
		currentplayer = 0;
		getCurrentPlayer().setActive(true);
		status = EES_PREPARE;

		int maxarmysize = INT_MAX;
		// int maxarmysize = getMaxPlayerUnits();
		players[0].getArmy().deleteAllUnits();
		players[0].getArmy().setMaxSize(maxarmysize);
		players[1].getArmy().deleteAllUnits();
		players[1].getArmy().setMaxSize(maxarmysize);
	}

	void Engine::startGame()
	{
		currentplayer = 0;
		status = EES_RUNNING;
	}

	ENGINSTATES Engine::getStatus()
	{
		return status;
	}

	int Engine::getMaxPlayerUnits()
	{
		if(board)
			return (board->getHeight() * board->getWidth()) / 3;
		return 0;
	}

	void Engine::createPlayerUnits(int playerid, std::map<UNITTYPES, int> unitcounts)
	{
		Player* player = getPlayer(playerid);
		UNITTYPES unittype;
		Unit* unit;

		for(auto iter = unitcounts.begin(); iter != unitcounts.end(); ++iter)
		{
			unittype = iter->first;
			for(int i = 0; i < iter->second; ++i)
			{
				// Create new unit
				switch(unittype)
				{
					case EUT_SWORDMAN:
						unit = new Unit(EUT_SWORDMAN, 5, 2, 1, 1, 3, player, board);
						break;

					case EUT_ARCHER:
						unit = new Unit(EUT_ARCHER, 5, 2, 1, 3, 2, player, board);
						break;

					default:
						unit = new Unit(EUT_SPEARMAN, 5, 2, 1, 2, 2, player, board);
						break;
				}
				// Add new unit to army
				player->getArmy().addUnit(unit);
			}
		}
	}

	// bool Engine::setUnits(int playeroneunits[EUT_NUMBEROFUNITTYPES],
		// int playertwounits[EUT_NUMBEROFUNITTYPES])
	// {
	//	players[0].clearUnits();
	//	players[1].clearUnits();

	//	if(status != EES_PREPARE)
	//		return false;
	//	setPlayerUnits(0, playeroneunits);
	//	setPlayerUnits(1, playertwounits);
	//	return true;
	// }

	// void Engine::setPlayerUnits(int id, int unitnumbers[EUT_NUMBEROFUNITTYPES])
	// {
	//	Player* player = getPlayer(id);
	//	int i;
	//	// Attention! player is "overwritten" in the method Player::addUnit(...).
	//	for(i = 0; i < unitnumbers[EUT_SWORDMAN]; ++i)
	//		player->addUnit(new Unit(EUT_SWORDMAN, 2, 1, 1, 3, player));
	//	for(i = 0; i < unitnumbers[EUT_ARCHER]; ++i)
	//		player->addUnit(new Unit(EUT_ARCHER, 2, 1, 3, 2, player));
	//	for(i = 0; i < unitnumbers[EUT_SPEARMAN]; ++i)
	//		player->addUnit(new Unit(EUT_SPEARMAN, 2, 1, 2, 2, player));
	// }

	Board* Engine::getBoard()
	{
		return board;
	}

	Player& Engine::getCurrentPlayer()
	{
		return players[currentplayer];
	}

	void Engine::endTurn()
	{
		// Reset movement of current players units.
		Army& army = getCurrentPlayer().getArmy();

		for(int i = 0; i < EUT_NUMBEROFUNITTYPES; ++i)
		{
			std::set<Unit*>& unitset = army.getUnitsByType((UNITTYPES)i);

			for(auto iter = unitset.begin(); iter != unitset.end(); ++iter)
				(*iter)->setCurrentMovement((*iter)->getMovement());
		}

		// change player and update active flags.
		getCurrentPlayer().setActive(false);
		currentplayer = (currentplayer + 1) % 2;
		getCurrentPlayer().setActive(true);
	}

	/**
	 * @Return: 0 - success, -1 - wrong player, -2 origin empty,
	 *			-3 on destination is unit of same player, -4 origin out of range,
	 *			-5 dest out of ranage, -6 not enough movement,
	 *			-7 game not running, -8 unit on origin died, -9 enemy unit
	 *			was not defeated, -10 enemy out of range, -11 defender died
	 */
	int Engine::moveUnitIngame(Coordinates origin, Coordinates destination)
	{
		// Game is not running
		if(status != EES_RUNNING)
			return -7;

		Square* orsquare = board->getSquare(origin);
		// index out of range
		if(orsquare == 0)
			return -4;
		// no unit on this square
		if(orsquare->getUnit() == 0)
			return -2;

		Square* destsquare = board->getSquare(destination);
		// index out of range
		if(destsquare == 0)
			return -5;

		Unit* srcunit = orsquare->getUnit();
				// Unit does not belong to current player
		if(srcunit->getPlayer() != &getCurrentPlayer())
			return -1;

		int distance = orsquare->getDistance(destsquare);
		if(distance > 1)
		{
			Path* path = pathfinder->findPath(orsquare->getCoordinates(), destsquare->getCoordinates());
			if(path == 0)
			{
				delete path;
				return -5;
			}
			distance = path->getMovementCosts();
			delete path;
		}

		// Distance is too far
		if(distance > srcunit->getCurrentMovement())
			return -6;

		// Is there a unit on the destination?
		Unit* destunit = destsquare->getUnit();
		if(destunit != 0)
		{
			// unit on destination belongs to same player
			if(destunit->getPlayer() == srcunit->getPlayer())
				return -3;
			// otherwise: battle

			// Check for range
			printf("distance: %d", distance);
			if(distance > srcunit->getRange())
				return -10;

			// get modificators
			int attackmods[] = {0, 0};
			int defensemods[] = {0, 0};
			if(orsquare->getTerrain() != NULL)
			{
				attackmods[0] = orsquare->getTerrain()->getModificators()[0];
				attackmods[1] = orsquare->getTerrain()->getModificators()[1];
			}
			if(destsquare->getTerrain() != NULL)
			{
				defensemods[0] = destsquare->getTerrain()->getModificators()[0];
				defensemods[1] = destsquare->getTerrain()->getModificators()[1];
			}

			srcunit->attack(destunit, attackmods, defensemods);
			srcunit->setCurrentMovement(0);
			// Attacker died
			if(srcunit->getHP() == 0)
			{
				orsquare->setUnit(0);
				return -8;
			}
			// No one died
			else if(destunit->getHP() > 0)
			{
				return -9;
			}
			// Defender died
			else
			{
				orsquare->setUnit(0);
				destsquare->setUnit(srcunit);
				return -11;
			}
		}

		srcunit->setCurrentMovement(srcunit->getCurrentMovement() - distance);
		orsquare->setUnit(0);
		destsquare->setUnit(srcunit);
		return 0;
	}

	int Engine::moveUnitDeployment(Coordinates origin, Coordinates destination)
	{
		Square* orsquare = board->getSquare(origin);
		if(orsquare->getUnit() == NULL)
			return -1;

		Square* destsquare = board->getSquare(destination);

		if(destsquare->getUnit() != NULL)
			return -1;

		destsquare->setUnit(orsquare->getUnit());
		orsquare->setUnit(NULL);
		return 0;
	}

	bool Engine::placeUnit(Coordinates position, int playerid, UNITTYPES unittype)
	{
		if(status != EES_PREPARE)
			return false;
		Square* square = board->getSquare(position);

		if(square == 0)
			return false;

		if(square->getUnit() != 0)
			return false;

		Player* player = getPlayer(playerid);
		Unit* unit = *(player->getArmy().getUndeployedUnitsByType(unittype).begin());
		if(unit)
		{
			player->getArmy().markUnitAsDeployed(unit);
			square->setUnit(unit);
			return true;
		}
		return false;
	}

	bool Engine::placeTerrain(Coordinates position, TERRAINTYPES terraintype)
	{
		if(status != EES_PREPARE)
			return false;
		Square* square = board->getSquare(position);
		if(square == NULL)
			return false;

		if(square->getTerrain() != NULL)
			delete square->getTerrain();
		Terrain* terrain;
		switch(terraintype)
		{
			case ET_WOOD:	terrain = new Terrain(ET_WOOD, -1, 1);
							break;
			case ET_HILL:	terrain = new Terrain(ET_HILL, 1, -1);
							break;
			default:		terrain = new Terrain(ET_WALL, 1, 1);
							break;
		}
		square->setTerrain(terrain);
		return true;
	}

	bool Engine::removeTerrain(Coordinates position)
	{
		if(status != EES_PREPARE)
			return false;

		Square* square = board->getSquare(position);
		if(square == NULL)
			return false;

		if(square->getTerrain())
			delete square->getTerrain();
		square->setTerrain(NULL);
	}

	Player* Engine::getPlayer(int id)
	{
		if(id == 0 || id == 1)
			return &players[id];
		return 0;
	}

	Path* Engine::findPath(const Coordinates& start, const Coordinates& end)
	{
		return pathfinder->findPath(start, end);
	}
}
<commit_msg>Engine now sets Square to Units.<commit_after>#include <stdio.h>
#include <climits>

#include "engine/engine.hpp"

#include "engine/pathfinding/astar.hpp"
#include "engine/pathfinding/path.hpp"

namespace qrw
{
	Engine::Engine()
	:	board(0),
		status(EES_UNDEFINED)
	{
		players[0].setName("Player The First");
		players[0].setId(0);
		players[1].setName("Player The Second");
		players[1].setId(1);

		pathfinder = new AStar();
	}

	Engine::~Engine()
	{
		delete pathfinder;
	}

	void Engine::init(int boardwidth, int boardheight)
	{
		delete board;
		board = new Board(boardwidth, boardheight);
		pathfinder->setBoard(board);
		currentplayer = 0;
		getCurrentPlayer().setActive(true);
		status = EES_PREPARE;

		int maxarmysize = INT_MAX;
		// int maxarmysize = getMaxPlayerUnits();
		players[0].getArmy().deleteAllUnits();
		players[0].getArmy().setMaxSize(maxarmysize);
		players[1].getArmy().deleteAllUnits();
		players[1].getArmy().setMaxSize(maxarmysize);
	}

	void Engine::startGame()
	{
		currentplayer = 0;
		status = EES_RUNNING;
	}

	ENGINSTATES Engine::getStatus()
	{
		return status;
	}

	int Engine::getMaxPlayerUnits()
	{
		if(board)
			return (board->getHeight() * board->getWidth()) / 3;
		return 0;
	}

	void Engine::createPlayerUnits(int playerid, std::map<UNITTYPES, int> unitcounts)
	{
		Player* player = getPlayer(playerid);
		UNITTYPES unittype;
		Unit* unit;

		for(auto iter = unitcounts.begin(); iter != unitcounts.end(); ++iter)
		{
			unittype = iter->first;
			for(int i = 0; i < iter->second; ++i)
			{
				// Create new unit
				switch(unittype)
				{
					case EUT_SWORDMAN:
						unit = new Unit(EUT_SWORDMAN, 5, 2, 1, 1, 3, player, board);
						break;

					case EUT_ARCHER:
						unit = new Unit(EUT_ARCHER, 5, 2, 1, 3, 2, player, board);
						break;

					default:
						unit = new Unit(EUT_SPEARMAN, 5, 2, 1, 2, 2, player, board);
						break;
				}
				// Add new unit to army
				player->getArmy().addUnit(unit);
			}
		}
	}

	// bool Engine::setUnits(int playeroneunits[EUT_NUMBEROFUNITTYPES],
		// int playertwounits[EUT_NUMBEROFUNITTYPES])
	// {
	//	players[0].clearUnits();
	//	players[1].clearUnits();

	//	if(status != EES_PREPARE)
	//		return false;
	//	setPlayerUnits(0, playeroneunits);
	//	setPlayerUnits(1, playertwounits);
	//	return true;
	// }

	// void Engine::setPlayerUnits(int id, int unitnumbers[EUT_NUMBEROFUNITTYPES])
	// {
	//	Player* player = getPlayer(id);
	//	int i;
	//	// Attention! player is "overwritten" in the method Player::addUnit(...).
	//	for(i = 0; i < unitnumbers[EUT_SWORDMAN]; ++i)
	//		player->addUnit(new Unit(EUT_SWORDMAN, 2, 1, 1, 3, player));
	//	for(i = 0; i < unitnumbers[EUT_ARCHER]; ++i)
	//		player->addUnit(new Unit(EUT_ARCHER, 2, 1, 3, 2, player));
	//	for(i = 0; i < unitnumbers[EUT_SPEARMAN]; ++i)
	//		player->addUnit(new Unit(EUT_SPEARMAN, 2, 1, 2, 2, player));
	// }

	Board* Engine::getBoard()
	{
		return board;
	}

	Player& Engine::getCurrentPlayer()
	{
		return players[currentplayer];
	}

	void Engine::endTurn()
	{
		// Reset movement of current players units.
		Army& army = getCurrentPlayer().getArmy();

		for(int i = 0; i < EUT_NUMBEROFUNITTYPES; ++i)
		{
			std::set<Unit*>& unitset = army.getUnitsByType((UNITTYPES)i);

			for(auto iter = unitset.begin(); iter != unitset.end(); ++iter)
				(*iter)->setCurrentMovement((*iter)->getMovement());
		}

		// change player and update active flags.
		getCurrentPlayer().setActive(false);
		currentplayer = (currentplayer + 1) % 2;
		getCurrentPlayer().setActive(true);
	}

	/**
	 * @Return: 0 - success, -1 - wrong player, -2 origin empty,
	 *			-3 on destination is unit of same player, -4 origin out of range,
	 *			-5 dest out of ranage, -6 not enough movement,
	 *			-7 game not running, -8 unit on origin died, -9 enemy unit
	 *			was not defeated, -10 enemy out of range, -11 defender died
	 */
	int Engine::moveUnitIngame(Coordinates origin, Coordinates destination)
	{
		// Game is not running
		if(status != EES_RUNNING)
			return -7;

		Square* orsquare = board->getSquare(origin);
		// index out of range
		if(orsquare == 0)
			return -4;
		// no unit on this square
		if(orsquare->getUnit() == 0)
			return -2;

		Square* destsquare = board->getSquare(destination);
		// index out of range
		if(destsquare == 0)
			return -5;

		Unit* srcunit = orsquare->getUnit();
				// Unit does not belong to current player
		if(srcunit->getPlayer() != &getCurrentPlayer())
			return -1;

		int distance = orsquare->getDistance(destsquare);
		if(distance > 1)
		{
			Path* path = pathfinder->findPath(orsquare->getCoordinates(), destsquare->getCoordinates());
			if(path == 0)
			{
				delete path;
				return -5;
			}
			distance = path->getMovementCosts();
			delete path;
		}

		// Distance is too far
		if(distance > srcunit->getCurrentMovement())
			return -6;

		// Is there a unit on the destination?
		Unit* destunit = destsquare->getUnit();
		if(destunit != 0)
		{
			// unit on destination belongs to same player
			if(destunit->getPlayer() == srcunit->getPlayer())
				return -3;
			// otherwise: battle

			// Check for range
			printf("distance: %d", distance);
			if(distance > srcunit->getRange())
				return -10;

			// get modificators
			int attackmods[] = {0, 0};
			int defensemods[] = {0, 0};
			if(orsquare->getTerrain() != NULL)
			{
				attackmods[0] = orsquare->getTerrain()->getModificators()[0];
				attackmods[1] = orsquare->getTerrain()->getModificators()[1];
			}
			if(destsquare->getTerrain() != NULL)
			{
				defensemods[0] = destsquare->getTerrain()->getModificators()[0];
				defensemods[1] = destsquare->getTerrain()->getModificators()[1];
			}

			srcunit->attack(destunit, attackmods, defensemods);
			srcunit->setCurrentMovement(0);
			// Attacker died
			if(srcunit->getHP() == 0)
			{
				orsquare->setUnit(0);
				return -8;
			}
			// No one died
			else if(destunit->getHP() > 0)
			{
				return -9;
			}
			// Defender died
			else
			{
				orsquare->setUnit(0);
				destsquare->setUnit(srcunit);
				return -11;
			}
		}

		srcunit->setCurrentMovement(srcunit->getCurrentMovement() - distance);
		orsquare->setUnit(0);
		destsquare->setUnit(srcunit);
		return 0;
	}

	int Engine::moveUnitDeployment(Coordinates origin, Coordinates destination)
	{
		Square* orsquare = board->getSquare(origin);
		if(orsquare->getUnit() == NULL)
			return -1;

		Square* destsquare = board->getSquare(destination);

		if(destsquare->getUnit() != NULL)
			return -1;

		destsquare->setUnit(orsquare->getUnit());
		orsquare->setUnit(NULL);
		return 0;
	}

	bool Engine::placeUnit(Coordinates position, int playerid, UNITTYPES unittype)
	{
		if(status != EES_PREPARE)
			return false;
		Square* square = board->getSquare(position);

		if(square == 0)
			return false;

		if(square->getUnit() != 0)
			return false;

		Player* player = getPlayer(playerid);
		Unit* unit = *(player->getArmy().getUndeployedUnitsByType(unittype).begin());
		if(unit)
		{
			player->getArmy().markUnitAsDeployed(unit);
			square->setUnit(unit);
			unit->setSquare(square);
			return true;
		}
		return false;
	}

	bool Engine::placeTerrain(Coordinates position, TERRAINTYPES terraintype)
	{
		if(status != EES_PREPARE)
			return false;
		Square* square = board->getSquare(position);
		if(square == NULL)
			return false;

		if(square->getTerrain() != NULL)
			delete square->getTerrain();
		Terrain* terrain;
		switch(terraintype)
		{
			case ET_WOOD:	terrain = new Terrain(ET_WOOD, -1, 1);
							break;
			case ET_HILL:	terrain = new Terrain(ET_HILL, 1, -1);
							break;
			default:		terrain = new Terrain(ET_WALL, 1, 1);
							break;
		}
		square->setTerrain(terrain);
		return true;
	}

	bool Engine::removeTerrain(Coordinates position)
	{
		if(status != EES_PREPARE)
			return false;

		Square* square = board->getSquare(position);
		if(square == NULL)
			return false;

		if(square->getTerrain())
			delete square->getTerrain();
		square->setTerrain(NULL);
	}

	Player* Engine::getPlayer(int id)
	{
		if(id == 0 || id == 1)
			return &players[id];
		return 0;
	}

	Path* Engine::findPath(const Coordinates& start, const Coordinates& end)
	{
		return pathfinder->findPath(start, end);
	}
}
<|endoftext|>


<commit_before><commit_msg>removed wrong assert<commit_after><|endoftext|>


<commit_before>#include "libmesh/vectormap.h"
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>

#define VECTORMAPOBJECTTEST \
  CPPUNIT_TEST( testCreate );			\

using namespace libMesh;

class VectormapTest : public CppUnit::TestCase
{
public:
  CPPUNIT_TEST_SUITE ( VectormapTest );

  CPPUNIT_TEST( testCreate );
  CPPUNIT_TEST( testInsert );

  CPPUNIT_TEST_SUITE_END();

private:

  template <typename Key, typename Val>
  void create()
  {
    vectormap<Key,Val> vm;
  }

  template <typename Key, typename Val>
  void insert()
  {
    vectormap<Key,Val> vm;

    Val val(0); // requires default constructor for val type.

    for (Key key=1; key<32; key*=2)
      vm.insert (std::make_pair(key,val));
  }

public:

  // virtual void setUp()
  // {}

  // virtual void tearDown()
  // {}

  void testCreate()
  {
    create<int, int> ();
    create<int*,int> ();
    create<int*,int*>();
    create<int, std::vector<int> >();
  }

  void testInsert()
  {
    insert<int, int> ();
    insert<char,int> ();
    insert<long,int*>();
    insert<int, std::vector<int> >();
  }
};

CPPUNIT_TEST_SUITE_REGISTRATION ( VectormapTest );
<commit_msg>test iterating<commit_after>#include "libmesh/vectormap.h"
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>

#define VECTORMAPOBJECTTEST \
  CPPUNIT_TEST( testCreate );			\

using namespace libMesh;

class VectormapTest : public CppUnit::TestCase
{
public:
  CPPUNIT_TEST_SUITE ( VectormapTest );

  CPPUNIT_TEST( testCreate );
  CPPUNIT_TEST( testInsert );
  CPPUNIT_TEST( testIterate );

  CPPUNIT_TEST_SUITE_END();

private:

  template <typename Key, typename Val>
  void create()
  {
    vectormap<Key,Val> vm;
  }

  template <typename Key, typename Val>
  void insert()
  {
    vectormap<Key,Val> vm;

    Val val(0); // requires default constructor for val type.

    for (Key key=1; key<32; key*=2)
      vm.insert (std::make_pair(key,val));

    vm.sort();
  }

  template <typename Key, typename Val>
  void iterate(const Val &default_value=0)
  {
    vectormap<Key,Val> vm;

    Val val(default_value); // requires default constructor for val type.

    for (Key key=1; key<32; key*=2)
      vm.insert (std::make_pair(key,val));

    vm.sort();

    for (typename vectormap<Key,Val>::const_iterator it=vm.begin();
	 it != vm.end(); ++it)
      {
	const Key &ikey = it->first;
	const Val &ival = it->second;

	CPPUNIT_ASSERT       ( vm.count(ikey) == 1 );
	CPPUNIT_ASSERT_EQUAL (vm[ikey], ival);
	CPPUNIT_ASSERT_EQUAL (ival, val);
      }
  }

public:

  // virtual void setUp()
  // {}

  // virtual void tearDown()
  // {}

  void testCreate()
  {
    create<int, int> ();
    create<int*,int> ();
    create<int*,int*>();
    create<int, std::vector<int> >();
  }

  void testInsert()
  {
    insert<int, int> ();
    insert<char,int> ();
    insert<long,int*>();
    insert<int, std::vector<int> >();
  }

  void testIterate()
  {
    iterate<int, int> ();
    iterate<char,int> ();
    iterate<long,int*>();
    iterate<int, std::string>("test_string");
  }
};

CPPUNIT_TEST_SUITE_REGISTRATION ( VectormapTest );
<|endoftext|>


<commit_before>//---------------------------------------------------------- -*- Mode: C++ -*-
// $Id$
//
// Created 2006/11/01
// Author: Blake Lewis (Kosmix Corp.)
//
// Copyright 2006 Kosmix Corp.
//
// This file is part of Kosmos File System (KFS).
//
// Licensed under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
//----------------------------------------------------------------------------

#include "libkfsClient/KfsClient.h"

extern "C" {
#define FUSE_USE_VERSION	25
#define _FILE_OFFSET_BITS	64
#include <fuse.h>
#include <sys/stat.h>
#include <string.h>
}

using std::vector;
using namespace KFS;

static char *FUSE_KFS_PROPERTIES = "./kfs.prp";
static KFS::KfsClientPtr client;

void *
fuse_init()
{
	client = getKfsClientFactory()->GetClient(FUSE_KFS_PROPERTIES);
	return client->IsInitialized() ? client.get() : NULL;
}

void
fuse_destroy(void *cookie)
{
	client.reset();
}

static int
fuse_getattr(const char *path, struct stat *s)
{
	return client->Stat(path, *s);
}

static int
fuse_mkdir(const char *path, mode_t mode)
{
	return client->Mkdir(path);
}

static int
fuse_unlink(const char *path)
{
	return client->Remove(path);
}

static int
fuse_rmdir(const char *path)
{
	return client->Rmdir(path);
}

static int
fuse_rename(const char *src, const char *dst)
{
	return client->Rename(src, dst, false);
}

static int
fuse_truncate(const char *path, off_t size)
{
	int fd = client->Open(path, O_WRONLY);
	if (fd < 0)
		return fd;
	int status = client->Truncate(fd, size);
	client->Close(fd);
	return status;
}

static int
fuse_open(const char *path, struct fuse_file_info *finfo)
{
	int res = client->Open(path, finfo->flags);
	if (res >= 0)
		return 0;
	return res;
}

static int
fuse_create(const char *path, mode_t mode, struct fuse_file_info *finfo)
{
	int res = client->Create(path);
	if (res >= 0)
		return 0;
	return res;
}

static int
fuse_read(const char *path, char *buf, size_t nread, off_t off,
		struct fuse_file_info *finfo)
{
	int fd = client->Open(path, O_RDONLY);
	if (fd < 0)
		return fd;
	int status = client->Seek(fd, off, SEEK_SET);
	if (status == 0)
		status = client->Read(fd, buf, nread);
	client->Close(fd);
	return status;
}

static int
fuse_write(const char *path, const char *buf, size_t nwrite, off_t off,
		struct fuse_file_info *finfo)
{
	int fd = client->Open(path, O_WRONLY);
	if (fd < 0)
		return fd;
	int status = client->Seek(fd, off, SEEK_SET);
	if (status == 0)
		status = client->Write(fd, buf, nwrite);
	client->Close(fd);
	return status;
}

static int
fuse_flush(const char *path, struct fuse_file_info *finfo)
{
	int fd = client->Fileno(path);
	if (fd < 0)
		return fd;
	return client->Sync(fd);
}

static int
fuse_fsync(const char *path, int flags, struct fuse_file_info *finfo)
{
	int fd = client->Open(path, O_RDONLY);
	if (fd < 0)
		return fd;
	return client->Sync(fd);
}

static int
fuse_readdir(const char *path, void *buf,
		fuse_fill_dir_t filler, off_t offset,
		struct fuse_file_info *finfo)
{
	vector <KfsFileAttr> contents;
	int status = client->ReaddirPlus(path, contents);
	if (status < 0)
		return status;
	int n = contents.size();
	for (int i = 0; i != n; i++) {
		struct stat s;
		memset(&s, 0, sizeof s);
		s.st_ino = contents[i].fileId;
		s.st_mode = contents[i].isDirectory ? S_IFDIR : S_IFREG;
		if (filler(buf, contents[i].filename.c_str(), &s, 0) != 0)
			break;
	}
	return 0;
}

struct fuse_operations ops = {
	fuse_getattr,
	NULL,			/* readlink */
	NULL,			/* getdir */
	NULL,			/* mknod */
	fuse_mkdir,
	fuse_unlink,
	fuse_rmdir,
	NULL,			/* symlink */
	fuse_rename,
	NULL,			/* link */
	NULL,			/* chmod */
	NULL,			/* chown */
	fuse_truncate,
	NULL,			/* utime */
	fuse_open,
	fuse_read,
	fuse_write,
	NULL,			/* statfs */
	fuse_flush,		/* flush */
	NULL,			/* release */
	fuse_fsync,		/* fsync */
	NULL,			/* setxattr */
	NULL,			/* getxattr */
	NULL,			/* listxattr */
	NULL,			/* removexattr */
	NULL,			/* opendir */
	fuse_readdir,
	NULL,			/* releasedir */
	NULL,			/* fsyncdir */
	fuse_init,
	fuse_destroy,
	NULL,			/* access */
	fuse_create,		/* create */
	NULL,			/* ftruncate */
	NULL			/* fgetattr */
};

int
main(int argc, char **argv)
{
	return fuse_main(argc, argv, &ops);
}
<commit_msg> -- Updating fuse based on a patch that was submitted by Tong-Hong Kuo.<commit_after>//---------------------------------------------------------- -*- Mode: C++ -*-
// $Id$
//
// Created 2006/11/01
// Author: Blake Lewis (Kosmix Corp.)
//
// Copyright 2006 Kosmix Corp.
//
// This file is part of Kosmos File System (KFS).
//
// Licensed under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
//----------------------------------------------------------------------------

#include "libkfsClient/KfsClient.h"

extern "C" {
#define FUSE_USE_VERSION	25
#define _FILE_OFFSET_BITS	64
#include <fuse.h>
#include <sys/stat.h>
#include <string.h>
}

using std::vector;
using namespace KFS;

static char *FUSE_KFS_PROPERTIES = "./kfs.prp";
static KFS::KfsClientPtr client;

void *
fuse_init()
{
	client = getKfsClientFactory()->GetClient(FUSE_KFS_PROPERTIES);
	return client->IsInitialized() ? client.get() : NULL;
}

void
fuse_destroy(void *cookie)
{
	client.reset();
}

static int
fuse_getattr(const char *path, struct stat *s)
{
	return client->Stat(path, *s);
}

static int
fuse_mkdir(const char *path, mode_t mode)
{
	return client->Mkdir(path);
}

static int
fuse_unlink(const char *path)
{
	return client->Remove(path);
}

static int
fuse_rmdir(const char *path)
{
	return client->Rmdir(path);
}

static int
fuse_rename(const char *src, const char *dst)
{
	return client->Rename(src, dst, false);
}

static int
fuse_truncate(const char *path, off_t size)
{
	int fd = client->Open(path, O_WRONLY);
	if (fd < 0)
		return fd;
	int status = client->Truncate(fd, size);
	client->Close(fd);
	return status;
}

static int
fuse_open(const char *path, struct fuse_file_info *finfo)
{
	int res = client->Open(path, finfo->flags);
	if (res < 0)
		return res;
	finfo->fh = res;
	return 0;
}

static int
fuse_release(const char *path, struct fuse_file_info *finfo)
{
	int res = finfo->fh;
	client->Close(res);
	finfo->fh = -1;
	return 0;
}

static int
fuse_create(const char *path, mode_t mode, struct fuse_file_info *finfo)
{
	int res = client->Open(path, finfo->flags);
	if (res < 0)
		return res;
	finfo->fh = res;
	return 0;
}

static int
fuse_read(const char *path, char *buf, size_t nread, off_t off,
		struct fuse_file_info *finfo)
{
	int fd = finfo->fh;
	if (fd < 0)
		return fd;
	client->Seek(fd, off);
	int status = client->Read(fd, buf, nread);
	return status;
}

static int
fuse_write(const char *path, const char *buf, size_t nwrite, off_t off,
		struct fuse_file_info *finfo)
{
	int fd = finfo->fh;
	if (fd < 0)
		return fd;
	client->Seek(fd, off);
	int status = client->Write(fd, buf, nwrite);
	return status;
}

static int
fuse_flush(const char *path, struct fuse_file_info *finfo)
{
	int fd = finfo->fh;
	//int fd = client->Fileno(path);
	if (fd < 0)
		return fd;
	return client->Sync(fd);
}

static int
fuse_fsync(const char *path, int flags, struct fuse_file_info *finfo)
{
	int fd = finfo->fh;
	//int fd = client->Fileno(path);
	if (fd < 0)
		return fd;
	return client->Sync(fd);
}

static int
fuse_readdir(const char *path, void *buf,
		fuse_fill_dir_t filler, off_t offset,
		struct fuse_file_info *finfo)
{
	vector <KfsFileAttr> contents;
	int status = client->ReaddirPlus(path, contents);
	if (status < 0)
		return status;
	int n = contents.size();
	for (int i = 0; i != n; i++) {
		struct stat s;
		memset(&s, 0, sizeof s);
		s.st_ino = contents[i].fileId;
		s.st_mode = contents[i].isDirectory ? S_IFDIR : S_IFREG;
		if (filler(buf, contents[i].filename.c_str(), &s, 0) != 0)
			break;
	}
	return 0;
}

struct fuse_operations ops = {
	fuse_getattr,
	NULL,			/* readlink */
	NULL,			/* getdir */
	NULL,			/* mknod */
	fuse_mkdir,
	fuse_unlink,
	fuse_rmdir,
	NULL,			/* symlink */
	fuse_rename,
	NULL,			/* link */
	NULL,			/* chmod */
	NULL,			/* chown */
	fuse_truncate,
	NULL,			/* utime */
	fuse_open,
	fuse_read,
	fuse_write,
	NULL,			/* statfs */
	fuse_flush,		/* flush */
	fuse_release,		/* release */
	fuse_fsync,		/* fsync */
	NULL,			/* setxattr */
	NULL,			/* getxattr */
	NULL,			/* listxattr */
	NULL,			/* removexattr */
	NULL,			/* opendir */
	fuse_readdir,
	NULL,			/* releasedir */
	NULL,			/* fsyncdir */
	fuse_init,
	fuse_destroy,
	NULL,			/* access */
	fuse_create,		/* create */
	NULL,			/* ftruncate */
	NULL			/* fgetattr */
};

int
main(int argc, char **argv)
{
	return fuse_main(argc, argv, &ops);
}
<|endoftext|>


<commit_before>/*
 Copyright (c) 2010, The Barbarian Group
 All rights reserved.

 Redistribution and use in source and binary forms, with or without modification, are permitted provided that
 the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this list of conditions and
	the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
	the following disclaimer in the documentation and/or other materials provided with the distribution.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
*/

#include "cinder/app/App.h"
#include "cinder/params/Params.h"

#include "AntTweakBar.h"

#include <boost/assign/list_of.hpp>

using namespace std;

namespace cinder { namespace params {

namespace {

#define SYNONYM(ck,ak) ((int)cinder::app::KeyEvent::KEY_ ## ck, TW_KEY_ ## ak)
#define HOMONYM(k) SYNONYM(k,k)
    std::map<int,TwKeySpecial> specialKeys = boost::assign::map_list_of
        HOMONYM(RIGHT)
        HOMONYM(LEFT)
        HOMONYM(BACKSPACE)
        HOMONYM(DELETE)
        HOMONYM(TAB)
        HOMONYM(F1)
        HOMONYM(F2)
        HOMONYM(F3)
        HOMONYM(F4)
        HOMONYM(F5)
        HOMONYM(F6)
        HOMONYM(F7)
        HOMONYM(F8)
        HOMONYM(F9)
        HOMONYM(F10)
        HOMONYM(F11)
        HOMONYM(F12)
        HOMONYM(F13)
        HOMONYM(F14)
        HOMONYM(F15)
        HOMONYM(HOME)
        HOMONYM(END)
        SYNONYM(PAGEUP,PAGE_UP)
        SYNONYM(PAGEDOWN,PAGE_DOWN)
        ;
#undef SYNONYM
#undef HOMONYM

bool mouseDown( app::MouseEvent event )
{
	TwMouseButtonID button;
	if( event.isLeft() )
		button = TW_MOUSE_LEFT;
	else if( event.isRight() )
		button = TW_MOUSE_RIGHT;
	else
		button = TW_MOUSE_MIDDLE;
	return TwMouseButton( TW_MOUSE_PRESSED, button ) != 0;
}

bool mouseUp( app::MouseEvent event )
{
	TwMouseButtonID button;
	if( event.isLeft() )
		button = TW_MOUSE_LEFT;
	else if( event.isRight() )
		button = TW_MOUSE_RIGHT;
	else
		button = TW_MOUSE_MIDDLE;
	return TwMouseButton( TW_MOUSE_RELEASED, button ) != 0;
}

bool mouseWheel( app::MouseEvent event )
{
	static float sWheelPos = 0;
	sWheelPos += event.getWheelIncrement();
	return TwMouseWheel( (int)(sWheelPos) ) != 0;
}

bool mouseMove( app::MouseEvent event )
{
	return TwMouseMotion( event.getX(), event.getY() ) != 0;
}

bool keyDown( app::KeyEvent event )
{
	int kmod = 0;
	if( event.isShiftDown() )
		kmod |= TW_KMOD_SHIFT;
	if( event.isControlDown() )
		kmod |= TW_KMOD_CTRL;
	if( event.isAltDown() )
		kmod |= TW_KMOD_ALT;
	return TwKeyPressed(
            (specialKeys.count( event.getCode() ) > 0)
                ? specialKeys[event.getCode()]
                : event.getChar(),
            kmod ) != 0;
}

bool resize( app::ResizeEvent event )
{
	TwWindowSize( event.getWidth(), event.getHeight() );
	return false;
}

void TW_CALL implStdStringToClient( std::string& destinationClientString, const std::string& sourceLibraryString )
{
  // copy strings from the library to the client app
  destinationClientString = sourceLibraryString;
}

class AntMgr {
  public:
	AntMgr() {
		if( ! TwInit( TW_OPENGL, NULL ) ) {
			throw Exception();
		}

		app::App::get()->registerMouseDown( mouseDown );
		app::App::get()->registerMouseUp( mouseUp );
		app::App::get()->registerMouseWheel( mouseWheel );
		app::App::get()->registerMouseMove( mouseMove );
		app::App::get()->registerMouseDrag( mouseMove );
		app::App::get()->registerKeyDown( keyDown );
		app::App::get()->registerResize( resize );
	}

	~AntMgr() {
		TwTerminate();
	}
};

} // anonymous namespace

void initAntGl()
{
	static std::shared_ptr<AntMgr> mgr;
	if( ! mgr )
		mgr = std::shared_ptr<AntMgr>( new AntMgr );
}

InterfaceGl::InterfaceGl( const std::string &title, const Vec2i &size, const ColorA color )
{
	initAntGl();
	mBar = std::shared_ptr<TwBar>( TwNewBar( title.c_str() ), TwDeleteBar );
	char optionsStr[1024];
	sprintf( optionsStr, "`%s` size='%d %d' color='%d %d %d' alpha=%d", title.c_str(), size.x, size.y, (int)(color.r * 255), (int)(color.g * 255), (int)(color.b * 255), (int)(color.a * 255) );
	TwDefine( optionsStr );

	TwCopyStdStringToClientFunc( implStdStringToClient );
}

void InterfaceGl::draw()
{
	TwDraw();
}

void InterfaceGl::show( bool visible )
{
	int32_t visibleInt = ( visible ) ? 1 : 0;
	TwSetParam( mBar.get(), NULL, "visible", TW_PARAM_INT32, 1, &visibleInt );
}

void InterfaceGl::hide()
{
	int32_t visibleInt = 0;
	TwSetParam( mBar.get(), NULL, "visible", TW_PARAM_INT32, 1, &visibleInt );
}

bool InterfaceGl::isVisible() const
{
	int32_t visibleInt;
	TwGetParam( mBar.get(), NULL, "visible", TW_PARAM_INT32, 1, &visibleInt );
	return visibleInt != 0;
}

void InterfaceGl::implAddParam( const std::string &name, void *param, int type, const std::string &optionsStr, bool readOnly )
{
	if( readOnly )
		TwAddVarRO( mBar.get(), name.c_str(), (TwType)type, param, optionsStr.c_str() );
	else
		TwAddVarRW( mBar.get(), name.c_str(), (TwType)type, param, optionsStr.c_str() );
}

void InterfaceGl::addParam( const std::string &name, bool *param, const std::string &optionsStr, bool readOnly )
{
	implAddParam( name, param, TW_TYPE_BOOLCPP, optionsStr, readOnly );
}

void InterfaceGl::addParam( const std::string &name, float *param, const std::string &optionsStr, bool readOnly )
{
	implAddParam( name, param, TW_TYPE_FLOAT, optionsStr, readOnly );
}

void InterfaceGl::addParam( const std::string &name, int32_t *param, const std::string &optionsStr, bool readOnly )
{
	implAddParam( name, param, TW_TYPE_INT32, optionsStr, readOnly );
}

void InterfaceGl::addParam( const std::string &name, Vec3f *param, const std::string &optionsStr, bool readOnly )
{
	implAddParam( name, param, TW_TYPE_DIR3F, optionsStr, readOnly );
}

void InterfaceGl::addParam( const std::string &name, Quatf *param, const std::string &optionsStr, bool readOnly )
{
	implAddParam( name, param, TW_TYPE_QUAT4F, optionsStr, readOnly );
}

void InterfaceGl::addParam( const std::string &name, Color *param, const std::string &optionsStr, bool readOnly )
{
	implAddParam( name, param, TW_TYPE_COLOR3F, optionsStr, readOnly );
}

void InterfaceGl::addParam( const std::string &name, ColorA *param, const std::string &optionsStr, bool readOnly )
{
	implAddParam( name, param, TW_TYPE_COLOR4F, optionsStr, readOnly );
}

void InterfaceGl::addParam( const std::string &name, std::string *param, const std::string &optionsStr, bool readOnly )
{
	implAddParam( name, param, TW_TYPE_STDSTRING, optionsStr, readOnly );
}

void InterfaceGl::addParam( const std::string &name, const std::vector<std::string> &enumNames, int *param, const std::string &optionsStr, bool readOnly )
{
	TwEnumVal *ev = new TwEnumVal[enumNames.size()];
	for( size_t v = 0; v < enumNames.size(); ++v ) {
		ev[v].Value = v;
		ev[v].Label = const_cast<char*>( enumNames[v].c_str() );
	}

	TwType evType = TwDefineEnum( (name + "EnumType").c_str(), ev, enumNames.size() );

	if( readOnly )
		TwAddVarRO( mBar.get(), name.c_str(), evType, param, optionsStr.c_str() );
	else
		TwAddVarRW( mBar.get(), name.c_str(), evType, param, optionsStr.c_str() );

	delete [] ev;
}

void InterfaceGl::addSeparator( const std::string &name, const std::string &optionsStr )
{
	TwAddSeparator( mBar.get(), name.c_str(), optionsStr.c_str() );
}

void InterfaceGl::addText( const std::string &name, const std::string &optionsStr )
{
	TwAddButton( mBar.get(), name.c_str(), NULL, NULL, optionsStr.c_str() );
}

namespace { // anonymous namespace
void TW_CALL implButtonCallback( void *clientData )
{
	std::function<void ()> *fn = reinterpret_cast<std::function<void ()>*>( clientData );
	(*fn)();
}
} // anonymous namespace

void InterfaceGl::addButton( const std::string &name, const std::function<void ()> &callback, const std::string &optionsStr )
{
	std::shared_ptr<std::function<void ()> > callbackPtr( new std::function<void ()>( callback ) );
	mButtonCallbacks.push_back( callbackPtr );
	TwAddButton( mBar.get(), name.c_str(), implButtonCallback, (void*)callbackPtr.get(), optionsStr.c_str() );
}

void InterfaceGl::setOptions( const std::string &name, const std::string &optionsStr )
{
	std::string target = "`" + (std::string)TwGetBarName( mBar.get() ) + "`";
	if( !( name.empty() ) )
		target += "/`" + name + "`";

	TwDefine( ( target + " " + optionsStr ).c_str() );
}

} } // namespace cinder::params
<commit_msg>Fixed MSW conflict due to its DELETE macro<commit_after>/*
 Copyright (c) 2010, The Barbarian Group
 All rights reserved.

 Redistribution and use in source and binary forms, with or without modification, are permitted provided that
 the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this list of conditions and
	the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
	the following disclaimer in the documentation and/or other materials provided with the distribution.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
*/

#include "cinder/app/App.h"
#include "cinder/params/Params.h"

#include "AntTweakBar.h"

#include <boost/assign/list_of.hpp>

using namespace std;

namespace cinder { namespace params {

namespace {

#undef DELETE

#define SYNONYM(ck,ak) ((int)cinder::app::KeyEvent::KEY_ ## ck, TW_KEY_ ## ak)
#define HOMONYM(k) SYNONYM(k,k)
    std::map<int,TwKeySpecial> specialKeys = boost::assign::map_list_of
        HOMONYM(RIGHT)
        HOMONYM(LEFT)
        HOMONYM(BACKSPACE)
        HOMONYM(DELETE)
        HOMONYM(TAB)
        HOMONYM(F1)
        HOMONYM(F2)
        HOMONYM(F3)
        HOMONYM(F4)
        HOMONYM(F5)
        HOMONYM(F6)
        HOMONYM(F7)
        HOMONYM(F8)
        HOMONYM(F9)
        HOMONYM(F10)
        HOMONYM(F11)
        HOMONYM(F12)
        HOMONYM(F13)
        HOMONYM(F14)
        HOMONYM(F15)
        HOMONYM(HOME)
        HOMONYM(END)
        SYNONYM(PAGEUP,PAGE_UP)
        SYNONYM(PAGEDOWN,PAGE_DOWN)
        ;
#undef SYNONYM
#undef HOMONYM

bool mouseDown( app::MouseEvent event )
{
	TwMouseButtonID button;
	if( event.isLeft() )
		button = TW_MOUSE_LEFT;
	else if( event.isRight() )
		button = TW_MOUSE_RIGHT;
	else
		button = TW_MOUSE_MIDDLE;
	return TwMouseButton( TW_MOUSE_PRESSED, button ) != 0;
}

bool mouseUp( app::MouseEvent event )
{
	TwMouseButtonID button;
	if( event.isLeft() )
		button = TW_MOUSE_LEFT;
	else if( event.isRight() )
		button = TW_MOUSE_RIGHT;
	else
		button = TW_MOUSE_MIDDLE;
	return TwMouseButton( TW_MOUSE_RELEASED, button ) != 0;
}

bool mouseWheel( app::MouseEvent event )
{
	static float sWheelPos = 0;
	sWheelPos += event.getWheelIncrement();
	return TwMouseWheel( (int)(sWheelPos) ) != 0;
}

bool mouseMove( app::MouseEvent event )
{
	return TwMouseMotion( event.getX(), event.getY() ) != 0;
}

bool keyDown( app::KeyEvent event )
{
	int kmod = 0;
	if( event.isShiftDown() )
		kmod |= TW_KMOD_SHIFT;
	if( event.isControlDown() )
		kmod |= TW_KMOD_CTRL;
	if( event.isAltDown() )
		kmod |= TW_KMOD_ALT;
	return TwKeyPressed(
            (specialKeys.count( event.getCode() ) > 0)
                ? specialKeys[event.getCode()]
                : event.getChar(),
            kmod ) != 0;
}

bool resize( app::ResizeEvent event )
{
	TwWindowSize( event.getWidth(), event.getHeight() );
	return false;
}

void TW_CALL implStdStringToClient( std::string& destinationClientString, const std::string& sourceLibraryString )
{
  // copy strings from the library to the client app
  destinationClientString = sourceLibraryString;
}

class AntMgr {
  public:
	AntMgr() {
		if( ! TwInit( TW_OPENGL, NULL ) ) {
			throw Exception();
		}

		app::App::get()->registerMouseDown( mouseDown );
		app::App::get()->registerMouseUp( mouseUp );
		app::App::get()->registerMouseWheel( mouseWheel );
		app::App::get()->registerMouseMove( mouseMove );
		app::App::get()->registerMouseDrag( mouseMove );
		app::App::get()->registerKeyDown( keyDown );
		app::App::get()->registerResize( resize );
	}

	~AntMgr() {
		TwTerminate();
	}
};

} // anonymous namespace

void initAntGl()
{
	static std::shared_ptr<AntMgr> mgr;
	if( ! mgr )
		mgr = std::shared_ptr<AntMgr>( new AntMgr );
}

InterfaceGl::InterfaceGl( const std::string &title, const Vec2i &size, const ColorA color )
{
	initAntGl();
	mBar = std::shared_ptr<TwBar>( TwNewBar( title.c_str() ), TwDeleteBar );
	char optionsStr[1024];
	sprintf( optionsStr, "`%s` size='%d %d' color='%d %d %d' alpha=%d", title.c_str(), size.x, size.y, (int)(color.r * 255), (int)(color.g * 255), (int)(color.b * 255), (int)(color.a * 255) );
	TwDefine( optionsStr );

	TwCopyStdStringToClientFunc( implStdStringToClient );
}

void InterfaceGl::draw()
{
	TwDraw();
}

void InterfaceGl::show( bool visible )
{
	int32_t visibleInt = ( visible ) ? 1 : 0;
	TwSetParam( mBar.get(), NULL, "visible", TW_PARAM_INT32, 1, &visibleInt );
}

void InterfaceGl::hide()
{
	int32_t visibleInt = 0;
	TwSetParam( mBar.get(), NULL, "visible", TW_PARAM_INT32, 1, &visibleInt );
}

bool InterfaceGl::isVisible() const
{
	int32_t visibleInt;
	TwGetParam( mBar.get(), NULL, "visible", TW_PARAM_INT32, 1, &visibleInt );
	return visibleInt != 0;
}

void InterfaceGl::implAddParam( const std::string &name, void *param, int type, const std::string &optionsStr, bool readOnly )
{
	if( readOnly )
		TwAddVarRO( mBar.get(), name.c_str(), (TwType)type, param, optionsStr.c_str() );
	else
		TwAddVarRW( mBar.get(), name.c_str(), (TwType)type, param, optionsStr.c_str() );
}

void InterfaceGl::addParam( const std::string &name, bool *param, const std::string &optionsStr, bool readOnly )
{
	implAddParam( name, param, TW_TYPE_BOOLCPP, optionsStr, readOnly );
}

void InterfaceGl::addParam( const std::string &name, float *param, const std::string &optionsStr, bool readOnly )
{
	implAddParam( name, param, TW_TYPE_FLOAT, optionsStr, readOnly );
}

void InterfaceGl::addParam( const std::string &name, int32_t *param, const std::string &optionsStr, bool readOnly )
{
	implAddParam( name, param, TW_TYPE_INT32, optionsStr, readOnly );
}

void InterfaceGl::addParam( const std::string &name, Vec3f *param, const std::string &optionsStr, bool readOnly )
{
	implAddParam( name, param, TW_TYPE_DIR3F, optionsStr, readOnly );
}

void InterfaceGl::addParam( const std::string &name, Quatf *param, const std::string &optionsStr, bool readOnly )
{
	implAddParam( name, param, TW_TYPE_QUAT4F, optionsStr, readOnly );
}

void InterfaceGl::addParam( const std::string &name, Color *param, const std::string &optionsStr, bool readOnly )
{
	implAddParam( name, param, TW_TYPE_COLOR3F, optionsStr, readOnly );
}

void InterfaceGl::addParam( const std::string &name, ColorA *param, const std::string &optionsStr, bool readOnly )
{
	implAddParam( name, param, TW_TYPE_COLOR4F, optionsStr, readOnly );
}

void InterfaceGl::addParam( const std::string &name, std::string *param, const std::string &optionsStr, bool readOnly )
{
	implAddParam( name, param, TW_TYPE_STDSTRING, optionsStr, readOnly );
}

void InterfaceGl::addParam( const std::string &name, const std::vector<std::string> &enumNames, int *param, const std::string &optionsStr, bool readOnly )
{
	TwEnumVal *ev = new TwEnumVal[enumNames.size()];
	for( size_t v = 0; v < enumNames.size(); ++v ) {
		ev[v].Value = v;
		ev[v].Label = const_cast<char*>( enumNames[v].c_str() );
	}

	TwType evType = TwDefineEnum( (name + "EnumType").c_str(), ev, enumNames.size() );

	if( readOnly )
		TwAddVarRO( mBar.get(), name.c_str(), evType, param, optionsStr.c_str() );
	else
		TwAddVarRW( mBar.get(), name.c_str(), evType, param, optionsStr.c_str() );

	delete [] ev;
}

void InterfaceGl::addSeparator( const std::string &name, const std::string &optionsStr )
{
	TwAddSeparator( mBar.get(), name.c_str(), optionsStr.c_str() );
}

void InterfaceGl::addText( const std::string &name, const std::string &optionsStr )
{
	TwAddButton( mBar.get(), name.c_str(), NULL, NULL, optionsStr.c_str() );
}

namespace { // anonymous namespace
void TW_CALL implButtonCallback( void *clientData )
{
	std::function<void ()> *fn = reinterpret_cast<std::function<void ()>*>( clientData );
	(*fn)();
}
} // anonymous namespace

void InterfaceGl::addButton( const std::string &name, const std::function<void ()> &callback, const std::string &optionsStr )
{
	std::shared_ptr<std::function<void ()> > callbackPtr( new std::function<void ()>( callback ) );
	mButtonCallbacks.push_back( callbackPtr );
	TwAddButton( mBar.get(), name.c_str(), implButtonCallback, (void*)callbackPtr.get(), optionsStr.c_str() );
}

void InterfaceGl::setOptions( const std::string &name, const std::string &optionsStr )
{
	std::string target = "`" + (std::string)TwGetBarName( mBar.get() ) + "`";
	if( !( name.empty() ) )
		target += "/`" + name + "`";

	TwDefine( ( target + " " + optionsStr ).c_str() );
}

} } // namespace cinder::params
<|endoftext|>