<commit_before>/* -*-  mode: c++; c-default-style: "google"; indent-tabs-mode: nil -*- */
/* -------------------------------------------------------------------------
   ATS

   License: see $ATS_DIR/COPYRIGHT
   Author: Markus Berndt

   Interface for the Volumetric Deformation PK.

   <ParameterList name="volumetric deformation">
   <Parameter name="PK model" type="string" value="Prescibed Mesh Deformation"/>
   <Parameter name="Deformation method" type="string" value="method name"/>
   </ParameterList>

   ------------------------------------------------------------------------- */
#include "Teuchos_XMLParameterListHelpers.hpp"

#include "composite_vector_function_factory.hh"

#include "volumetric_deformation.hh"
#include "porosity_evaluator.hh"

namespace Amanzi {
namespace Deform {

using namespace Amanzi::AmanziMesh;

RegisteredPKFactory<VolumetricDeformation> VolumetricDeformation::reg_("volumetric deformation");

VolumetricDeformation::VolumetricDeformation(Teuchos::ParameterList& plist,
        const Teuchos::RCP<TreeVector>& solution):
    PKDefaultBase(plist,solution),
    PKPhysicalBase(plist,solution) {
  poro_key_ = plist_.get<std::string>("porosity key","porosity");
  bottom_surface_name_ = plist_.get<std::string>("bottom surface region", "bottom face");
}

// -- Setup data
void VolumetricDeformation::setup(const Teuchos::Ptr<State>& S) {
  PKPhysicalBase::setup(S);
  mesh_->build_columns(bottom_surface_name_);

  // save the meshes
  surf_mesh_ = S->GetMesh("surface");
  surf3d_mesh_ = S->GetMesh("surface_3d");
  mesh_nc_ = Teuchos::rcp_const_cast<AmanziMesh::Mesh>(mesh_);
  surf_mesh_nc_ = Teuchos::rcp_const_cast<AmanziMesh::Mesh>(surf_mesh_);
  surf3d_mesh_nc_ = Teuchos::rcp_const_cast<AmanziMesh::Mesh>(surf3d_mesh_);

  // create storage for primary variable, rock volume
  Teuchos::RCP<CompositeVectorFactory> cell_def_fac = S->RequireField(key_, name_);
  cell_def_fac->SetMesh(mesh_)->SetGhosted()
    ->SetComponent("cell", AmanziMesh::CELL, 1);

  // create the function
  Teuchos::ParameterList func_plist = plist_.sublist("deformation function");
  deform_func_ = Functions::CreateCompositeVectorFunction(func_plist, *cell_def_fac);

  // Additional data:
  // create storage for cell volume change
  S->RequireField("dcell_volume_dtime", name_)->SetMesh(mesh_)->SetGhosted()
      ->SetComponent("cell", AmanziMesh::CELL, 1);

  // create storage for the nodal deformation
  S->RequireField("nodal_dz", name_)->SetMesh(mesh_)->SetGhosted()
      ->SetComponent("node", AmanziMesh::NODE, 2);

  // create storage for the vertex coordinates
  // we need to checkpoint those to be able to create
  // the deformed mesh after restart
  int dim = mesh_->space_dimension();
  S->RequireField("vertex coordinate", name_)->SetMesh(mesh_)->SetGhosted()
      ->SetComponent("node", AmanziMesh::NODE, dim);

  S->RequireFieldEvaluator("cell_volume");
  S->RequireFieldEvaluator("porosity");
  S->RequireField("porosity")->SetMesh(mesh_)->SetGhosted()
      ->AddComponent("cell",AmanziMesh::CELL,1);
}

// -- Initialize owned (dependent) variables.
void VolumetricDeformation::initialize(const Teuchos::Ptr<State>& S) {
  PKPhysicalBase::initialize(S);

  // the PK's initial condition sets the initial porosity.  From this, we
  // calculate the actual initial condition, which is the rock volume.
  Epetra_MultiVector& rock_vol = *S->GetFieldData(key_,name_)
      ->ViewComponent("cell",false);
  int ncells = rock_vol.MyLength();
  for (int c=0; c!=ncells; ++c) {
    rock_vol[0][c] = (1.0 - rock_vol[0][c]) * mesh_->cell_volume(c);
  }

  // initialize the deformation rate to 0
  S->GetFieldData("dcell_volume_dtime",name_)->PutScalar(0.);
  S->GetField("dcell_volume_dtime",name_)->set_initialized();

  // initialize the plane displacement to be zero
  S->GetFieldData("nodal_dz",name_)->PutScalar(0.);
  S->GetField("nodal_dz",name_)->set_initialized();

  // initialize the vertex coordinate to the current mesh
  int dim = mesh_->space_dimension();
  AmanziGeometry::Point coords;
  coords.init(dim);

  // number of vertices
  int nV = mesh_->num_entities(Amanzi::AmanziMesh::NODE,
          Amanzi::AmanziMesh::OWNED);

  Epetra_MultiVector& vc = *S->GetFieldData("vertex coordinate",name_)
      ->ViewComponent("node",false);

  // search the id of the mid point on the top
  for (int iV=0; iV!=nV; ++iV) {
    // get the coords of the node
    mesh_->node_get_coordinates(iV,&coords);
    for (int s=0; s!=dim; ++s) vc[s][iV] = coords[s];
  }
  S->GetField("vertex coordinate",name_)->set_initialized();

}

bool VolumetricDeformation::advance(double dt) {
  Teuchos::OSTab tab = getOSTab();
  if (out_.get() && includesVerbLevel(verbosity_, Teuchos::VERB_MEDIUM, true)) {
    *out_ << "Advancing deformation PK from time " << S_->time() << " to "
          << S_next_->time() << " with step size " << dt << std::endl;
    *out_ << "----------------------------------------------------------------" << std::endl;
  }

  double ss = S_next_->time();
  double ss0 = S_->time();
  double dT = ss - ss0;
  double T_mid = (ss + ss0) / 2.;

  // Evaluate the function at the mean time to get d(cv)/dT
  Teuchos::RCP<CompositeVector> dcell_vol_vec =
      S_next_->GetFieldData("dcell_volume_dtime", name_);
  deform_func_->Compute(T_mid, dcell_vol_vec.ptr());
  const Epetra_MultiVector& dcell_vol = *dcell_vol_vec->ViewComponent("cell",false);

  // Evaluate dz of the plane above the prism by integrating up the
  // change, and contribute these to the nodes that make up that plane
  // for averaging.
  Teuchos::RCP<CompositeVector> nodal_dz_vec = S_next_->GetFieldData("nodal_dz",name_);
  Epetra_MultiVector& nodal_dz_g = *nodal_dz_vec->ViewComponent("node",true);
  nodal_dz_g.PutScalar(0.);

  // Simultaneously evaluate contributions to the

  AmanziMesh::Entity_ID_List bottomfaces;
  mesh_->get_set_entities(bottom_surface_name_, AmanziMesh::FACE,
                          AmanziMesh::OWNED, &bottomfaces);
  int ncols = 0;
  int ncells_tot = 0;

  for (unsigned int i=0; i!=bottomfaces.size(); ++i) {
    // find the bottom cell
    AmanziMesh::Entity_ID f_below = bottomfaces[i];
    AmanziMesh::Entity_ID_List cells;
    mesh_->face_get_cells(f_below, AmanziMesh::OWNED, &cells);
    ASSERT(cells.size() == 1);
    AmanziMesh::Entity_ID c0 = cells[0];

    // for each cell in the column, integrate the change
    double face_displacement = 0.;
    bool done = false;
    int ncells_in_col = 1;

    while (!done) {
      // find the face above
      AmanziMesh::Entity_ID f_above = mesh_->cell_get_face_above(c0);

      // calculate the displacement of the face above the cell
      double dz = mesh_->face_centroid(f_above)[2] - mesh_->face_centroid(f_below)[2];
      face_displacement += dz * dcell_vol[0][c0] * dT;

      // distribute that to the nodes of the face
      AmanziMesh::Entity_ID_List nodes;
      mesh_->face_get_nodes(f_above, &nodes);
      for (AmanziMesh::Entity_ID_List::const_iterator n=nodes.begin();
           n!=nodes.end(); ++n) {
        nodal_dz_g[0][*n] += face_displacement;
        nodal_dz_g[1][*n]++;
      }

      // iterate til we reach the top of the domain
      // get the cell above
      AmanziMesh::Entity_ID c1 = mesh_->cell_get_cell_above(c0);
      if (c1 >= 0) {
        c0 = c1;
        f_below = f_above;
        ncells_in_col++;
      } else {
        done = true;
      }
    }

    ncells_tot += ncells_in_col;
    if (out_.get() && includesVerbLevel(verbosity_, Teuchos::VERB_EXTREME, true)) {
      *out_ << "  Integrated column " << ncols << " with " << ncells_in_col << " cells." << std::endl;
    }
    ncols++;
  }

  if (out_.get() && includesVerbLevel(verbosity_, Teuchos::VERB_EXTREME, true)) {
    int ncells_loc = ncells_tot;
    nodal_dz_vec->comm()->SumAll(&ncells_loc, &ncells_tot, 1);
    *out_ << "Integrated " << ncols << " columns, total # cells touched = " << ncells_tot << std::endl;
  }

  // take the average
  nodal_dz_vec->GatherGhostedToMaster("node");
  Epetra_MultiVector& nodal_dz_l = *nodal_dz_vec->ViewComponent("node",false);
  for (int i=0; i!=nodal_dz_l.MyLength(); ++i) {
    if (nodal_dz_l[1][i] > 1) {
      nodal_dz_l[0][i] /= nodal_dz_l[1][i];
    }
  }

  // form list of deformed nodes
  Entity_ID_List nodeids;
  AmanziGeometry::Point_List newpos;
  Amanzi::AmanziGeometry::Point coords, new_coords;
  int dim = mesh_->space_dimension();
  new_coords.init(dim);

  int nnodes = nodal_dz_l.MyLength();
  for (int i=0; i!=nnodes; ++i) {
    nodeids.push_back(i);
    mesh_->node_get_coordinates(i,&coords);
    new_coords = coords;
    new_coords[2] += nodal_dz_l[0][i];
    newpos.push_back(new_coords);
  }

  // deform the mesh
  AmanziGeometry::Point_List finpos;
  mesh_nc_->deform(nodeids, newpos, false, &finpos);

  // now we have to adapt the surface mesh to the new volume mesh
  // extract the correct new coordinates for the surface from the domain
  // mesh and update the surface mesh accordingly
  int nsurfnodes = surf_mesh_->num_entities(Amanzi::AmanziMesh::NODE,
          Amanzi::AmanziMesh::OWNED);
  AmanziGeometry::Point coord_domain(dim);
  AmanziGeometry::Point coord_surface(dim-1);

  Entity_ID_List surface_nodeids, surface3d_nodeids;
  AmanziGeometry::Point_List surface_newpos, surface3d_newpos;

  for (int i=0; i!=nsurfnodes; ++i) {
    // get the coords of the node
    AmanziGeometry::Point coord(3);
    AmanziMesh::Entity_ID pnode =
      surf_mesh_->entity_get_parent(AmanziMesh::NODE, i);
    mesh_->node_get_coordinates(i, &coord_domain);

    // surface points are two dimensional
    for (int s=0; s!=dim-1; ++s) coord_surface[s] = coord_domain[s];
    surface_nodeids.push_back(i);
    surface_newpos.push_back(coord_surface);

    surface3d_nodeids.push_back(i);
    surface3d_newpos.push_back(coord_domain);
  }

  // now deform the surface meshes, note that we set the keep_valid
  // flag to false, since we want the surface mesh to exactly mirror
  // the domain mesh
  AmanziGeometry::Point_List surface_finpos;
  surf_mesh_nc_->deform(surface_nodeids, surface_newpos, false, &surface_finpos);
  surf3d_mesh_nc_->deform(surface3d_nodeids, surface3d_newpos, false, &surface_finpos);

  // update vertex coordinates in state (for checkpointing)
  Epetra_MultiVector& vc = *S_next_->GetFieldData("vertex coordinate",name_)
      ->ViewComponent("node",false);
  for (int i=0; i!=nnodes; ++i) {
    mesh_->node_get_coordinates(i,&coords);
    for (int s=0; s!=dim; ++s) vc[s][i] = coords[s];
  }

  // setting deformation to be rock_volume at old time, (1-poro_old)*CV_old
  const Epetra_MultiVector& cv = *S_->GetFieldData("cell_volume")
      ->ViewComponent("cell",false);
  const Epetra_MultiVector& poro = *S_->GetFieldData(poro_key_)
      ->ViewComponent("cell",false);
  Epetra_MultiVector& def = *S_next_->GetFieldData(key_,name_)
      ->ViewComponent("cell",false);

  int ncells = def.MyLength();
  for (int c=0; c!=ncells; ++c) {
    def[0][c] = (1. - poro[0][c]) * cv[0][c];
  }
  // mark the placeholder evaluator as changed
  solution_evaluator_->SetFieldAsChanged(S_next_.ptr());

  // update porosity and cell volumes
  S_next_->GetFieldEvaluator("cell_volume")
      ->HasFieldChanged(S_next_.ptr(), name_);
  S_next_->GetFieldEvaluator("porosity")
      ->HasFieldChanged(S_next_.ptr(), name_);

  return false;
}

} // namespace
} // namespace
<commit_msg>comments volumetric_deformation to allow it to compile.  This PK no longer works, thanks to reversions to Mesh.hh's column formation pieces.  It is not expected to work until the new deformation capability is added by Rao<commit_after>/* -*-  mode: c++; c-default-style: "google"; indent-tabs-mode: nil -*- */
/* -------------------------------------------------------------------------
   ATS

   License: see $ATS_DIR/COPYRIGHT
   Author: Markus Berndt

   Interface for the Volumetric Deformation PK.

   <ParameterList name="volumetric deformation">
   <Parameter name="PK model" type="string" value="Prescibed Mesh Deformation"/>
   <Parameter name="Deformation method" type="string" value="method name"/>
   </ParameterList>

   ------------------------------------------------------------------------- */
#include "Teuchos_XMLParameterListHelpers.hpp"

#include "composite_vector_function_factory.hh"

#include "volumetric_deformation.hh"
#include "porosity_evaluator.hh"

namespace Amanzi {
namespace Deform {

using namespace Amanzi::AmanziMesh;

RegisteredPKFactory<VolumetricDeformation> VolumetricDeformation::reg_("volumetric deformation");

VolumetricDeformation::VolumetricDeformation(Teuchos::ParameterList& plist,
        const Teuchos::RCP<TreeVector>& solution):
    PKDefaultBase(plist,solution),
    PKPhysicalBase(plist,solution) {
  poro_key_ = plist_.get<std::string>("porosity key","porosity");
  bottom_surface_name_ = plist_.get<std::string>("bottom surface region", "bottom face");
}

// -- Setup data
void VolumetricDeformation::setup(const Teuchos::Ptr<State>& S) {
  PKPhysicalBase::setup(S);
  // build_columns() call removed as Mesh reverted to old build_columns()
  //  routine, which is currently buggy.  To run this PK, this will need
  //  re-fixed.
  // mesh_->build_columns(bottom_surface_name_);
  ASSERT(0);

  // save the meshes
  surf_mesh_ = S->GetMesh("surface");
  surf3d_mesh_ = S->GetMesh("surface_3d");
  mesh_nc_ = Teuchos::rcp_const_cast<AmanziMesh::Mesh>(mesh_);
  surf_mesh_nc_ = Teuchos::rcp_const_cast<AmanziMesh::Mesh>(surf_mesh_);
  surf3d_mesh_nc_ = Teuchos::rcp_const_cast<AmanziMesh::Mesh>(surf3d_mesh_);

  // create storage for primary variable, rock volume
  Teuchos::RCP<CompositeVectorFactory> cell_def_fac = S->RequireField(key_, name_);
  cell_def_fac->SetMesh(mesh_)->SetGhosted()
    ->SetComponent("cell", AmanziMesh::CELL, 1);

  // create the function
  Teuchos::ParameterList func_plist = plist_.sublist("deformation function");
  deform_func_ = Functions::CreateCompositeVectorFunction(func_plist, *cell_def_fac);

  // Additional data:
  // create storage for cell volume change
  S->RequireField("dcell_volume_dtime", name_)->SetMesh(mesh_)->SetGhosted()
      ->SetComponent("cell", AmanziMesh::CELL, 1);

  // create storage for the nodal deformation
  S->RequireField("nodal_dz", name_)->SetMesh(mesh_)->SetGhosted()
      ->SetComponent("node", AmanziMesh::NODE, 2);

  // create storage for the vertex coordinates
  // we need to checkpoint those to be able to create
  // the deformed mesh after restart
  int dim = mesh_->space_dimension();
  S->RequireField("vertex coordinate", name_)->SetMesh(mesh_)->SetGhosted()
      ->SetComponent("node", AmanziMesh::NODE, dim);

  S->RequireFieldEvaluator("cell_volume");
  S->RequireFieldEvaluator("porosity");
  S->RequireField("porosity")->SetMesh(mesh_)->SetGhosted()
      ->AddComponent("cell",AmanziMesh::CELL,1);
}

// -- Initialize owned (dependent) variables.
void VolumetricDeformation::initialize(const Teuchos::Ptr<State>& S) {
  PKPhysicalBase::initialize(S);

  // the PK's initial condition sets the initial porosity.  From this, we
  // calculate the actual initial condition, which is the rock volume.
  Epetra_MultiVector& rock_vol = *S->GetFieldData(key_,name_)
      ->ViewComponent("cell",false);
  int ncells = rock_vol.MyLength();
  for (int c=0; c!=ncells; ++c) {
    rock_vol[0][c] = (1.0 - rock_vol[0][c]) * mesh_->cell_volume(c);
  }

  // initialize the deformation rate to 0
  S->GetFieldData("dcell_volume_dtime",name_)->PutScalar(0.);
  S->GetField("dcell_volume_dtime",name_)->set_initialized();

  // initialize the plane displacement to be zero
  S->GetFieldData("nodal_dz",name_)->PutScalar(0.);
  S->GetField("nodal_dz",name_)->set_initialized();

  // initialize the vertex coordinate to the current mesh
  int dim = mesh_->space_dimension();
  AmanziGeometry::Point coords;
  coords.init(dim);

  // number of vertices
  int nV = mesh_->num_entities(Amanzi::AmanziMesh::NODE,
          Amanzi::AmanziMesh::OWNED);

  Epetra_MultiVector& vc = *S->GetFieldData("vertex coordinate",name_)
      ->ViewComponent("node",false);

  // search the id of the mid point on the top
  for (int iV=0; iV!=nV; ++iV) {
    // get the coords of the node
    mesh_->node_get_coordinates(iV,&coords);
    for (int s=0; s!=dim; ++s) vc[s][iV] = coords[s];
  }
  S->GetField("vertex coordinate",name_)->set_initialized();

}

bool VolumetricDeformation::advance(double dt) {
  Teuchos::OSTab tab = getOSTab();
  if (out_.get() && includesVerbLevel(verbosity_, Teuchos::VERB_MEDIUM, true)) {
    *out_ << "Advancing deformation PK from time " << S_->time() << " to "
          << S_next_->time() << " with step size " << dt << std::endl;
    *out_ << "----------------------------------------------------------------" << std::endl;
  }

  double ss = S_next_->time();
  double ss0 = S_->time();
  double dT = ss - ss0;
  double T_mid = (ss + ss0) / 2.;

  // Evaluate the function at the mean time to get d(cv)/dT
  Teuchos::RCP<CompositeVector> dcell_vol_vec =
      S_next_->GetFieldData("dcell_volume_dtime", name_);
  deform_func_->Compute(T_mid, dcell_vol_vec.ptr());
  const Epetra_MultiVector& dcell_vol = *dcell_vol_vec->ViewComponent("cell",false);

  // Evaluate dz of the plane above the prism by integrating up the
  // change, and contribute these to the nodes that make up that plane
  // for averaging.
  Teuchos::RCP<CompositeVector> nodal_dz_vec = S_next_->GetFieldData("nodal_dz",name_);
  Epetra_MultiVector& nodal_dz_g = *nodal_dz_vec->ViewComponent("node",true);
  nodal_dz_g.PutScalar(0.);

  // Simultaneously evaluate contributions to the

  AmanziMesh::Entity_ID_List bottomfaces;
  mesh_->get_set_entities(bottom_surface_name_, AmanziMesh::FACE,
                          AmanziMesh::OWNED, &bottomfaces);
  int ncols = 0;
  int ncells_tot = 0;

  for (unsigned int i=0; i!=bottomfaces.size(); ++i) {
    // find the bottom cell
    AmanziMesh::Entity_ID f_below = bottomfaces[i];
    AmanziMesh::Entity_ID_List cells;
    mesh_->face_get_cells(f_below, AmanziMesh::OWNED, &cells);
    ASSERT(cells.size() == 1);
    AmanziMesh::Entity_ID c0 = cells[0];

    // for each cell in the column, integrate the change
    double face_displacement = 0.;
    bool done = false;
    int ncells_in_col = 1;

    while (!done) {
      // find the face above
      // fix me when Mesh is fixed!
      ASSERT(0);
      AmanziMesh::Entity_ID f_above = 0;
      //      AmanziMesh::Entity_ID f_above = mesh_->cell_get_face_above(c0);

      // calculate the displacement of the face above the cell
      double dz = mesh_->face_centroid(f_above)[2] - mesh_->face_centroid(f_below)[2];
      face_displacement += dz * dcell_vol[0][c0] * dT;

      // distribute that to the nodes of the face
      AmanziMesh::Entity_ID_List nodes;
      mesh_->face_get_nodes(f_above, &nodes);
      for (AmanziMesh::Entity_ID_List::const_iterator n=nodes.begin();
           n!=nodes.end(); ++n) {
        nodal_dz_g[0][*n] += face_displacement;
        nodal_dz_g[1][*n]++;
      }

      // iterate til we reach the top of the domain
      // get the cell above
      AmanziMesh::Entity_ID c1 = mesh_->cell_get_cell_above(c0);
      if (c1 >= 0) {
        c0 = c1;
        f_below = f_above;
        ncells_in_col++;
      } else {
        done = true;
      }
    }

    ncells_tot += ncells_in_col;
    if (out_.get() && includesVerbLevel(verbosity_, Teuchos::VERB_EXTREME, true)) {
      *out_ << "  Integrated column " << ncols << " with " << ncells_in_col << " cells." << std::endl;
    }
    ncols++;
  }

  if (out_.get() && includesVerbLevel(verbosity_, Teuchos::VERB_EXTREME, true)) {
    int ncells_loc = ncells_tot;
    nodal_dz_vec->comm()->SumAll(&ncells_loc, &ncells_tot, 1);
    *out_ << "Integrated " << ncols << " columns, total # cells touched = " << ncells_tot << std::endl;
  }

  // take the average
  nodal_dz_vec->GatherGhostedToMaster("node");
  Epetra_MultiVector& nodal_dz_l = *nodal_dz_vec->ViewComponent("node",false);
  for (int i=0; i!=nodal_dz_l.MyLength(); ++i) {
    if (nodal_dz_l[1][i] > 1) {
      nodal_dz_l[0][i] /= nodal_dz_l[1][i];
    }
  }

  // form list of deformed nodes
  Entity_ID_List nodeids;
  AmanziGeometry::Point_List newpos;
  Amanzi::AmanziGeometry::Point coords, new_coords;
  int dim = mesh_->space_dimension();
  new_coords.init(dim);

  int nnodes = nodal_dz_l.MyLength();
  for (int i=0; i!=nnodes; ++i) {
    nodeids.push_back(i);
    mesh_->node_get_coordinates(i,&coords);
    new_coords = coords;
    new_coords[2] += nodal_dz_l[0][i];
    newpos.push_back(new_coords);
  }

  // deform the mesh
  AmanziGeometry::Point_List finpos;
  mesh_nc_->deform(nodeids, newpos, false, &finpos);

  // now we have to adapt the surface mesh to the new volume mesh
  // extract the correct new coordinates for the surface from the domain
  // mesh and update the surface mesh accordingly
  int nsurfnodes = surf_mesh_->num_entities(Amanzi::AmanziMesh::NODE,
          Amanzi::AmanziMesh::OWNED);
  AmanziGeometry::Point coord_domain(dim);
  AmanziGeometry::Point coord_surface(dim-1);

  Entity_ID_List surface_nodeids, surface3d_nodeids;
  AmanziGeometry::Point_List surface_newpos, surface3d_newpos;

  for (int i=0; i!=nsurfnodes; ++i) {
    // get the coords of the node
    AmanziGeometry::Point coord(3);
    AmanziMesh::Entity_ID pnode =
      surf_mesh_->entity_get_parent(AmanziMesh::NODE, i);
    mesh_->node_get_coordinates(i, &coord_domain);

    // surface points are two dimensional
    for (int s=0; s!=dim-1; ++s) coord_surface[s] = coord_domain[s];
    surface_nodeids.push_back(i);
    surface_newpos.push_back(coord_surface);

    surface3d_nodeids.push_back(i);
    surface3d_newpos.push_back(coord_domain);
  }

  // now deform the surface meshes, note that we set the keep_valid
  // flag to false, since we want the surface mesh to exactly mirror
  // the domain mesh
  AmanziGeometry::Point_List surface_finpos;
  surf_mesh_nc_->deform(surface_nodeids, surface_newpos, false, &surface_finpos);
  surf3d_mesh_nc_->deform(surface3d_nodeids, surface3d_newpos, false, &surface_finpos);

  // update vertex coordinates in state (for checkpointing)
  Epetra_MultiVector& vc = *S_next_->GetFieldData("vertex coordinate",name_)
      ->ViewComponent("node",false);
  for (int i=0; i!=nnodes; ++i) {
    mesh_->node_get_coordinates(i,&coords);
    for (int s=0; s!=dim; ++s) vc[s][i] = coords[s];
  }

  // setting deformation to be rock_volume at old time, (1-poro_old)*CV_old
  const Epetra_MultiVector& cv = *S_->GetFieldData("cell_volume")
      ->ViewComponent("cell",false);
  const Epetra_MultiVector& poro = *S_->GetFieldData(poro_key_)
      ->ViewComponent("cell",false);
  Epetra_MultiVector& def = *S_next_->GetFieldData(key_,name_)
      ->ViewComponent("cell",false);

  int ncells = def.MyLength();
  for (int c=0; c!=ncells; ++c) {
    def[0][c] = (1. - poro[0][c]) * cv[0][c];
  }
  // mark the placeholder evaluator as changed
  solution_evaluator_->SetFieldAsChanged(S_next_.ptr());

  // update porosity and cell volumes
  S_next_->GetFieldEvaluator("cell_volume")
      ->HasFieldChanged(S_next_.ptr(), name_);
  S_next_->GetFieldEvaluator("porosity")
      ->HasFieldChanged(S_next_.ptr(), name_);

  return false;
}

} // namespace
} // namespace
<|endoftext|>


<commit_before>#include "precompiled.hpp"
#include "model/gl/BlendState.hpp"

#include <QOpenGLFunctions_3_0>

namespace balls {

BlendState::BlendState(OpenGLPointers& gl, QObject* parent = nullptr)
  : QObject(parent),
    m_gl(gl),
    m_blendRgb(BlendEquation::Add),
    m_blendAlpha(BlendEquation::Add),
    m_srcRgb(BlendFunction::One),
    m_dstRgb(BlendFunction::Zero),
    m_srcAlpha(BlendFunction::One),
    m_dstAlpha(BlendFunction::Zero) {}
//  ^ Defaults specified in OpenGL

void BlendState::setBlendColor(const QColor& color) {
  m_blendColor = color;

  m_gl.gl30->glBlendColor(
    color.redF(), color.greenF(), color.blueF(), color.alphaF());
}

void BlendState::setBlendRgb(BlendEquation equation) {
  m_blendRgb = equation;

  updateEquation();
}

void BlendState::setBlendAlpha(BlendEquation equation) {
  m_blendAlpha = equation;

  updateEquation();
}

void BlendState::setSrcRgb(BlendFunction function) {
  m_srcRgb = function;

  updateFunction();
}

void BlendState::setDstRgb(BlendFunction function) {
  m_dstRgb = function;

  updateFunction();
}

void BlendState::setSrcAlpha(BlendFunction function) {
  m_srcAlpha = function;

  updateFunction();
}

void BlendState::setDstAlpha(BlendFunction function) {
  m_dstAlpha = function;

  updateFunction();
}

void BlendState::updateEquation() noexcept {
  m_gl.gl30->glBlendEquationSeparate(m_blendRgb, m_blendAlpha);
}

void BlendState::updateFunction() noexcept {
  m_gl.gl30->glBlendFuncSeparate(m_srcRgb, m_dstRgb, m_srcAlpha, m_dstAlpha);
}
}
<commit_msg>Q_ASSUME that we have OpenGL 3.0 at least<commit_after>#include "precompiled.hpp"
#include "model/gl/BlendState.hpp"

#include <QOpenGLFunctions_3_0>

namespace balls {

BlendState::BlendState(OpenGLPointers& gl, QObject* parent = nullptr)
  : QObject(parent),
    m_gl(gl),
    m_blendRgb(BlendEquation::Add),
    m_blendAlpha(BlendEquation::Add),
    m_srcRgb(BlendFunction::One),
    m_dstRgb(BlendFunction::Zero),
    m_srcAlpha(BlendFunction::One),
    m_dstAlpha(BlendFunction::Zero) {
  Q_ASSUME(m_gl.gl30 != nullptr);
}
//  ^ Defaults specified in OpenGL

void BlendState::setBlendColor(const QColor& color) {
  m_blendColor = color;

  m_gl.gl30->glBlendColor(
    color.redF(), color.greenF(), color.blueF(), color.alphaF());
}

void BlendState::setBlendRgb(BlendEquation equation) {
  m_blendRgb = equation;

  updateEquation();
}

void BlendState::setBlendAlpha(BlendEquation equation) {
  m_blendAlpha = equation;

  updateEquation();
}

void BlendState::setSrcRgb(BlendFunction function) {
  m_srcRgb = function;

  updateFunction();
}

void BlendState::setDstRgb(BlendFunction function) {
  m_dstRgb = function;

  updateFunction();
}

void BlendState::setSrcAlpha(BlendFunction function) {
  m_srcAlpha = function;

  updateFunction();
}

void BlendState::setDstAlpha(BlendFunction function) {
  m_dstAlpha = function;

  updateFunction();
}

void BlendState::updateEquation() noexcept {
  m_gl.gl30->glBlendEquationSeparate(m_blendRgb, m_blendAlpha);
}

void BlendState::updateFunction() noexcept {
  m_gl.gl30->glBlendFuncSeparate(m_srcRgb, m_dstRgb, m_srcAlpha, m_dstAlpha);
}
}
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2014 Max-Planck-Institute for Intelligent Systems,
 *                     University of Southern California
 *    Jan Issac (jan.issac@gmail.com)
 *    Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 *
 *
 *  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.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  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 OWNER 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.
 *
 */

/**
 * @date 2014
 * @author Jan Issac (jan.issac@gmail.com)
 * Max-Planck-Institute for Intelligent Systems,
 * University of Southern California
 */

#include <gtest/gtest.h>
#include "../typecast.hpp"

#include <Eigen/Dense>

#include <cmath>
#include <iostream>

#include <fl/util/math/linear_algebra.hpp>
#include <fl/filter/filter_interface.hpp>

#include <fl/filter/gaussian/gaussian_filter_linear.hpp>
#include <fl/model/process/linear_state_transition_model.hpp>
#include <fl/model/observation/linear_gaussian_observation_model.hpp>
#include <fl/model/observation/linear_decorrelated_gaussian_observation_model.hpp>

enum : signed int
{
    DecorrelatedGaussianModel,
    GaussianModel
};

static constexpr double epsilon = 0.1;

template <typename TestType>
class GaussianFilterLinearVsXTest
    : public ::testing::Test
{
protected:
    typedef typename TestType::Parameter Configuration;

    enum: signed int
    {
        StateDim = Configuration::StateDim,
        InputDim = Configuration::InputDim,
        ObsrvDim = Configuration::ObsrvDim,

        StateSize = fl::TestSize<StateDim, TestType>::Value,
        InputSize = fl::TestSize<InputDim, TestType>::Value,
        ObsrvSize = fl::TestSize<ObsrvDim, TestType>::Value
    };

    enum ModelSetup
    {
        Random,
        Identity
    };

    typedef Eigen::Matrix<fl::Real, StateSize, 1> State;
    typedef Eigen::Matrix<fl::Real, InputSize, 1> Input;
    typedef Eigen::Matrix<fl::Real, ObsrvSize, 1> Obsrv;

    typedef fl::IntegerTypeMap<
                fl::IntegerTypePair<
                    DecorrelatedGaussianModel,
                    fl::LinearDecorrelatedGaussianObservationModel<Obsrv, State>
                >,
                fl::IntegerTypePair<
                    GaussianModel,
                    fl::LinearGaussianObservationModel<Obsrv, State>
                >
            > ObsrvModelMap;

    typedef fl::LinearStateTransitionModel<State, Input> LinearStateTransition;

    typedef typename ObsrvModelMap::template Select<
                Configuration::SelectedModel
            >::Type LinearObservationModel;

    typedef fl::GaussianFilter<
                LinearStateTransition, LinearObservationModel
            > KalmanFilter;

    typedef typename Configuration::template FilterDefinition<
                LinearStateTransition,
                LinearObservationModel
            > FilterDefinition;

    typedef typename FilterDefinition::Type Filter;

    GaussianFilterLinearVsXTest()
        : predict_steps_(200),
          predict_update_steps_(30)
    { }

    KalmanFilter create_kalman_filter() const
    {
        return KalmanFilter(
                LinearStateTransition(StateDim, InputDim),
                LinearObservationModel(ObsrvDim, StateDim));
    }

    Filter create_filter() const
    {
        return Configuration::create_filter(
                LinearStateTransition(StateDim, InputDim),
                LinearObservationModel(ObsrvDim, StateDim));
    }

    void setup_models(
        KalmanFilter& kalman_filter, Filter& other_filter, ModelSetup setup)
    {
        auto A = kalman_filter.process_model().create_dynamics_matrix();
        auto B = kalman_filter.process_model().create_input_matrix();
        auto Q = kalman_filter.process_model().create_noise_matrix();

        auto H = kalman_filter.obsrv_model().create_sensor_matrix();
        auto R = kalman_filter.obsrv_model().create_noise_matrix();

        Q.setZero();
        R.setZero();
        B.setZero();

        switch (setup)
        {
        case Random:
            A.diagonal().setRandom();
            H.diagonal().setRandom();
            Q.diagonal().setRandom(); Q *= Q.transpose().eval();
            R.diagonal().setRandom(); R *= R.transpose().eval();
            break;

        case Identity:
            A.setIdentity();
            H.setIdentity();
            Q.setIdentity();
            R.setIdentity();
            break;
        }

        kalman_filter.process_model().dynamics_matrix(A);
        kalman_filter.process_model().input_matrix(B);
        kalman_filter.process_model().noise_matrix(Q);
        kalman_filter.obsrv_model().sensor_matrix(H);
        kalman_filter.obsrv_model().noise_matrix(R);

        other_filter.process_model().dynamics_matrix(A);
        other_filter.process_model().input_matrix(B);
        other_filter.process_model().noise_matrix(Q);
        other_filter.obsrv_model().sensor_matrix(H);
        other_filter.obsrv_model().noise_matrix(R);
    }

    State zero_state() { return State::Zero(StateDim); }
    Input zero_input() { return Input::Zero(InputDim); }
    Obsrv zero_obsrv() { return Obsrv::Zero(ObsrvDim); }

    State rand_state() { return State::Random(StateDim); }
    Input rand_input() { return Input::Random(InputDim); }
    Obsrv rand_obsrv() { return Obsrv::Random(ObsrvDim); }

protected:
    int predict_steps_;
    int predict_update_steps_;
};

TYPED_TEST_CASE_P(GaussianFilterLinearVsXTest);

//TYPED_TEST_P(GaussianFilterLinearVsXTest, predict)
//{
//    typedef TestFixture This;

//    auto other_filter = This::create_filter();
//    auto kalman_filter = This::create_kalman_filter();

//    This::setup_models(kalman_filter, other_filter, This::Random);

//    auto belief_other = other_filter.create_belief();
//    auto belief_kf = kalman_filter.create_belief();

//    for (int i = 0; i < This::predict_steps_; ++i)
//    {
//        other_filter.predict(belief_other, This::zero_input(), belief_other);
//        kalman_filter.predict(belief_kf, This::zero_input(), belief_kf);

//        if (!fl::are_similar(belief_other.mean(), belief_kf.mean(), epsilon))
//        {
//            std::cout << "i = " << i << std::endl;
//            PV(belief_kf.mean());
//            PV(belief_other.mean());
//        }

//        if (!fl::are_similar(belief_other.covariance(), belief_kf.covariance(), epsilon))
//        {
//            std::cout << "i = " << i << std::endl;
//            PV(belief_kf.covariance());
//            PV(belief_other.covariance());
//        }

//        ASSERT_TRUE(
//            fl::are_similar(belief_other.mean(), belief_kf.mean(), epsilon));

//        ASSERT_TRUE(
//            fl::are_similar(belief_other.covariance(), belief_kf.covariance(), epsilon));
//    }

//    PV(belief_kf.mean());
//    PV(belief_other.mean());
//    PV(belief_kf.covariance());
//    PV(belief_other.covariance());
//}

TYPED_TEST_P(GaussianFilterLinearVsXTest, predict_and_update)
{
    typedef TestFixture This;

    auto other_filter = This::create_filter();
    auto kalman_filter = This::create_kalman_filter();

    This::setup_models(kalman_filter, other_filter, This::Random);

    auto belief_other = other_filter.create_belief();
    auto belief_kf = kalman_filter.create_belief();

    for (int i = 0; i < This::predict_update_steps_; ++i)
    {
        auto y = This::rand_obsrv();

        kalman_filter.predict(belief_kf, This::zero_input(), belief_kf);
        other_filter.predict(belief_other, This::zero_input(), belief_other);

//        if (!fl::are_similar(belief_other.mean(), belief_kf.mean(), epsilon))
//        {
//            std::cout << "predict i = " << i << std::endl;
//            PV(belief_kf.mean());
//            PV(belief_other.mean());
//        }

//        if (!fl::are_similar(belief_other.covariance(), belief_kf.covariance(), epsilon))
//        {
//            std::cout << "predict i = " << i << std::endl;
//            PV(belief_kf.covariance());
//            PV(belief_other.covariance());
//        }

        kalman_filter.update(belief_kf, y, belief_kf);
        other_filter.update(belief_other, y, belief_other);

//        if (!fl::are_similar(belief_other.mean(), belief_kf.mean(), epsilon))
//        {
//            std::cout << "update i = " << i << std::endl;
//            PV(belief_kf.mean());
//            PV(belief_other.mean());
//        }

//        if (!fl::are_similar(belief_other.covariance(), belief_kf.covariance(), epsilon))
//        {
//            std::cout << "update i = " << i << std::endl;
//            PV(belief_kf.covariance());
//            PV(belief_other.covariance());
//        }

        ASSERT_TRUE(
            fl::are_similar(belief_other.mean(), belief_kf.mean(), epsilon));

        ASSERT_TRUE(
            fl::are_similar(belief_other.covariance(), belief_kf.covariance(), epsilon));
    }

//    PV(belief_kf.mean());
//    PV(belief_other.mean());

//    PV(belief_kf.covariance());
//    PV(belief_other.covariance());

//    std::cout << other_filter.name() << std::endl;
}

REGISTER_TYPED_TEST_CASE_P(GaussianFilterLinearVsXTest,
                           predict_and_update);
<commit_msg>header updated<commit_after>/*
 * This is part of the FL library, a C++ Bayesian filtering library
 * (https://github.com/filtering-library)
 *
 * Copyright (c) 2014 Jan Issac (jan.issac@gmail.com)
 * Copyright (c) 2014 Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 * Max-Planck Institute for Intelligent Systems, AMD Lab
 * University of Southern California, CLMC Lab
 *
 * This Source Code Form is subject to the terms of the MIT License (MIT).
 * A copy of the license can be found in the LICENSE file distributed with this
 * source code.
 */

/**
 * \file gaussian_filter_linear_vs_x_test_suite.hpp
 * \date July 2015
 * \author Jan Issac (jan.issac@gmail.com)
 */

#include <gtest/gtest.h>
#include "../typecast.hpp"

#include <Eigen/Dense>

#include <cmath>
#include <iostream>

#include <fl/util/math/linear_algebra.hpp>
#include <fl/filter/filter_interface.hpp>

#include <fl/filter/gaussian/gaussian_filter_linear.hpp>
#include <fl/model/process/linear_state_transition_model.hpp>
#include <fl/model/observation/linear_gaussian_observation_model.hpp>
#include <fl/model/observation/linear_decorrelated_gaussian_observation_model.hpp>

enum : signed int
{
    DecorrelatedGaussianModel,
    GaussianModel
};

static constexpr double epsilon = 0.1;

template <typename TestType>
class GaussianFilterLinearVsXTest
    : public ::testing::Test
{
protected:
    typedef typename TestType::Parameter Configuration;

    enum: signed int
    {
        StateDim = Configuration::StateDim,
        InputDim = Configuration::InputDim,
        ObsrvDim = Configuration::ObsrvDim,

        StateSize = fl::TestSize<StateDim, TestType>::Value,
        InputSize = fl::TestSize<InputDim, TestType>::Value,
        ObsrvSize = fl::TestSize<ObsrvDim, TestType>::Value
    };

    enum ModelSetup
    {
        Random,
        Identity
    };

    typedef Eigen::Matrix<fl::Real, StateSize, 1> State;
    typedef Eigen::Matrix<fl::Real, InputSize, 1> Input;
    typedef Eigen::Matrix<fl::Real, ObsrvSize, 1> Obsrv;

    typedef fl::IntegerTypeMap<
                fl::IntegerTypePair<
                    DecorrelatedGaussianModel,
                    fl::LinearDecorrelatedGaussianObservationModel<Obsrv, State>
                >,
                fl::IntegerTypePair<
                    GaussianModel,
                    fl::LinearGaussianObservationModel<Obsrv, State>
                >
            > ObsrvModelMap;

    typedef fl::LinearStateTransitionModel<State, Input> LinearStateTransition;

    typedef typename ObsrvModelMap::template Select<
                Configuration::SelectedModel
            >::Type LinearObservationModel;

    typedef fl::GaussianFilter<
                LinearStateTransition, LinearObservationModel
            > KalmanFilter;

    typedef typename Configuration::template FilterDefinition<
                LinearStateTransition,
                LinearObservationModel
            > FilterDefinition;

    typedef typename FilterDefinition::Type Filter;

    GaussianFilterLinearVsXTest()
        : predict_steps_(200),
          predict_update_steps_(30)
    { }

    KalmanFilter create_kalman_filter() const
    {
        return KalmanFilter(
                LinearStateTransition(StateDim, InputDim),
                LinearObservationModel(ObsrvDim, StateDim));
    }

    Filter create_filter() const
    {
        return Configuration::create_filter(
                LinearStateTransition(StateDim, InputDim),
                LinearObservationModel(ObsrvDim, StateDim));
    }

    void setup_models(
        KalmanFilter& kalman_filter, Filter& other_filter, ModelSetup setup)
    {
        auto A = kalman_filter.process_model().create_dynamics_matrix();
        auto B = kalman_filter.process_model().create_input_matrix();
        auto Q = kalman_filter.process_model().create_noise_matrix();

        auto H = kalman_filter.obsrv_model().create_sensor_matrix();
        auto R = kalman_filter.obsrv_model().create_noise_matrix();

        Q.setZero();
        R.setZero();
        B.setZero();

        switch (setup)
        {
        case Random:
            A.diagonal().setRandom();
            H.diagonal().setRandom();
            Q.diagonal().setRandom(); Q *= Q.transpose().eval();
            R.diagonal().setRandom(); R *= R.transpose().eval();
            break;

        case Identity:
            A.setIdentity();
            H.setIdentity();
            Q.setIdentity();
            R.setIdentity();
            break;
        }

        kalman_filter.process_model().dynamics_matrix(A);
        kalman_filter.process_model().input_matrix(B);
        kalman_filter.process_model().noise_matrix(Q);
        kalman_filter.obsrv_model().sensor_matrix(H);
        kalman_filter.obsrv_model().noise_matrix(R);

        other_filter.process_model().dynamics_matrix(A);
        other_filter.process_model().input_matrix(B);
        other_filter.process_model().noise_matrix(Q);
        other_filter.obsrv_model().sensor_matrix(H);
        other_filter.obsrv_model().noise_matrix(R);
    }

    State zero_state() { return State::Zero(StateDim); }
    Input zero_input() { return Input::Zero(InputDim); }
    Obsrv zero_obsrv() { return Obsrv::Zero(ObsrvDim); }

    State rand_state() { return State::Random(StateDim); }
    Input rand_input() { return Input::Random(InputDim); }
    Obsrv rand_obsrv() { return Obsrv::Random(ObsrvDim); }

protected:
    int predict_steps_;
    int predict_update_steps_;
};

TYPED_TEST_CASE_P(GaussianFilterLinearVsXTest);

//TYPED_TEST_P(GaussianFilterLinearVsXTest, predict)
//{
//    typedef TestFixture This;

//    auto other_filter = This::create_filter();
//    auto kalman_filter = This::create_kalman_filter();

//    This::setup_models(kalman_filter, other_filter, This::Random);

//    auto belief_other = other_filter.create_belief();
//    auto belief_kf = kalman_filter.create_belief();

//    for (int i = 0; i < This::predict_steps_; ++i)
//    {
//        other_filter.predict(belief_other, This::zero_input(), belief_other);
//        kalman_filter.predict(belief_kf, This::zero_input(), belief_kf);

//        if (!fl::are_similar(belief_other.mean(), belief_kf.mean(), epsilon))
//        {
//            std::cout << "i = " << i << std::endl;
//            PV(belief_kf.mean());
//            PV(belief_other.mean());
//        }

//        if (!fl::are_similar(belief_other.covariance(), belief_kf.covariance(), epsilon))
//        {
//            std::cout << "i = " << i << std::endl;
//            PV(belief_kf.covariance());
//            PV(belief_other.covariance());
//        }

//        ASSERT_TRUE(
//            fl::are_similar(belief_other.mean(), belief_kf.mean(), epsilon));

//        ASSERT_TRUE(
//            fl::are_similar(belief_other.covariance(), belief_kf.covariance(), epsilon));
//    }

//    PV(belief_kf.mean());
//    PV(belief_other.mean());
//    PV(belief_kf.covariance());
//    PV(belief_other.covariance());
//}

TYPED_TEST_P(GaussianFilterLinearVsXTest, predict_and_update)
{
    typedef TestFixture This;

    auto other_filter = This::create_filter();
    auto kalman_filter = This::create_kalman_filter();

    This::setup_models(kalman_filter, other_filter, This::Random);

    auto belief_other = other_filter.create_belief();
    auto belief_kf = kalman_filter.create_belief();

    for (int i = 0; i < This::predict_update_steps_; ++i)
    {
        auto y = This::rand_obsrv();

        kalman_filter.predict(belief_kf, This::zero_input(), belief_kf);
        other_filter.predict(belief_other, This::zero_input(), belief_other);

//        if (!fl::are_similar(belief_other.mean(), belief_kf.mean(), epsilon))
//        {
//            std::cout << "predict i = " << i << std::endl;
//            PV(belief_kf.mean());
//            PV(belief_other.mean());
//        }

//        if (!fl::are_similar(belief_other.covariance(), belief_kf.covariance(), epsilon))
//        {
//            std::cout << "predict i = " << i << std::endl;
//            PV(belief_kf.covariance());
//            PV(belief_other.covariance());
//        }

        kalman_filter.update(belief_kf, y, belief_kf);
        other_filter.update(belief_other, y, belief_other);

//        if (!fl::are_similar(belief_other.mean(), belief_kf.mean(), epsilon))
//        {
//            std::cout << "update i = " << i << std::endl;
//            PV(belief_kf.mean());
//            PV(belief_other.mean());
//        }

//        if (!fl::are_similar(belief_other.covariance(), belief_kf.covariance(), epsilon))
//        {
//            std::cout << "update i = " << i << std::endl;
//            PV(belief_kf.covariance());
//            PV(belief_other.covariance());
//        }

        ASSERT_TRUE(
            fl::are_similar(belief_other.mean(), belief_kf.mean(), epsilon));

        ASSERT_TRUE(
            fl::are_similar(belief_other.covariance(), belief_kf.covariance(), epsilon));
    }

//    PV(belief_kf.mean());
//    PV(belief_other.mean());

//    PV(belief_kf.covariance());
//    PV(belief_other.covariance());

//    std::cout << other_filter.name() << std::endl;
}

REGISTER_TYPED_TEST_CASE_P(GaussianFilterLinearVsXTest,
                           predict_and_update);
<|endoftext|>


<commit_before>#include <boost/algorithm/string.hpp>
#include <iostream>
using namespace std;

const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

string get_keyphrase(const string& text, const string& keyword)
{
  /* Returns the Vigenere keyword of appropriate length (in all caps) for a
   * given text (either plaintext or ciphertext) and keyword.
   */
  string keyphrase = "";
  string caps_keyword = boost::algorithm::to_upper_copy<string>(keyword);

  size_t keyword_length = keyword.length();
  size_t text_length = text.length();

  for (int i = 0; i < text_length; i++)
  {
    keyphrase += caps_keyword[i % keyword_length];
  }

  return keyphrase;
}

string encrypt(const string& plaintext, const string& keyword)
{
  /* Returns the ciphertext produced by encrypting the plaintext using the
   * given keyword and the Vigenere Cipher
   * (http://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher).
   */

  string ciphertext = "";
  string caps_plaintext = boost::algorithm::to_upper_copy<string>(plaintext);
  string keyphrase = get_keyphrase(plaintext, keyword);

  for (int i = 0; i < plaintext.length(); i++)
  {
    int plaintext_index = alphabet.find(caps_plaintext[i]);
    int advance_by = alphabet.find(keyphrase[i]);
    int ciphertext_index = (plaintext_index + advance_by) % alphabet.length();

    ciphertext += alphabet[ciphertext_index];
  }

  return ciphertext;
}

string decrypt(const string& ciphertext, const string& keyword)
{
  /* Returns the plaintext produced by decrypting the ciphertext using the
   * given keyword and the Vigenere Cipher
   * (http://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher).
   */
  string plaintext = "";
  string keyphrase = get_keyphrase(ciphertext, keyword);

  string caps_ciphertext = boost::algorithm::to_upper_copy<string>(ciphertext);

  for (int i = 0; i < ciphertext.length(); i++)
  {
    int ciphertext_index = alphabet.find(caps_ciphertext[i]);
    int reverse_by = alphabet.find(keyphrase[i]);
    int plaintext_index = (ciphertext_index - reverse_by) % alphabet.length();

    plaintext += alphabet[plaintext_index];
  }

  return plaintext;
}
<commit_msg>Played around with whitespace and line organization.<commit_after>#include <boost/algorithm/string.hpp>
#include <iostream>
using namespace std;

const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

string get_keyphrase(const string& text, const string& keyword)
{
  /* Returns the Vigenere keyword of appropriate length (in all caps) for a
   * given text (either plaintext or ciphertext) and keyword.
   */
  string keyphrase = "";
  string caps_keyword = boost::algorithm::to_upper_copy<string>(keyword);

  size_t keyword_length = keyword.length();
  size_t text_length = text.length();

  for (int i = 0; i < text_length; i++)
  {
    keyphrase += caps_keyword[i % keyword_length];
  }

  return keyphrase;
}

string encrypt(const string& plaintext, const string& keyword)
{
  /* Returns the ciphertext produced by encrypting the plaintext using the
   * given keyword and the Vigenere Cipher
   * (http://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher).
   */

  string ciphertext = "";
  string caps_plaintext = boost::algorithm::to_upper_copy<string>(plaintext);
  string keyphrase = get_keyphrase(plaintext, keyword);

  for (int i = 0; i < plaintext.length(); i++)
  {
    int plaintext_index = alphabet.find(caps_plaintext[i]);
    int advance_by = alphabet.find(keyphrase[i]);
    int ciphertext_index = (plaintext_index + advance_by) % alphabet.length();

    ciphertext += alphabet[ciphertext_index];
  }

  return ciphertext;
}

string decrypt(const string& ciphertext, const string& keyword)
{
  /* Returns the plaintext produced by decrypting the ciphertext using the
   * given keyword and the Vigenere Cipher
   * (http://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher).
   */
  string plaintext = "";
  string caps_ciphertext = boost::algorithm::to_upper_copy<string>(ciphertext);
  string keyphrase = get_keyphrase(ciphertext, keyword);

  for (int i = 0; i < ciphertext.length(); i++)
  {
    int ciphertext_index = alphabet.find(caps_ciphertext[i]);
    int reverse_by = alphabet.find(keyphrase[i]);
    int plaintext_index = (ciphertext_index - reverse_by) % alphabet.length();

    plaintext += alphabet[plaintext_index];
  }

  return plaintext;
}
<|endoftext|>


<commit_before>// Copyright (c) 2013, Matthew Harvey. All rights reserved.

#include "transaction_dialog.hpp"
#include "account.hpp"
#include "date.hpp"
#include "decimal_text_ctrl.hpp"
#include "decimal_validator.hpp"
#include "entry.hpp"
#include "finformat.hpp"
#include "frame.hpp"
#include "ordinary_journal.hpp"
#include "locale.hpp"
#include "phatbooks_database_connection.hpp"
#include <boost/date_time/gregorian/gregorian.hpp>
#include <jewel/debug_log.hpp>
#include <jewel/decimal.hpp>
#include <wx/arrstr.h>
#include <wx/button.h>
#include <wx/datectrl.h>
#include <wx/dialog.h>
#include <wx/event.h>
#include <wx/msgdlg.h>
#include <wx/radiobox.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/string.h>
#include <wx/textctrl.h>
#include <cassert>
#include <iostream>
#include <vector>

using jewel::Decimal;
using std::endl;
using std::vector;

namespace gregorian = boost::gregorian;

namespace phatbooks
{
namespace gui
{

BEGIN_EVENT_TABLE(TransactionDialog, wxDialog)
	EVT_BUTTON
	(	wxID_OK,
		TransactionDialog::on_ok_button_click
	)
END_EVENT_TABLE()

// TODO HIGH PRIORITY.
// There are bugs in wxWidgets' wxDatePickerCtrl, at least in wxGTK.
// Firstly, tab traversal gets stuck on that control.
// Secondly, if we type a different date and then press "Enter" for OK,
// the date that actually gets picked up as the transaction date always
// seems to be TODAY's date, not the date actually entered. This appears to
// be an unresolved bug in wxWidgets.
// Note adding wxTAB_TRAVERSAL to style does not seem to fix the problem.

TransactionDialog::TransactionDialog
(	Frame* p_parent,
	vector<Account> const& p_accounts
):
	wxDialog
	(	p_parent,
		wxID_ANY,
		"New transaction",
		wxDefaultPosition,
		wxDefaultSize
	),
	m_top_sizer(0),
	m_actual_vs_budget_ctrl(0),
	m_date_ctrl(0),
	m_cancel_button(0),
	m_ok_button(0),
	m_database_connection(0)
{
	assert (m_account_name_boxes.empty());
	assert (m_comment_boxes.empty());
	assert (m_amount_boxes.empty());

	// We construct m_ok_button first as we want to be able to refer to its
	// size when sizing certain other controls below. But we will not add
	// the OK button to m_top_sizer till later.
	m_ok_button = new wxButton
	(	this,
		wxID_OK,
		wxString("&OK"),
		wxDefaultPosition,
		wxDefaultSize
	);
	wxSize const ok_button_size = m_ok_button->GetSize();

	// Top sizer
	m_top_sizer = new wxFlexGridSizer(p_accounts.size() + 4, 3, 0, 0);

	// Column titles
	wxStaticText* header0 = new wxStaticText(this, wxID_ANY, "Account");
	wxStaticText* header1 = new wxStaticText(this, wxID_ANY, "Comment");
	wxStaticText* header2 = new wxStaticText(this, wxID_ANY, "Amount");
	unsigned int const header_flag = wxLEFT | wxTOP | wxBOTTOM;
	m_top_sizer->Add(header0, 2, header_flag, 10);
	m_top_sizer->Add(header1, 3, header_flag, 10);
	m_top_sizer->Add(header2, 2, header_flag, 10);

	// Rows for entering Entry details
	typedef vector<Account>::size_type Size;
	Size const sz = p_accounts.size();
	for (Size id = s_min_entry_row_id, i = 0 ; i != sz; ++i, ++id)
	{
		Account const account = p_accounts[i];
		if (!m_database_connection)
		{
			m_database_connection = &(account.database_connection());
		}
		wxStaticText* account_name_text = new wxStaticText
		(	this,
			id,
			bstring_to_wx(account.name()),
			wxDefaultPosition,
			wxDefaultSize
		);
		wxSize const account_name_text_size = account_name_text->GetSize();
		wxTextCtrl* comment_ctrl = new wxTextCtrl
		(	this,
			id,
			wxEmptyString,
			wxDefaultPosition,
			wxSize(ok_button_size.x * 4.5, account_name_text_size.y * 1.2),
			wxALIGN_LEFT
		);
		Decimal::places_type const precision =
			account.commodity().precision();
		DecimalTextCtrl* entry_ctrl = new DecimalTextCtrl
		(	this,
			id,
			wxSize(ok_button_size.x * 1.5, account_name_text_size.y * 1.2),
			precision,
			false
		);
		int base_flag = wxLEFT;
		if (i == 0) base_flag |= wxTOP;
		m_top_sizer->
			Add(account_name_text, 2, base_flag | wxRIGHT | wxALIGN_LEFT, 10);
		m_top_sizer->
			Add(comment_ctrl, 3, base_flag | wxALIGN_LEFT, 10);
		m_top_sizer->
			Add(entry_ctrl, 2, base_flag | wxRIGHT | wxALIGN_RIGHT, 10);

		m_account_name_boxes.push_back(account_name_text);
		m_comment_boxes.push_back(comment_ctrl);
		m_amount_boxes.push_back(entry_ctrl);
	}

	m_top_sizer->AddStretchSpacer();
	m_top_sizer->AddStretchSpacer();

	// Radio box for selecting actual vs. budget
	wxArrayString radio_box_strings;
	radio_box_strings.Add(wxString("Actual"));
	radio_box_strings.Add(wxString("Budget"));
	m_actual_vs_budget_ctrl = new wxRadioBox
	(	this,
		wxID_ANY,
		wxEmptyString,
		wxDefaultPosition,
		wxDefaultSize,
		radio_box_strings,
		1,
		wxRA_SPECIFY_COLS
	);
	m_top_sizer->Add
	(	m_actual_vs_budget_ctrl,
		3,
		wxRIGHT | wxLEFT | wxALIGN_RIGHT,
		10
	);

	m_top_sizer->AddStretchSpacer();
	m_top_sizer->AddStretchSpacer();

	// Date control
	m_date_ctrl = new wxDatePickerCtrl(this, wxID_ANY);
	m_top_sizer->Add(m_date_ctrl, 2, wxRIGHT | wxLEFT | wxTOP, 10);

	// Cancel and OK buttons
	m_cancel_button = new wxButton
	(	this,
		wxID_CANCEL,
		wxString("&Cancel"),
		wxDefaultPosition,
		wxDefaultSize
	);
	m_top_sizer->Add
	(	m_cancel_button,
		2,
		wxALIGN_LEFT | wxLEFT | wxRIGHT | wxBOTTOM | wxTOP,
		10
	);
	m_top_sizer->AddStretchSpacer();
	m_top_sizer->Add
	(	m_ok_button,
		2,
		wxALIGN_LEFT | wxLEFT | wxRIGHT | wxBOTTOM | wxTOP,
		10
	);
	m_ok_button->SetDefault();  // Enter key will now trigger "OK" button

	// "Admin"
	SetSizer(m_top_sizer);
	m_top_sizer->Fit(this);
	m_top_sizer->SetSizeHints(this);
	Layout();
	CentreOnScreen();
}

void
TransactionDialog::on_ok_button_click(wxCommandEvent& event)
{
	(void)event;  // Silence compiler re. unused parameter.
	if (Validate() && TransferDataFromWindow())
	{
		assert (IsModal());
		if (is_balanced())
		{
			post_journal();
			EndModal(wxID_OK);
		}
		else
		{
			wxMessageBox("Transaction does not balance.");
		}
	}
	return;
}

void
TransactionDialog::post_journal() const
{
	if (m_database_connection)
	{
		OrdinaryJournal journal(*m_database_connection);
		journal.set_whether_actual
		(	m_actual_vs_budget_ctrl->GetSelection() == 0
		);
		size_t const sz = m_account_name_boxes.size();
		assert (sz == m_comment_boxes.size());
		assert (sz == m_amount_boxes.size());
		for (size_t i = 0; i != sz; ++i)
		{
			assert (m_database_connection);
			Account const account
			(	*m_database_connection,
				wx_to_bstring(wxString(m_account_name_boxes[i]->GetLabel()))
			);
			Entry entry(*m_database_connection);
			entry.set_account(account);
			entry.set_comment
			(	wx_to_bstring(m_comment_boxes[i]->GetValue())
			);
			Decimal amount = wx_to_decimal
			(	wxString(m_amount_boxes[i]->GetValue()),
				locale()
			);
			if (!journal.is_actual()) amount = -amount;
			amount = round(amount, account.commodity().precision());
			entry.set_amount(amount);
			entry.set_whether_reconciled(false);
			journal.push_entry(entry);
		}
		assert (journal.is_balanced());
		journal.set_comment("");
		wxDateTime const date_wx = m_date_ctrl->GetValue();
		int year = date_wx.GetYear();
		if (year < 100) year += 2000;
		int const month = static_cast<int>(date_wx.GetMonth()) + 1;
		int const day = date_wx.GetDay();
		journal.set_date(gregorian::date(year, month, day));

		journal.save();

		Frame* const frame = dynamic_cast<Frame*>(GetParent());
		assert (frame);
		frame->update_for_posted_journal(journal);
	}
}

bool
TransactionDialog::is_balanced() const
{
	Decimal balance(0, 0);
	vector<DecimalTextCtrl*>::size_type i = 0;
	vector<DecimalTextCtrl*>::size_type const sz = m_amount_boxes.size();
	for ( ; i != sz; ++i)
	{
		balance += wx_to_decimal(m_amount_boxes[i]->GetValue(), locale());
	}
	return balance == Decimal(0, 0);
}

}  // namespace gui
}  // namespace phatbooks
<commit_msg>In TransactionDialog, forced style of wxDatePickerCtrl to be wxDP_SPIN.<commit_after>// Copyright (c) 2013, Matthew Harvey. All rights reserved.

#include "transaction_dialog.hpp"
#include "account.hpp"
#include "date.hpp"
#include "decimal_text_ctrl.hpp"
#include "decimal_validator.hpp"
#include "entry.hpp"
#include "finformat.hpp"
#include "frame.hpp"
#include "ordinary_journal.hpp"
#include "locale.hpp"
#include "phatbooks_database_connection.hpp"
#include <boost/date_time/gregorian/gregorian.hpp>
#include <jewel/debug_log.hpp>
#include <jewel/decimal.hpp>
#include <wx/arrstr.h>
#include <wx/button.h>
#include <wx/datectrl.h>
#include <wx/dialog.h>
#include <wx/event.h>
#include <wx/msgdlg.h>
#include <wx/radiobox.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/string.h>
#include <wx/textctrl.h>
#include <cassert>
#include <iostream>
#include <vector>

using jewel::Decimal;
using std::endl;
using std::vector;

namespace gregorian = boost::gregorian;

namespace phatbooks
{
namespace gui
{

BEGIN_EVENT_TABLE(TransactionDialog, wxDialog)
	EVT_BUTTON
	(	wxID_OK,
		TransactionDialog::on_ok_button_click
	)
END_EVENT_TABLE()

// TODO HIGH PRIORITY.
// There are bugs in wxWidgets' wxDatePickerCtrl under wxGTK.
// Firstly, tab traversal gets stuck on that control.
// Secondly, if we type a different date and then press "Enter" for OK,
// the date that actually gets picked up as the transaction date always
// seems to be TODAY's date, not the date actually entered. This appears to
// be an unresolved bug in wxWidgets.
// Note adding wxTAB_TRAVERSAL to style does not seem to fix the problem.

TransactionDialog::TransactionDialog
(	Frame* p_parent,
	vector<Account> const& p_accounts
):
	wxDialog
	(	p_parent,
		wxID_ANY,
		"New transaction",
		wxDefaultPosition,
		wxDefaultSize
	),
	m_top_sizer(0),
	m_actual_vs_budget_ctrl(0),
	m_date_ctrl(0),
	m_cancel_button(0),
	m_ok_button(0),
	m_database_connection(0)
{
	assert (m_account_name_boxes.empty());
	assert (m_comment_boxes.empty());
	assert (m_amount_boxes.empty());

	// We construct m_ok_button first as we want to be able to refer to its
	// size when sizing certain other controls below. But we will not add
	// the OK button to m_top_sizer till later.
	m_ok_button = new wxButton
	(	this,
		wxID_OK,
		wxString("&OK"),
		wxDefaultPosition,
		wxDefaultSize
	);
	wxSize const ok_button_size = m_ok_button->GetSize();

	// Top sizer
	m_top_sizer = new wxFlexGridSizer(p_accounts.size() + 4, 3, 0, 0);

	// Column titles
	wxStaticText* header0 = new wxStaticText(this, wxID_ANY, "Account");
	wxStaticText* header1 = new wxStaticText(this, wxID_ANY, "Comment");
	wxStaticText* header2 = new wxStaticText(this, wxID_ANY, "Amount");
	unsigned int const header_flag = wxLEFT | wxTOP | wxBOTTOM;
	m_top_sizer->Add(header0, 2, header_flag, 10);
	m_top_sizer->Add(header1, 3, header_flag, 10);
	m_top_sizer->Add(header2, 2, header_flag, 10);

	// Rows for entering Entry details
	typedef vector<Account>::size_type Size;
	Size const sz = p_accounts.size();
	for (Size id = s_min_entry_row_id, i = 0 ; i != sz; ++i, ++id)
	{
		Account const account = p_accounts[i];
		if (!m_database_connection)
		{
			m_database_connection = &(account.database_connection());
		}
		wxStaticText* account_name_text = new wxStaticText
		(	this,
			id,
			bstring_to_wx(account.name()),
			wxDefaultPosition,
			wxDefaultSize
		);
		wxSize const account_name_text_size = account_name_text->GetSize();
		wxTextCtrl* comment_ctrl = new wxTextCtrl
		(	this,
			id,
			wxEmptyString,
			wxDefaultPosition,
			wxSize(ok_button_size.x * 4.5, account_name_text_size.y * 1.2),
			wxALIGN_LEFT
		);
		Decimal::places_type const precision =
			account.commodity().precision();
		DecimalTextCtrl* entry_ctrl = new DecimalTextCtrl
		(	this,
			id,
			wxSize(ok_button_size.x * 1.5, account_name_text_size.y * 1.2),
			precision,
			false
		);
		int base_flag = wxLEFT;
		if (i == 0) base_flag |= wxTOP;
		m_top_sizer->
			Add(account_name_text, 2, base_flag | wxRIGHT | wxALIGN_LEFT, 10);
		m_top_sizer->
			Add(comment_ctrl, 3, base_flag | wxALIGN_LEFT, 10);
		m_top_sizer->
			Add(entry_ctrl, 2, base_flag | wxRIGHT | wxALIGN_RIGHT, 10);

		m_account_name_boxes.push_back(account_name_text);
		m_comment_boxes.push_back(comment_ctrl);
		m_amount_boxes.push_back(entry_ctrl);
	}

	m_top_sizer->AddStretchSpacer();
	m_top_sizer->AddStretchSpacer();

	// Radio box for selecting actual vs. budget
	wxArrayString radio_box_strings;
	radio_box_strings.Add(wxString("Actual"));
	radio_box_strings.Add(wxString("Budget"));
	m_actual_vs_budget_ctrl = new wxRadioBox
	(	this,
		wxID_ANY,
		wxEmptyString,
		wxDefaultPosition,
		wxDefaultSize,
		radio_box_strings,
		1,
		wxRA_SPECIFY_COLS
	);
	m_top_sizer->Add
	(	m_actual_vs_budget_ctrl,
		3,
		wxRIGHT | wxLEFT | wxALIGN_RIGHT,
		10
	);

	m_top_sizer->AddStretchSpacer();
	m_top_sizer->AddStretchSpacer();

	// Date control
	m_date_ctrl = new wxDatePickerCtrl
	(	this,
		wxID_ANY,
		wxDefaultDateTime,
		wxDefaultPosition,
		wxDefaultSize,
		wxDP_DEFAULT | wxDP_SHOWCENTURY | wxDP_SPIN
	);
	m_top_sizer->Add(m_date_ctrl, 2, wxRIGHT | wxLEFT | wxTOP, 10);

	// Cancel and OK buttons
	m_cancel_button = new wxButton
	(	this,
		wxID_CANCEL,
		wxString("&Cancel"),
		wxDefaultPosition,
		wxDefaultSize
	);
	m_top_sizer->Add
	(	m_cancel_button,
		2,
		wxALIGN_LEFT | wxLEFT | wxRIGHT | wxBOTTOM | wxTOP,
		10
	);
	m_top_sizer->AddStretchSpacer();
	m_top_sizer->Add
	(	m_ok_button,
		2,
		wxALIGN_LEFT | wxLEFT | wxRIGHT | wxBOTTOM | wxTOP,
		10
	);
	m_ok_button->SetDefault();  // Enter key will now trigger "OK" button

	// "Admin"
	SetSizer(m_top_sizer);
	m_top_sizer->Fit(this);
	m_top_sizer->SetSizeHints(this);
	Layout();
	CentreOnScreen();
}

void
TransactionDialog::on_ok_button_click(wxCommandEvent& event)
{
	(void)event;  // Silence compiler re. unused parameter.
	if (Validate() && TransferDataFromWindow())
	{
		assert (IsModal());
		if (is_balanced())
		{
			post_journal();
			EndModal(wxID_OK);
		}
		else
		{
			wxMessageBox("Transaction does not balance.");
		}
	}
	return;
}

void
TransactionDialog::post_journal() const
{
	if (m_database_connection)
	{
		OrdinaryJournal journal(*m_database_connection);
		journal.set_whether_actual
		(	m_actual_vs_budget_ctrl->GetSelection() == 0
		);
		size_t const sz = m_account_name_boxes.size();
		assert (sz == m_comment_boxes.size());
		assert (sz == m_amount_boxes.size());
		for (size_t i = 0; i != sz; ++i)
		{
			assert (m_database_connection);
			Account const account
			(	*m_database_connection,
				wx_to_bstring(wxString(m_account_name_boxes[i]->GetLabel()))
			);
			Entry entry(*m_database_connection);
			entry.set_account(account);
			entry.set_comment
			(	wx_to_bstring(m_comment_boxes[i]->GetValue())
			);
			Decimal amount = wx_to_decimal
			(	wxString(m_amount_boxes[i]->GetValue()),
				locale()
			);
			if (!journal.is_actual()) amount = -amount;
			amount = round(amount, account.commodity().precision());
			entry.set_amount(amount);
			entry.set_whether_reconciled(false);
			journal.push_entry(entry);
		}
		assert (journal.is_balanced());
		journal.set_comment("");
		wxDateTime const date_wx = m_date_ctrl->GetValue();
		int year = date_wx.GetYear();
		if (year < 100) year += 2000;
		int const month = static_cast<int>(date_wx.GetMonth()) + 1;
		int const day = date_wx.GetDay();
		journal.set_date(gregorian::date(year, month, day));

		journal.save();

		Frame* const frame = dynamic_cast<Frame*>(GetParent());
		assert (frame);
		frame->update_for_posted_journal(journal);
	}
}

bool
TransactionDialog::is_balanced() const
{
	Decimal balance(0, 0);
	vector<DecimalTextCtrl*>::size_type i = 0;
	vector<DecimalTextCtrl*>::size_type const sz = m_amount_boxes.size();
	for ( ; i != sz; ++i)
	{
		balance += wx_to_decimal(m_amount_boxes[i]->GetValue(), locale());
	}
	return balance == Decimal(0, 0);
}

}  // namespace gui
}  // namespace phatbooks
<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
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.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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 OWNER 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 "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent_info.hpp"
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/magnet_uri.hpp"

int load_file(std::string const& filename, std::vector<char>& v, libtorrent::error_code& ec, int limit = 8000000)
{
	ec.clear();
	FILE* f = fopen(filename.c_str(), "rb");
	if (f == NULL)
	{
		ec.assign(errno, boost::system::get_generic_category());
		return -1;
	}

	int r = fseek(f, 0, SEEK_END);
	if (r != 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}
	long s = ftell(f);
	if (s < 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}

	if (s > limit)
	{
		fclose(f);
		return -2;
	}

	r = fseek(f, 0, SEEK_SET);
	if (r != 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}

	v.resize(s);
	if (s == 0)
	{
		fclose(f);
		return 0;
	}

	r = fread(&v[0], 1, v.size(), f);
	if (r < 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}

	fclose(f);

	if (r != s) return -3;

	return 0;
}

int line_longer_than(libtorrent::lazy_entry const& e, int limit)
{
	using namespace libtorrent;

	int line_len = 0;
	switch (e.type())
	{
	case lazy_entry::list_t:
		line_len += 4;
		if (line_len > limit) return -1;
		for (int i = 0; i < e.list_size(); ++i)
		{
			int ret = line_longer_than(*e.list_at(i), limit - line_len);
			if (ret == -1) return -1;
			line_len += ret + 2;
		}
		break;
	case lazy_entry::dict_t:
		line_len += 4;
		if (line_len > limit) return -1;
		for (int i = 0; i < e.dict_size(); ++i)
		{
			line_len += 4 + e.dict_at(i).first.size();
			if (line_len > limit) return -1;
			int ret = line_longer_than(*e.dict_at(i).second, limit - line_len);
			if (ret == -1) return -1;
			line_len += ret + 1;
		}
		break;
	case lazy_entry::string_t:
		line_len += 3 + e.string_length();
		break;
	case lazy_entry::int_t:
	{
		size_type val = e.int_value();
		while (val > 0)
		{
			++line_len;
			val /= 10;
		}
		line_len += 2;
	}
	break;
	case lazy_entry::none_t:
		line_len += 4;
		break;
	}

	if (line_len > limit) return -1;
	return line_len;
}

std::string print_entry(libtorrent::lazy_entry const& e, bool single_line = false, int indent = 0)
{
	using namespace libtorrent;

	char indent_str[200];
	memset(indent_str, ' ', 200);
	indent_str[0] = ',';
	indent_str[1] = '\n';
	indent_str[199] = 0;
	if (indent < 197 && indent >= 0) indent_str[indent+2] = 0;
	std::string ret;
	switch (e.type())
	{
		case lazy_entry::none_t: return "none";
		case lazy_entry::int_t:
		{
			char str[100];
			snprintf(str, sizeof(str), "%"PRId64, e.int_value());
			return str;
		}
		case lazy_entry::string_t:
		{
			bool printable = true;
			char const* str = e.string_ptr();
			for (int i = 0; i < e.string_length(); ++i)
			{
				using namespace std;
				if (is_print((unsigned char)str[i])) continue;
				printable = false;
				break;
			}
			ret += "'";
			if (printable)
			{
				ret += e.string_value();
				ret += "'";
				return ret;
			}
			for (int i = 0; i < e.string_length(); ++i)
			{
				char tmp[5];
				snprintf(tmp, sizeof(tmp), "%02x", (unsigned char)str[i]);
				ret += tmp;
			}
			ret += "'";
			return ret;
		}
		case lazy_entry::list_t:
		{
			ret += '[';
			bool one_liner = line_longer_than(e, 200) != -1 || single_line;

			if (!one_liner) ret += indent_str + 1;
			for (int i = 0; i < e.list_size(); ++i)
			{
				if (i == 0 && one_liner) ret += " ";
				ret += ::print_entry(*e.list_at(i), single_line, indent + 2);
				if (i < e.list_size() - 1) ret += (one_liner?", ":indent_str);
				else ret += (one_liner?" ":indent_str+1);
			}
			ret += "]";
			return ret;
		}
		case lazy_entry::dict_t:
		{
			ret += "{";
			bool one_liner = line_longer_than(e, 200) != -1 || single_line;

			if (!one_liner) ret += indent_str+1;
			for (int i = 0; i < e.dict_size(); ++i)
			{
				if (i == 0 && one_liner) ret += " ";
				std::pair<std::string, lazy_entry const*> ent = e.dict_at(i);
				ret += "'";
				ret += ent.first;
				ret += "': ";
				ret += ::print_entry(*ent.second, single_line, indent + 2);
				if (i < e.dict_size() - 1) ret += (one_liner?", ":indent_str);
				else ret += (one_liner?" ":indent_str+1);
			}
			ret += "}";
			return ret;
		}
	}
	return ret;
}

int main(int argc, char* argv[])
{
	using namespace libtorrent;

	if (argc < 2 || argc > 4)
	{
		fputs("usage: dump_torrent torrent-file [total-items-limit] [recursion-limit]\n", stderr);
		return 1;
	}

	int item_limit = 1000000;
	int depth_limit = 1000;

	if (argc > 2) item_limit = atoi(argv[2]);
	if (argc > 3) depth_limit = atoi(argv[3]);

	int size = file_size(argv[1]);
	if (size > 40 * 1000000)
	{
		fprintf(stderr, "file too big (%d), aborting\n", size);
		return 1;
	}
	std::vector<char> buf(size);
	error_code ec;
	int ret = load_file(argv[1], buf, ec, 40 * 1000000);
	if (ret != 0)
	{
		fprintf(stderr, "failed to load file: %s\n", ec.message().c_str());
		return 1;
	}
	lazy_entry e;
	int pos;
	printf("decoding. recursion limit: %d total item count limit: %d\n"
		, depth_limit, item_limit);
	ret = lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec, &pos
		, depth_limit, item_limit);

	printf("\n\n----- raw info -----\n\n%s\n", ::print_entry(e).c_str());

	if (ret != 0)
	{
		fprintf(stderr, "failed to decode: '%s' at character: %d\n", ec.message().c_str(), pos);
		return 1;
	}

	torrent_info t(e, ec);
	if (ec)
	{
		fprintf(stderr, "%s\n", ec.message().c_str());
		return 1;
	}
	e.clear();
	std::vector<char>().swap(buf);

	// print info about torrent
	printf("\n\n----- torrent file info -----\n\n"
		"nodes:\n");

	typedef std::vector<std::pair<std::string, int> > node_vec;
	node_vec const& nodes = t.nodes();
	for (node_vec::const_iterator i = nodes.begin(), end(nodes.end());
		i != end; ++i)
	{
		printf("%s: %d\n", i->first.c_str(), i->second);
	}
	puts("trackers:\n");
	for (std::vector<announce_entry>::const_iterator i = t.trackers().begin();
		i != t.trackers().end(); ++i)
	{
		printf("%2d: %s\n", i->tier, i->url.c_str());
	}

	char ih[41];
	to_hex((char const*)&t.info_hash()[0], 20, ih);
	printf("number of pieces: %d\n"
		"piece length: %d\n"
		"info hash: %s\n"
		"comment: %s\n"
		"created by: %s\n"
		"magnet link: %s\n"
		"name: %s\n"
		"number of files: %d\n"
		"files:\n"
		, t.num_pieces()
		, t.piece_length()
		, ih
		, t.comment().c_str()
		, t.creator().c_str()
		, make_magnet_uri(t).c_str()
		, t.name().c_str()
		, t.num_files());
	int index = 0;
	for (torrent_info::file_iterator i = t.begin_files();
		i != t.end_files(); ++i, ++index)
	{
		int first = t.map_file(index, 0, 0).piece;
		int last = t.map_file(index, (std::max)(size_type(i->size)-1, size_type(0)), 0).piece;
		printf(" %8"PRIx64" %11"PRId64" %c%c%c%c [ %5d, %5d ] %7u %s %s %s%s\n"
			, i->offset
			, i->size
			, (i->pad_file?'p':'-')
			, (i->executable_attribute?'x':'-')
			, (i->hidden_attribute?'h':'-')
			, (i->symlink_attribute?'l':'-')
			, first, last
			, boost::uint32_t(t.files().mtime(*i))
			, t.files().hash(*i) != sha1_hash(0) ? to_hex(t.files().hash(*i).to_string()).c_str() : ""
			, t.files().file_path(*i).c_str()
			, i->symlink_attribute ? "-> ": ""
			, i->symlink_attribute && i->symlink_index != -1 ? t.files().symlink(*i).c_str() : "");
	}

	return 0;
}

<commit_msg>make dump_torrent build without deprecated functions<commit_after>/*

Copyright (c) 2003, Arvid Norberg
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.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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 OWNER 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 "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent_info.hpp"
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/magnet_uri.hpp"

int load_file(std::string const& filename, std::vector<char>& v, libtorrent::error_code& ec, int limit = 8000000)
{
	ec.clear();
	FILE* f = fopen(filename.c_str(), "rb");
	if (f == NULL)
	{
		ec.assign(errno, boost::system::get_generic_category());
		return -1;
	}

	int r = fseek(f, 0, SEEK_END);
	if (r != 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}
	long s = ftell(f);
	if (s < 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}

	if (s > limit)
	{
		fclose(f);
		return -2;
	}

	r = fseek(f, 0, SEEK_SET);
	if (r != 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}

	v.resize(s);
	if (s == 0)
	{
		fclose(f);
		return 0;
	}

	r = fread(&v[0], 1, v.size(), f);
	if (r < 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}

	fclose(f);

	if (r != s) return -3;

	return 0;
}

int line_longer_than(libtorrent::lazy_entry const& e, int limit)
{
	using namespace libtorrent;

	int line_len = 0;
	switch (e.type())
	{
	case lazy_entry::list_t:
		line_len += 4;
		if (line_len > limit) return -1;
		for (int i = 0; i < e.list_size(); ++i)
		{
			int ret = line_longer_than(*e.list_at(i), limit - line_len);
			if (ret == -1) return -1;
			line_len += ret + 2;
		}
		break;
	case lazy_entry::dict_t:
		line_len += 4;
		if (line_len > limit) return -1;
		for (int i = 0; i < e.dict_size(); ++i)
		{
			line_len += 4 + e.dict_at(i).first.size();
			if (line_len > limit) return -1;
			int ret = line_longer_than(*e.dict_at(i).second, limit - line_len);
			if (ret == -1) return -1;
			line_len += ret + 1;
		}
		break;
	case lazy_entry::string_t:
		line_len += 3 + e.string_length();
		break;
	case lazy_entry::int_t:
	{
		size_type val = e.int_value();
		while (val > 0)
		{
			++line_len;
			val /= 10;
		}
		line_len += 2;
	}
	break;
	case lazy_entry::none_t:
		line_len += 4;
		break;
	}

	if (line_len > limit) return -1;
	return line_len;
}

std::string print_entry(libtorrent::lazy_entry const& e, bool single_line = false, int indent = 0)
{
	using namespace libtorrent;

	char indent_str[200];
	memset(indent_str, ' ', 200);
	indent_str[0] = ',';
	indent_str[1] = '\n';
	indent_str[199] = 0;
	if (indent < 197 && indent >= 0) indent_str[indent+2] = 0;
	std::string ret;
	switch (e.type())
	{
		case lazy_entry::none_t: return "none";
		case lazy_entry::int_t:
		{
			char str[100];
			snprintf(str, sizeof(str), "%"PRId64, e.int_value());
			return str;
		}
		case lazy_entry::string_t:
		{
			bool printable = true;
			char const* str = e.string_ptr();
			for (int i = 0; i < e.string_length(); ++i)
			{
				using namespace std;
				if (is_print((unsigned char)str[i])) continue;
				printable = false;
				break;
			}
			ret += "'";
			if (printable)
			{
				ret += e.string_value();
				ret += "'";
				return ret;
			}
			for (int i = 0; i < e.string_length(); ++i)
			{
				char tmp[5];
				snprintf(tmp, sizeof(tmp), "%02x", (unsigned char)str[i]);
				ret += tmp;
			}
			ret += "'";
			return ret;
		}
		case lazy_entry::list_t:
		{
			ret += '[';
			bool one_liner = line_longer_than(e, 200) != -1 || single_line;

			if (!one_liner) ret += indent_str + 1;
			for (int i = 0; i < e.list_size(); ++i)
			{
				if (i == 0 && one_liner) ret += " ";
				ret += ::print_entry(*e.list_at(i), single_line, indent + 2);
				if (i < e.list_size() - 1) ret += (one_liner?", ":indent_str);
				else ret += (one_liner?" ":indent_str+1);
			}
			ret += "]";
			return ret;
		}
		case lazy_entry::dict_t:
		{
			ret += "{";
			bool one_liner = line_longer_than(e, 200) != -1 || single_line;

			if (!one_liner) ret += indent_str+1;
			for (int i = 0; i < e.dict_size(); ++i)
			{
				if (i == 0 && one_liner) ret += " ";
				std::pair<std::string, lazy_entry const*> ent = e.dict_at(i);
				ret += "'";
				ret += ent.first;
				ret += "': ";
				ret += ::print_entry(*ent.second, single_line, indent + 2);
				if (i < e.dict_size() - 1) ret += (one_liner?", ":indent_str);
				else ret += (one_liner?" ":indent_str+1);
			}
			ret += "}";
			return ret;
		}
	}
	return ret;
}

int main(int argc, char* argv[])
{
	using namespace libtorrent;

	if (argc < 2 || argc > 4)
	{
		fputs("usage: dump_torrent torrent-file [total-items-limit] [recursion-limit]\n", stderr);
		return 1;
	}

	int item_limit = 1000000;
	int depth_limit = 1000;

	if (argc > 2) item_limit = atoi(argv[2]);
	if (argc > 3) depth_limit = atoi(argv[3]);

	int size = file_size(argv[1]);
	if (size > 40 * 1000000)
	{
		fprintf(stderr, "file too big (%d), aborting\n", size);
		return 1;
	}
	std::vector<char> buf(size);
	error_code ec;
	int ret = load_file(argv[1], buf, ec, 40 * 1000000);
	if (ret != 0)
	{
		fprintf(stderr, "failed to load file: %s\n", ec.message().c_str());
		return 1;
	}
	lazy_entry e;
	int pos;
	printf("decoding. recursion limit: %d total item count limit: %d\n"
		, depth_limit, item_limit);
	ret = lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec, &pos
		, depth_limit, item_limit);

	printf("\n\n----- raw info -----\n\n%s\n", ::print_entry(e).c_str());

	if (ret != 0)
	{
		fprintf(stderr, "failed to decode: '%s' at character: %d\n", ec.message().c_str(), pos);
		return 1;
	}

	torrent_info t(e, ec);
	if (ec)
	{
		fprintf(stderr, "%s\n", ec.message().c_str());
		return 1;
	}
	e.clear();
	std::vector<char>().swap(buf);

	// print info about torrent
	printf("\n\n----- torrent file info -----\n\n"
		"nodes:\n");

	typedef std::vector<std::pair<std::string, int> > node_vec;
	node_vec const& nodes = t.nodes();
	for (node_vec::const_iterator i = nodes.begin(), end(nodes.end());
		i != end; ++i)
	{
		printf("%s: %d\n", i->first.c_str(), i->second);
	}
	puts("trackers:\n");
	for (std::vector<announce_entry>::const_iterator i = t.trackers().begin();
		i != t.trackers().end(); ++i)
	{
		printf("%2d: %s\n", i->tier, i->url.c_str());
	}

	char ih[41];
	to_hex((char const*)&t.info_hash()[0], 20, ih);
	printf("number of pieces: %d\n"
		"piece length: %d\n"
		"info hash: %s\n"
		"comment: %s\n"
		"created by: %s\n"
		"magnet link: %s\n"
		"name: %s\n"
		"number of files: %d\n"
		"files:\n"
		, t.num_pieces()
		, t.piece_length()
		, ih
		, t.comment().c_str()
		, t.creator().c_str()
		, make_magnet_uri(t).c_str()
		, t.name().c_str()
		, t.num_files());
	file_storage const& st = t.files();
	for (int i = 0; i < st.num_files(); ++i)
	{
		int first = st.map_file(i, 0, 0).piece;
		int last = st.map_file(i, (std::max)(size_type(st.file_size(i))-1, size_type(0)), 0).piece;
		int flags = st.file_flags(i);
		printf(" %8" PRIx64 " %11" PRId64 " %c%c%c%c [ %5d, %5d ] %7u %s %s %s%s\n"
			, st.file_offset(i)
			, st.file_size(i)
			, ((flags & file_storage::flag_pad_file)?'p':'-')
			, ((flags & file_storage::flag_executable)?'x':'-')
			, ((flags & file_storage::flag_hidden)?'h':'-')
			, ((flags & file_storage::flag_symlink)?'l':'-')
			, first, last
			, boost::uint32_t(st.mtime(i))
			, st.hash(i) != sha1_hash(0) ? to_hex(st.hash(i).to_string()).c_str() : ""
			, st.file_path(i).c_str()
			, (flags & file_storage::flag_symlink) ? "-> " : ""
			, (flags & file_storage::flag_symlink) ? st.symlink(i).c_str() : "");
	}

	return 0;
}

<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
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.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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 OWNER 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 <iostream>
#include <fstream>
#include <iterator>
#include <iomanip>

#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent_info.hpp"
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/magnet_uri.hpp"

int main(int argc, char* argv[])
{
	using namespace libtorrent;

	if (argc != 2)
	{
		std::cerr << "usage: dump_torrent torrent-file\n";
		return 1;
	}

	int size = file_size(argv[1]);
	if (size > 10 * 1000000)
	{
		std::cerr << "file too big (" << size << "), aborting\n";
		return 1;
	}
	std::vector<char> buf(size);
	std::ifstream(argv[1], std::ios_base::binary).read(&buf[0], size);
	lazy_entry e;
	int ret = lazy_bdecode(&buf[0], &buf[0] + buf.size(), e);

	if (ret != 0)
	{
		std::cerr << "invalid bencoding: " << ret << std::endl;
		return 1;
	}

	std::cout << "\n\n----- raw info -----\n\n";
	std::cout << print_entry(e) << std::endl;

	error_code ec;
	torrent_info t(e, ec);
	if (ec)
	{
		std::cout << ec.message() << std::endl;
		return 1;
	}

	// print info about torrent
	std::cout << "\n\n----- torrent file info -----\n\n";
	std::cout << "nodes:\n";
	typedef std::vector<std::pair<std::string, int> > node_vec;
	node_vec const& nodes = t.nodes();
	for (node_vec::const_iterator i = nodes.begin(), end(nodes.end());
		i != end; ++i)
	{
		std::cout << i->first << ":" << i->second << "\n";
	}
	std::cout << "trackers:\n";
	for (std::vector<announce_entry>::const_iterator i = t.trackers().begin();
		i != t.trackers().end(); ++i)
	{
		std::cout << i->tier << ": " << i->url << "\n";
	}

	std::cout << "number of pieces: " << t.num_pieces() << "\n";
	std::cout << "piece length: " << t.piece_length() << "\n";
	char ih[41];
	to_hex((char const*)&t.info_hash()[0], 20, ih);
	std::cout << "info hash: " << ih << "\n";
	std::cout << "comment: " << t.comment() << "\n";
	std::cout << "created by: " << t.creator() << "\n";
	std::cout << "magnet link: " << make_magnet_uri(t) << "\n";
	std::cout << "name: " << t.name() << "\n";
	std::cout << "files:\n";
	int index = 0;
	for (torrent_info::file_iterator i = t.begin_files();
		i != t.end_files(); ++i, ++index)
	{
		int first = t.map_file(index, 0, 0).piece;
		int last = t.map_file(index, (std::max)(i->size-1, size_type(0)), 0).piece;
		std::cout << "  " << std::setw(11) << i->size
			<< " "
			<< (i->pad_file?'p':'-')
			<< (i->executable_attribute?'x':'-')
			<< (i->hidden_attribute?'h':'-')
			<< (i->symlink_attribute?'l':'-')
			<< " "
			<< "[ " << std::setw(4) << first << ", " << std::setw(4) << last << " ]\t"
			<< i->path;
		if (i->symlink_attribute)
			std::cout << " -> " << i->symlink_path;
		std::cout << std::endl;
	}

	return 0;
}

<commit_msg>replaced iostream in dump_torrent example<commit_after>/*

Copyright (c) 2003, Arvid Norberg
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.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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 OWNER 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 "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent_info.hpp"
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/magnet_uri.hpp"

int main(int argc, char* argv[])
{
	using namespace libtorrent;

	if (argc != 2)
	{
		fputs("usage: dump_torrent torrent-file\n", stderr);
		return 1;
	}

	int size = file_size(argv[1]);
	if (size > 10 * 1000000)
	{
		fprintf(stderr, "file too big (%d), aborting\n", size);
		return 1;
	}
	std::vector<char> buf(size);
	int ret = load_file(argv[1], buf);
	if (ret != 0)
	{
		fprintf(stderr, "failed to load file: %d\n", ret);
		return 1;
	}
	lazy_entry e;
	ret = lazy_bdecode(&buf[0], &buf[0] + buf.size(), e);

	if (ret != 0)
	{
		fprintf(stderr, "invalid bencoding: %d\n", ret);
		return 1;
	}

	printf("\n\n----- raw info -----\n\n%s\n", print_entry(e).c_str());

	error_code ec;
	torrent_info t(e, ec);
	if (ec)
	{
		fprintf(stderr, "%s\n", ec.message().c_str());
		return 1;
	}

	// print info about torrent
	printf("\n\n----- torrent file info -----\n\n"
		"nodes:\n");

	typedef std::vector<std::pair<std::string, int> > node_vec;
	node_vec const& nodes = t.nodes();
	for (node_vec::const_iterator i = nodes.begin(), end(nodes.end());
		i != end; ++i)
	{
		printf("%s: %d\n", i->first.c_str(), i->second);
	}
	puts("trackers:\n");
	for (std::vector<announce_entry>::const_iterator i = t.trackers().begin();
		i != t.trackers().end(); ++i)
	{
		printf("%2d: %s\n", i->tier, i->url.c_str());
	}

	char ih[41];
	to_hex((char const*)&t.info_hash()[0], 20, ih);
	printf("number of pieces: %d\n"
		"piece length: %d\n"
		"info hash: %s\n"
		"comment: %s\n"
		"created by: %s\n"
		"magnet link: %s\n"
		"name: %s\n"
		"files:\n"
		, t.num_pieces()
		, t.piece_length()
		, ih
		, t.comment().c_str()
		, t.creator().c_str()
		, make_magnet_uri(t).c_str()
		, t.name().c_str());
	int index = 0;
	for (torrent_info::file_iterator i = t.begin_files();
		i != t.end_files(); ++i, ++index)
	{
		int first = t.map_file(index, 0, 0).piece;
		int last = t.map_file(index, (std::max)(i->size-1, size_type(0)), 0).piece;
		printf("  %11"PRId64" %c%c%c%c [ %4d, %4d ] %s %s%s\n"
			, i->size
			, (i->pad_file?'p':'-')
			, (i->executable_attribute?'x':'-')
			, (i->hidden_attribute?'h':'-')
			, (i->symlink_attribute?'l':'-')
			, first, last, i->path.c_str()
			, i->symlink_attribute ? "-> ": ""
			, i->symlink_attribute ? i->symlink_path.c_str() : "");
	}

	return 0;
}

<|endoftext|>