<commit_before>#ifndef __MODEL_HPP_INCLUDED
#define __MODEL_HPP_INCLUDED

// Include GLEW
#ifndef __GL_GLEW_H_INCLUDED
#define __GL_GLEW_H_INCLUDED
#include <GL/glew.h>
#endif

// Include GLFW
#ifndef __GLFW3_H_INCLUDED
#define __GLFW3_H_INCLUDED
#include <glfw3.h>
#endif

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp>
#endif

#include <iostream>
#include <queue> // std::queue
#include <string.h>
#include "globals.hpp"
#include "shader.hpp"
#include "heightmap_loader.hpp"
#include "objloader.hpp"

namespace model
{
    class World
    {
        friend class Shader;
        friend class Species;

        public:
            // constructor.
            World();

            // destructor.
            ~World();

            // this method renders the entire world, one shader at a time.
            void render();

        protected:
            // this method sets a shader pointer.
            void set_shader_pointer(GLuint shaderID, void* shader_pointer);

            // this method gets a shader pointer.
            void* get_shader_pointer(GLuint shaderID);

            // this method gets a shader ID and removes it from the `free_shaderID_queue` if it was popped from the queue.
            GLuint get_shaderID();

            // this method sets a world species pointer.
            void set_world_species_pointer(void* world_species_pointer);

        private:
            void compute_matrices_from_inputs();

            void* world_species_pointer;              // pointer to world species (used in collision detection).

            std::vector<void*> shader_pointer_vector;
            std::queue<GLuint> free_shaderID_queue;
    };

    class Shader
    {
        friend class World;
        friend class Texture;
        friend class Species;
        friend class Object;

        public:
            // constructor.
            Shader(ShaderStruct shader_struct);

            // destructor.
            ~Shader();

        protected:
            // this method renders all textures using this shader.
            void render();

            // this method sets a texture pointer.
            void set_texture_pointer(GLuint textureID, void* texture_pointer);

            // this method gets a texture pointer.
            void* get_texture_pointer(GLuint textureID);

            // this method gets a texture ID and removes it from the `free_textureID_queue` if it was popped from the queue.
            GLuint get_textureID();

            // this method sets pointer to this shader to NULL, sets `world_pointer` according to the input, and requests a new `shaderID` from the new world.
            void switch_to_new_world(model::World *new_world_pointer);

            // this method sets a world species pointer.
            void set_world_species_pointer(void* world_species_pointer);

            model::World *world_pointer;          // pointer to the world.

            GLuint programID;                     // shaders' programID, returned by `LoadShaders`.

            GLuint MatrixID;
            GLuint ViewMatrixID;
            GLuint ModelMatrixID;

        private:
            void bind_to_world();

            void* world_species_pointer;          // pointer to world species (used in collision detection).

            GLuint shaderID;                      // shader ID, returned by `model::World->get_shaderID()`.

            std::string vertex_shader;            // filename of vertex shader.
            std::string fragment_shader;          // filename of fragment shader.

            std::vector<void*> texture_pointer_vector;
            std::queue<GLuint> free_textureID_queue;

            const char *char_vertex_shader;
            const char *char_fragment_shader;
    };

    class Texture
    {
        friend class Shader;
        friend class Species;
        friend class Object;

        public:
            // constructor.
            Texture(TextureStruct texture_struct);

            // destructor.
            ~Texture();

        protected:
            // this method renders all species using this texture.
            void render();

            // this method sets a species pointer.
            void set_species_pointer(GLuint speciesID, void* species_pointer);

            // this method gets a species pointer.
            void* get_species_pointer(GLuint speciesID);

            // this method gets a species ID and removes it from the `free_speciesID_queue` if it was popped from the queue.
            GLuint get_speciesID();

            // this method sets pointer to this shader to NULL, sets `shader_pointer` according to the input, and requests a new `textureID` from the new shader.
            void switch_to_new_shader(model::Shader *new_world_pointer);

            // this method sets a world species pointer.
            void set_world_species_pointer(void* world_species_pointer);

            model::Shader *shader_pointer;         // pointer to the shader.

        private:
            void bind_to_shader();

            void* world_species_pointer;           // pointer to world species (used in collision detection).

            GLuint texture;                        // Texture, returned by `load_DDS_texture` or `load_BMP_texture`.
            GLuint openGL_textureID;               // texture ID, returned by `glGetUniformLocation(programID, "myTextureSampler");`.

            std::vector<void*> species_pointer_vector;
            std::queue<GLuint> free_speciesID_queue;

            std::string texture_file_format;       // type of the model file, eg. `"bmp"`.
            std::string texture_filename;          // filename of the model file.
            GLuint textureID;                      // texture ID, returned by `Shader::get_textureID`.
            const char *char_texture_file_format;
            const char *char_texture_filename;
    };

    class Graph
    {
        friend class Node;

        public:
            // constructor.
            Graph();

            // destructor.
            ~Graph();

        protected:
            // this method sets a node pointer.
            void set_node_pointer(GLuint nodeID, void* node_pointer);

            // this method gets a node pointer.
            void* get_node_pointer(GLuint nodeID);

            // this method gets a node ID and removes it from the `free_nodeID_queue` if it was popped from the queue.
            GLuint get_nodeID();

        private:
            std::vector<void*> node_pointer_vector;
            std::queue<GLuint> free_nodeID_queue;
    };

    // `Node` is not a subclass of `Graph` because if the graph splits, node may be transferred to an another graph.
    // Transferring a node to a new graph naturally requires appropriate reindexing of `nodeID`s.
    // The graph in which a node belongs is accessible through `void* graph_pointer` (must be cast to `model::Graph*`).
    class Node
    {
        public:
            // constructor.
            Node(NodeStruct node_struct);

            // destructor.
            ~Node();

            // this method creates a bidirectional link.
            // creating of bidirectional links is not possible before all nodes are created.
            void create_bidirectional_link(GLuint nodeID);

            // this method deletes a bidirectional link.
            // deleting of links is not possible before all nodes are created.
            void delete_bidirectional_link(GLuint nodeID);

            // this method transfers this node to a new graph.
            // links will not be changed.
            // all nodes that are to be transferred must be transferred separately.
            // before transfering any node to a new graph,
            // all links to nodes that do not belong to the new graph of this node must be deleted with separate `delete_bidirectional_link` calls.
            void transfer_to_new_graph(model::Graph *new_graph_pointer);

            GLuint nodeID;
            model::Graph *graph_pointer;

        private:
            // nodes do not keep pointers to neighbor nodes, because all pointer values are not known yet before all nodes are created.
            std::vector<GLuint> neighbor_nodeIDs;

            // this method creates an unidirectional link.
            // in the constructor only unidirectional links can be created.
            void create_unidirectional_link(GLuint nodeID);

            // this method deletes an unidirectional link.
            void delete_unidirectional_link(GLuint nodeID);

            glm::vec3 coordinate_vector;
    };

    class Species
    {
        public:
            // constructor.
            Species(SpeciesStruct species_struct);

            // destructor.
            ~Species();

            // this method renders all objects of this species.
            void render();

            // this method sets a object pointer.
            void set_object_pointer(GLuint objectID, void* object_pointer);

            // this method gets a object pointer.
            void* get_object_pointer(GLuint objectID);

            // this method gets a object ID and removes it from the `free_objectID_queue` if it was popped from the queue.
            GLuint get_objectID();

            // this method sets pointer to this species to NULL, sets `texture_pointer` according to the input, and requests a new `speciesID` from the new texture.
            void switch_to_new_texture(model::Texture *new_texture_pointer);

            bool is_world;                           // worlds currently do not rotate nor translate.

            std::string color_channel;               // color channel in use: `"red"`, `"green"`, `"blue"`, `"mean"` or `"all"`.
            std::vector<ObjectStruct> object_vector; // vector of individual objects of this species.
            glm::vec3 lightPos;                      // light position.

            // The rest fields are created in the constructor.
            GLuint image_width;
            GLuint image_height;

            GLuint vertexPosition_modelspaceID;
            GLuint vertexUVID;
            GLuint vertexNormal_modelspaceID;

            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object.

            std::vector<GLuint> indices;           // the deleted vertices will be reused (though it is not required, if there's enough memory).
            std::vector<glm::vec3> indexed_vertices;
            std::vector<glm::vec2> indexed_UVs;
            std::vector<glm::vec3> indexed_normals;

            GLuint vertexbuffer;
            GLuint uvbuffer;
            GLuint normalbuffer;
            GLuint elementbuffer;

            model::Texture *texture_pointer;       // pointer to the texture.

        private:
            void bind_to_texture();

            std::string model_file_format;         // type of the model file, eg. `"bmp"`.
            std::string model_filename;            // filename of the model file.
            GLuint speciesID;                      // species ID, returned by `model::Texture->get_speciesID()`.
            GLuint lightID;                        // light ID, returned by `glGetUniformLocation(programID, "LightPosition_worldspace");`.
            const char *char_model_file_format;
            const char *char_model_filename;
            const char *char_color_channel;

            std::vector<void*> object_pointer_vector;
            std::queue<GLuint> free_objectID_queue;
    };

    class Font
    {
        public:
            // constructor.
            Font(FontStruct font_struct);

            // destructor.
            ~Font();

            // this method renders all objects of this species.
            void render();

            // this method sets a glyph pointer.
            void set_glyph_pointer(GLuint objectID, void* object_pointer);

            // this method gets a glyph pointer.
            void* get_glyph_pointer(GLuint objectID);

            // this method gets a object ID and removes it from the `free_objectID_queue` if it was popped from the queue.
            GLuint get_glyphID();

            // this method sets pointer to this species to NULL, sets `texture_pointer` according to the input, and requests a new `speciesID` from the new texture.
            void switch_to_new_texture(model::Texture *new_texture_pointer);

            std::vector<ObjectStruct> object_vector; // vector of individual objects of this species.
            glm::vec3 lightPos;                      // light position.

            // The rest fields are created in the constructor.
            GLuint image_width;
            GLuint image_height;

            model::Texture *texture_pointer;       // pointer to the texture.

        private:
            void bind_to_texture();

            std::string model_file_format;         // type of the model file, eg. `"bmp"`.
            std::string model_filename;            // filename of the model file.
            GLuint speciesID;                      // species ID, returned by `model::Texture->get_speciesID()`.
            GLuint lightID;                        // light ID, returned by `glGetUniformLocation(programID, "LightPosition_worldspace");`.
            const char *char_model_file_format;
            const char *char_model_filename;
            const char *char_color_channel;

            std::vector<void*> object_pointer_vector;
            std::queue<GLuint> free_objectID_queue;
    };

    class Glyph
    {
        public:
            // constructor.
            Glyph(GlyphStruct glyph_struct);

            // destructor.
            ~Glyph();

            // this method renders all objects of this species.
            void render();

            // this method sets a object pointer.
            void set_object_pointer(GLuint objectID, void* object_pointer);

            // this method gets a object pointer.
            void* get_object_pointer(GLuint objectID);

            // this method gets a object ID and removes it from the `free_objectID_queue` if it was popped from the queue.
            GLuint get_objectID();

            // The rest fields are created in the constructor.
            GLuint image_width;
            GLuint image_height;

            GLuint vertexPosition_modelspaceID;
            GLuint vertexUVID;
            GLuint vertexNormal_modelspaceID;

            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object.

            std::vector<GLuint> indices;           // the deleted vertices will be reused (though it is not required, if there's enough memory).
            std::vector<glm::vec3> indexed_vertices;
            std::vector<glm::vec2> indexed_UVs;
            std::vector<glm::vec3> indexed_normals;

            GLuint vertexbuffer;
            GLuint uvbuffer;
            GLuint normalbuffer;
            GLuint elementbuffer;

            model::Font *font_pointer;             // pointer to the font.

        private:
            void bind_to_font();

            GLuint glyphID;                        // glyph ID, returned by `model::Font->get_glyphID()`.
            GLuint lightID;                        // light ID, returned by `glGetUniformLocation(programID, "LightPosition_worldspace");`.

            std::vector<void*> object_pointer_vector;
            std::queue<GLuint> free_objectID_queue;
    };

    class Object
    {
        public:
            // constructor.
            Object(ObjectStruct object_struct);

            // destructor.
            ~Object();

            // this method renders this object.
            void render();

            // this method sets pointer to this object to NULL, sets `species_pointer` according to the input, and requests a new `objectID` from the new species.
            void switch_to_new_species(model::Species *new_species_pointer);

        private:
            void bind_to_species();

            model::Species *species_pointer;       // pointer to the species.

            GLuint objectID;                       // object ID, returned by `model::Species->get_objectID()`.
            bool has_entered;

            glm::vec3 coordinate_vector;           // coordinate vector.
            glm::vec3 original_scale_vector;       // original scale vector.
            GLfloat rotate_angle;                  // rotate angle.
            glm::vec3 rotate_vector;               // rotate vector.
            glm::vec3 translate_vector;            // translate vector.

            // The rest fields are created in the constructor.
            glm::mat4 model_matrix;                // model matrix.
            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object. not used at the moment.

            glm::mat4 MVP_matrix;                  // model view projection matrix.
    };
}

#endif
<commit_msg>`namespace model`: `protected:` -> `private:`.<commit_after>#ifndef __MODEL_HPP_INCLUDED
#define __MODEL_HPP_INCLUDED

// Include GLEW
#ifndef __GL_GLEW_H_INCLUDED
#define __GL_GLEW_H_INCLUDED
#include <GL/glew.h>
#endif

// Include GLFW
#ifndef __GLFW3_H_INCLUDED
#define __GLFW3_H_INCLUDED
#include <glfw3.h>
#endif

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp>
#endif

#include <iostream>
#include <queue> // std::queue
#include <string.h>
#include "globals.hpp"
#include "shader.hpp"
#include "heightmap_loader.hpp"
#include "objloader.hpp"

namespace model
{
    class World
    {
        friend class Shader;
        friend class Species;

        public:
            // constructor.
            World();

            // destructor.
            ~World();

            // this method renders the entire world, one shader at a time.
            void render();

        private:
            // this method sets a shader pointer.
            void set_shader_pointer(GLuint shaderID, void* shader_pointer);

            // this method gets a shader pointer.
            void* get_shader_pointer(GLuint shaderID);

            // this method gets a shader ID and removes it from the `free_shaderID_queue` if it was popped from the queue.
            GLuint get_shaderID();

            // this method sets a world species pointer.
            void set_world_species_pointer(void* world_species_pointer);

            void compute_matrices_from_inputs();

            void* world_species_pointer;              // pointer to world species (used in collision detection).

            std::vector<void*> shader_pointer_vector;
            std::queue<GLuint> free_shaderID_queue;
    };

    class Shader
    {
        friend class World;
        friend class Texture;
        friend class Species;
        friend class Object;

        public:
            // constructor.
            Shader(ShaderStruct shader_struct);

            // destructor.
            ~Shader();

        private:
            // this method renders all textures using this shader.
            void render();

            // this method sets a texture pointer.
            void set_texture_pointer(GLuint textureID, void* texture_pointer);

            // this method gets a texture pointer.
            void* get_texture_pointer(GLuint textureID);

            // this method gets a texture ID and removes it from the `free_textureID_queue` if it was popped from the queue.
            GLuint get_textureID();

            // this method sets pointer to this shader to NULL, sets `world_pointer` according to the input, and requests a new `shaderID` from the new world.
            void switch_to_new_world(model::World *new_world_pointer);

            // this method sets a world species pointer.
            void set_world_species_pointer(void* world_species_pointer);

            model::World *world_pointer;          // pointer to the world.

            GLuint programID;                     // shaders' programID, returned by `LoadShaders`.

            GLuint MatrixID;
            GLuint ViewMatrixID;
            GLuint ModelMatrixID;

            void bind_to_world();

            void* world_species_pointer;          // pointer to world species (used in collision detection).

            GLuint shaderID;                      // shader ID, returned by `model::World->get_shaderID()`.

            std::string vertex_shader;            // filename of vertex shader.
            std::string fragment_shader;          // filename of fragment shader.

            std::vector<void*> texture_pointer_vector;
            std::queue<GLuint> free_textureID_queue;

            const char *char_vertex_shader;
            const char *char_fragment_shader;
    };

    class Texture
    {
        friend class Shader;
        friend class Species;
        friend class Object;

        public:
            // constructor.
            Texture(TextureStruct texture_struct);

            // destructor.
            ~Texture();

        private:
            // this method renders all species using this texture.
            void render();

            // this method sets a species pointer.
            void set_species_pointer(GLuint speciesID, void* species_pointer);

            // this method gets a species pointer.
            void* get_species_pointer(GLuint speciesID);

            // this method gets a species ID and removes it from the `free_speciesID_queue` if it was popped from the queue.
            GLuint get_speciesID();

            // this method sets pointer to this shader to NULL, sets `shader_pointer` according to the input, and requests a new `textureID` from the new shader.
            void switch_to_new_shader(model::Shader *new_world_pointer);

            // this method sets a world species pointer.
            void set_world_species_pointer(void* world_species_pointer);

            model::Shader *shader_pointer;         // pointer to the shader.

            void bind_to_shader();

            void* world_species_pointer;           // pointer to world species (used in collision detection).

            GLuint texture;                        // Texture, returned by `load_DDS_texture` or `load_BMP_texture`.
            GLuint openGL_textureID;               // texture ID, returned by `glGetUniformLocation(programID, "myTextureSampler");`.

            std::vector<void*> species_pointer_vector;
            std::queue<GLuint> free_speciesID_queue;

            std::string texture_file_format;       // type of the model file, eg. `"bmp"`.
            std::string texture_filename;          // filename of the model file.
            GLuint textureID;                      // texture ID, returned by `Shader::get_textureID`.
            const char *char_texture_file_format;
            const char *char_texture_filename;
    };

    class Graph
    {
        friend class Node;

        public:
            // constructor.
            Graph();

            // destructor.
            ~Graph();

        private:
            // this method sets a node pointer.
            void set_node_pointer(GLuint nodeID, void* node_pointer);

            // this method gets a node pointer.
            void* get_node_pointer(GLuint nodeID);

            // this method gets a node ID and removes it from the `free_nodeID_queue` if it was popped from the queue.
            GLuint get_nodeID();

            std::vector<void*> node_pointer_vector;
            std::queue<GLuint> free_nodeID_queue;
    };

    // `Node` is not a subclass of `Graph` because if the graph splits, node may be transferred to an another graph.
    // Transferring a node to a new graph naturally requires appropriate reindexing of `nodeID`s.
    // The graph in which a node belongs is accessible through `void* graph_pointer` (must be cast to `model::Graph*`).
    class Node
    {
        public:
            // constructor.
            Node(NodeStruct node_struct);

            // destructor.
            ~Node();

            // this method creates a bidirectional link.
            // creating of bidirectional links is not possible before all nodes are created.
            void create_bidirectional_link(GLuint nodeID);

            // this method deletes a bidirectional link.
            // deleting of links is not possible before all nodes are created.
            void delete_bidirectional_link(GLuint nodeID);

            // this method transfers this node to a new graph.
            // links will not be changed.
            // all nodes that are to be transferred must be transferred separately.
            // before transfering any node to a new graph,
            // all links to nodes that do not belong to the new graph of this node must be deleted with separate `delete_bidirectional_link` calls.
            void transfer_to_new_graph(model::Graph *new_graph_pointer);

            GLuint nodeID;
            model::Graph *graph_pointer;

        private:
            // nodes do not keep pointers to neighbor nodes, because all pointer values are not known yet before all nodes are created.
            std::vector<GLuint> neighbor_nodeIDs;

            // this method creates an unidirectional link.
            // in the constructor only unidirectional links can be created.
            void create_unidirectional_link(GLuint nodeID);

            // this method deletes an unidirectional link.
            void delete_unidirectional_link(GLuint nodeID);

            glm::vec3 coordinate_vector;
    };

    class Species
    {
        public:
            // constructor.
            Species(SpeciesStruct species_struct);

            // destructor.
            ~Species();

            // this method renders all objects of this species.
            void render();

            // this method sets a object pointer.
            void set_object_pointer(GLuint objectID, void* object_pointer);

            // this method gets a object pointer.
            void* get_object_pointer(GLuint objectID);

            // this method gets a object ID and removes it from the `free_objectID_queue` if it was popped from the queue.
            GLuint get_objectID();

            // this method sets pointer to this species to NULL, sets `texture_pointer` according to the input, and requests a new `speciesID` from the new texture.
            void switch_to_new_texture(model::Texture *new_texture_pointer);

            bool is_world;                           // worlds currently do not rotate nor translate.

            std::string color_channel;               // color channel in use: `"red"`, `"green"`, `"blue"`, `"mean"` or `"all"`.
            std::vector<ObjectStruct> object_vector; // vector of individual objects of this species.
            glm::vec3 lightPos;                      // light position.

            // The rest fields are created in the constructor.
            GLuint image_width;
            GLuint image_height;

            GLuint vertexPosition_modelspaceID;
            GLuint vertexUVID;
            GLuint vertexNormal_modelspaceID;

            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object.

            std::vector<GLuint> indices;           // the deleted vertices will be reused (though it is not required, if there's enough memory).
            std::vector<glm::vec3> indexed_vertices;
            std::vector<glm::vec2> indexed_UVs;
            std::vector<glm::vec3> indexed_normals;

            GLuint vertexbuffer;
            GLuint uvbuffer;
            GLuint normalbuffer;
            GLuint elementbuffer;

            model::Texture *texture_pointer;       // pointer to the texture.

        private:
            void bind_to_texture();

            std::string model_file_format;         // type of the model file, eg. `"bmp"`.
            std::string model_filename;            // filename of the model file.
            GLuint speciesID;                      // species ID, returned by `model::Texture->get_speciesID()`.
            GLuint lightID;                        // light ID, returned by `glGetUniformLocation(programID, "LightPosition_worldspace");`.
            const char *char_model_file_format;
            const char *char_model_filename;
            const char *char_color_channel;

            std::vector<void*> object_pointer_vector;
            std::queue<GLuint> free_objectID_queue;
    };

    class Font
    {
        public:
            // constructor.
            Font(FontStruct font_struct);

            // destructor.
            ~Font();

            // this method renders all objects of this species.
            void render();

            // this method sets a glyph pointer.
            void set_glyph_pointer(GLuint objectID, void* object_pointer);

            // this method gets a glyph pointer.
            void* get_glyph_pointer(GLuint objectID);

            // this method gets a object ID and removes it from the `free_objectID_queue` if it was popped from the queue.
            GLuint get_glyphID();

            // this method sets pointer to this species to NULL, sets `texture_pointer` according to the input, and requests a new `speciesID` from the new texture.
            void switch_to_new_texture(model::Texture *new_texture_pointer);

            std::vector<ObjectStruct> object_vector; // vector of individual objects of this species.
            glm::vec3 lightPos;                      // light position.

            // The rest fields are created in the constructor.
            GLuint image_width;
            GLuint image_height;

            model::Texture *texture_pointer;       // pointer to the texture.

        private:
            void bind_to_texture();

            std::string model_file_format;         // type of the model file, eg. `"bmp"`.
            std::string model_filename;            // filename of the model file.
            GLuint speciesID;                      // species ID, returned by `model::Texture->get_speciesID()`.
            GLuint lightID;                        // light ID, returned by `glGetUniformLocation(programID, "LightPosition_worldspace");`.
            const char *char_model_file_format;
            const char *char_model_filename;
            const char *char_color_channel;

            std::vector<void*> object_pointer_vector;
            std::queue<GLuint> free_objectID_queue;
    };

    class Glyph
    {
        public:
            // constructor.
            Glyph(GlyphStruct glyph_struct);

            // destructor.
            ~Glyph();

            // this method renders all objects of this species.
            void render();

            // this method sets a object pointer.
            void set_object_pointer(GLuint objectID, void* object_pointer);

            // this method gets a object pointer.
            void* get_object_pointer(GLuint objectID);

            // this method gets a object ID and removes it from the `free_objectID_queue` if it was popped from the queue.
            GLuint get_objectID();

            // The rest fields are created in the constructor.
            GLuint image_width;
            GLuint image_height;

            GLuint vertexPosition_modelspaceID;
            GLuint vertexUVID;
            GLuint vertexNormal_modelspaceID;

            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object.

            std::vector<GLuint> indices;           // the deleted vertices will be reused (though it is not required, if there's enough memory).
            std::vector<glm::vec3> indexed_vertices;
            std::vector<glm::vec2> indexed_UVs;
            std::vector<glm::vec3> indexed_normals;

            GLuint vertexbuffer;
            GLuint uvbuffer;
            GLuint normalbuffer;
            GLuint elementbuffer;

            model::Font *font_pointer;             // pointer to the font.

        private:
            void bind_to_font();

            GLuint glyphID;                        // glyph ID, returned by `model::Font->get_glyphID()`.
            GLuint lightID;                        // light ID, returned by `glGetUniformLocation(programID, "LightPosition_worldspace");`.

            std::vector<void*> object_pointer_vector;
            std::queue<GLuint> free_objectID_queue;
    };

    class Object
    {
        public:
            // constructor.
            Object(ObjectStruct object_struct);

            // destructor.
            ~Object();

            // this method renders this object.
            void render();

            // this method sets pointer to this object to NULL, sets `species_pointer` according to the input, and requests a new `objectID` from the new species.
            void switch_to_new_species(model::Species *new_species_pointer);

        private:
            void bind_to_species();

            model::Species *species_pointer;       // pointer to the species.

            GLuint objectID;                       // object ID, returned by `model::Species->get_objectID()`.
            bool has_entered;

            glm::vec3 coordinate_vector;           // coordinate vector.
            glm::vec3 original_scale_vector;       // original scale vector.
            GLfloat rotate_angle;                  // rotate angle.
            glm::vec3 rotate_vector;               // rotate vector.
            glm::vec3 translate_vector;            // translate vector.

            // The rest fields are created in the constructor.
            glm::mat4 model_matrix;                // model matrix.
            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object. not used at the moment.

            glm::mat4 MVP_matrix;                  // model view projection matrix.
    };
}

#endif
<|endoftext|>


<commit_before>#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<iomanip>
using namespace std;

#define ll long long
#define mem(Arr,x) memset(Arr,x,sizeof(Arr))
#define Find(Arr,size,x) (lower_bound(&Arr[1],&Arr[size+1],x)-Arr)

const int maxN=2010;
const int maxNode=maxN*20;
const int maxM=maxNode*4;
const int inf=2147483647;

class Point
{
public:
	int x,y,id;
};

int n,Sx,Sy,Tx,Ty,S,T;
int A[maxN],B[maxN],C[maxN],D[maxN];
int nx,Nx[maxNode],ny,Ny[maxNode];
int edgecnt=0,Head[maxNode],Next[maxM],V[maxM],W[maxM];
int stu[maxN][maxN],Id[maxN][maxN],pcnt;
Point P[maxNode];
bool Exi[maxN],inq[maxNode];
int Dist[maxNode];
queue<int> Q;

void Go(int x,int y,int dx,int dy);
bool cmpx(Point P1,Point P2);
bool cmpy(Point P1,Point P2);
void Add_Edge(int u,int v,int w);
void Spfa();

int main(){
	int TTT;scanf("%d",&TTT);
	while (TTT--){
		nx=ny=edgecnt=0;mem(Nx,0);mem(Ny,0);mem(stu,0);mem(Id,0);mem(Head,-1);mem(Exi,0);
		scanf("%d%d%d%d",&Sx,&Sy,&Tx,&Ty);
		Nx[++nx]=Sx;Nx[++nx]=Tx;Ny[++ny]=Sy,Ny[++ny]=Ty;
		scanf("%d",&n);
		bool flag=1;
		for (int i=1;i<=n;i++){
			scanf("%d%d%d%d",&A[i],&B[i],&C[i],&D[i]);Exi[i]=1;
			if (A[i]>C[i]) swap(A[i],C[i]);
			if (B[i]>D[i]) swap(B[i],D[i]);
			if ((A[i]<Sx)&&(C[i]>Sx)&&(B[i]<Sy)&&(D[i]>Sy)) flag=0;
			if ((A[i]<Tx)&&(C[i]>Tx)&&(B[i]<Ty)&&(D[i]>Ty)) flag=0;
			Nx[++nx]=A[i];Nx[++nx]=C[i];Ny[++ny]=B[i];Ny[++ny]=D[i];
		}
		if (flag==0){
			printf("No Path\n");continue;
		}
		for (int i=1;i<=n;i++)
			for (int j=1;j<=n;j++)
				if (i!=j)
					if ((A[j]<=A[i])&&(B[j]<=B[i])&&(C[j]>=C[i])&&(D[j]>=D[i])){
						Exi[i]=0;break;
					}
		sort(&Nx[1],&Nx[nx+1]);nx=unique(&Nx[1],&Nx[nx+1])-Nx-1;
		sort(&Ny[1],&Ny[ny+1]);ny=unique(&Ny[1],&Ny[ny+1])-Ny-1;

		cout<<"Nx:";for (int i=1;i<=nx;i++) cout<<Nx[i]<<" ";cout<<endl;
		cout<<"Ny:";for (int i=1;i<=ny;i++) cout<<Ny[i]<<" ";cout<<endl;

		Sx=Find(Nx,nx,Sx);Sy=Find(Ny,ny,Sy);Tx=Find(Nx,nx,Tx);Ty=Find(Ny,ny,Ty);
		for (int i=1;i<=n;i++) A[i]=Find(Nx,nx,A[i]),B[i]=Find(Ny,ny,B[i]),C[i]=Find(Nx,nx,C[i]),D[i]=Find(Ny,ny,D[i]);

		cout<<Sx<<" "<<Sy<<" "<<Tx<<" "<<Ty<<endl;
		for (int i=1;i<=n;i++) cout<<"("<<A[i]<<","<<B[i]<<") ("<<C[i]<<","<<D[i]<<")"<<endl;

		for (int i=1;i<=n;i++){
			if (Exi[i]==0) continue;
			for (int j=A[i];j<=C[i];j++) stu[j][B[i]]=1,stu[j][D[i]]=2;
			for (int j=B[i];j<=D[i];j++) stu[A[i]][j]=1,stu[C[i]][j]=2;
			stu[A[i]][B[i]]=stu[A[i]][D[i]]=stu[C[i]][B[i]]=stu[C[i]][D[i]]=-1;
		}
		stu[Sx][Sy]=stu[Tx][Ty]=-1;
		for (int i=1;i<=nx;i++){
			for (int j=1;j<=ny;j++)
				cout<<setw(4)<<stu[i][j];
			cout<<endl;
		}
		for (int i=1;i<=n;i++){
			if (Exi[i]==0) continue;
			Go(A[i],B[i],-1,0);Go(A[i],B[i],0,-1);Go(A[i],D[i],-1,0);Go(A[i],D[i],0,1);
			Go(C[i],B[i],1,0);Go(C[i],B[i],0,-1);Go(C[i],D[i],1,0);Go(C[i],D[i],0,1);
			Id[A[i]][B[i]]=Id[A[i]][D[i]]=Id[C[i]][B[i]]=Id[C[i]][D[i]]=1;
		}
		Id[Sx][Sy]=Id[Tx][Ty]=1;

		cout<<endl;
		for (int i=1;i<=nx;i++){
			for (int j=1;j<=ny;j++)
				cout<<setw(4)<<Id[i][j];
			cout<<endl;
		}

		for (int i=1;i<=nx;i++)
			for (int j=1;j<=ny;j++){
				if (Id[i][j]) P[++pcnt]=((Point){i,j,pcnt});
				if ((i==Sx)&&(j==Sy)) S=pcnt;
				if ((i==Tx)&&(j==Ty)) T=pcnt;
			}
		sort(&P[1],&P[pcnt+1],cmpx);
		for (int i=1,j;i<=pcnt;i=j){
			j=i+1;
			while (P[j].x==P[i].x){
				if ((stu[P[j-1].x][P[j-1].y]==-1)||(stu[P[j].x][P[j].y]==-1)||((stu[P[j-1].x][P[j-1].y]==2)&&(stu[P[j].x][P[j].y]==1)))
					Add_Edge(P[j-1].id,P[j].id,abs(Ny[P[j].y]-Ny[P[j-1].y]));
				j++;
			}
		}
		sort(&P[1],&P[pcnt+1],cmpy);
		for (int i=1,j;i<=pcnt;i=j){
			j=i+1;
			while (P[j].y==P[i].y){
				if ((stu[P[j-1].x][P[j-1].y]==-1)||(stu[P[j].x][P[j].y]==-1)||((stu[P[j-1].x][P[j-1].y]==2)&&(stu[P[j].x][P[j].y]==1)))
					Add_Edge(P[j-1].id,P[j].id,abs(Nx[P[j].x]-Nx[P[j-1].x]));
				j++;
			}
		}
		Spfa();
		if (Dist[T]==inf) printf("No Path\n");
		else printf("%d\n",Dist[T]);
	}
	return 0;
}

void Add_Edge(int u,int v,int w){
	Next[++edgecnt]=Head[u];Head[u]=edgecnt;V[edgecnt]=v;W[edgecnt]=w;
	Next[++edgecnt]=Head[v];Head[v]=edgecnt;V[edgecnt]=u;W[edgecnt]=w;
	return;
}

void Go(int x,int y,int dx,int dy){
	x+=dx;y+=dy;
	while (stu[x][y]==0){
		if ((x<1)||(y<1)||(x>nx)||(y>ny)) return;
		x+=dx;y+=dy;
	}
	Id[x][y]=1;return;
}

bool cmpx(Point P1,Point P2){
	if (P1.x!=P2.x) return P1.x<P2.x;
	return P1.y<P2.y;
}

bool cmpy(Point P1,Point P2){
	if (P1.y!=P2.y) return P1.y<P2.y;
	return P1.x<P2.x;
}

void Spfa(){
	for (int i=1;i<=pcnt;i++) Dist[i]=inf;
	Dist[S]=0;inq[S]=1;Q.push(S);
	while (!Q.empty()){
		int u=Q.front();Q.pop();
		for (int i=Head[u];i!=-1;i=Next[i])
			if (Dist[V[i]]>Dist[u]+W[i]){
				Dist[V[i]]=Dist[u]+W[i];
				if (inq[V[i]]==0){
					Q.push(V[i]);inq[V[i]]=1;
				}
			}
		inq[u]=0;
	}
	return;
}
<commit_msg>2018.10.2 noon<commit_after>#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<iomanip>
using namespace std;

#define ll long long
#define mem(Arr,x) memset(Arr,x,sizeof(Arr))
#define Find(Arr,size,x) (lower_bound(&Arr[1],&Arr[size+1],x)-Arr)

const int maxN=2010;
const int maxNode=maxN*20;
const int maxM=maxNode*4;
const int inf=2147483647;

class Point
{
public:
	int x,y,id;
};

int n,Sx,Sy,Tx,Ty,S,T;
int A[maxN],B[maxN],C[maxN],D[maxN];
int nx,Nx[maxNode],ny,Ny[maxNode];
int edgecnt=0,Head[maxNode],Next[maxM],V[maxM],W[maxM];
int stu[maxN][maxN],Id[maxN][maxN],pcnt;
Point P[maxNode];
bool Exi[maxN],inq[maxNode];
int Dist[maxNode];
queue<int> Q;

void Go(int x,int y,int dx,int dy);
bool cmpx(Point P1,Point P2);
bool cmpy(Point P1,Point P2);
void Add_Edge(int u,int v,int w);
void Spfa();

int main(){
	int TTT;scanf("%d",&TTT);
	while (TTT--){
		nx=ny=edgecnt=pcnt=0;mem(Nx,0);mem(Ny,0);mem(stu,0);mem(Id,0);mem(Head,-1);mem(Exi,0);
		scanf("%d%d%d%d",&Sx,&Sy,&Tx,&Ty);
		Nx[++nx]=Sx;Nx[++nx]=Tx;Ny[++ny]=Sy,Ny[++ny]=Ty;
		scanf("%d",&n);
		bool flag=1;
		for (int i=1;i<=n;i++){
			scanf("%d%d%d%d",&A[i],&B[i],&C[i],&D[i]);Exi[i]=1;
			if (A[i]>C[i]) swap(A[i],C[i]);
			if (B[i]>D[i]) swap(B[i],D[i]);
			if ((A[i]<Sx)&&(C[i]>Sx)&&(B[i]<Sy)&&(D[i]>Sy)) flag=0;
			if ((A[i]<Tx)&&(C[i]>Tx)&&(B[i]<Ty)&&(D[i]>Ty)) flag=0;
			Nx[++nx]=A[i];Nx[++nx]=C[i];Ny[++ny]=B[i];Ny[++ny]=D[i];
		}
		if (flag==0){
			printf("No Path\n");continue;
		}
		for (int i=1;i<=n;i++)
			for (int j=1;j<=n;j++)
				if (i!=j)
					if ((A[j]<=A[i])&&(B[j]<=B[i])&&(C[j]>=C[i])&&(D[j]>=D[i])){
						Exi[i]=0;break;
					}
		sort(&Nx[1],&Nx[nx+1]);nx=unique(&Nx[1],&Nx[nx+1])-Nx-1;
		sort(&Ny[1],&Ny[ny+1]);ny=unique(&Ny[1],&Ny[ny+1])-Ny-1;

		//cout<<"Nx:";for (int i=1;i<=nx;i++) cout<<Nx[i]<<" ";cout<<endl;
		//cout<<"Ny:";for (int i=1;i<=ny;i++) cout<<Ny[i]<<" ";cout<<endl;

		Sx=Find(Nx,nx,Sx);Sy=Find(Ny,ny,Sy);Tx=Find(Nx,nx,Tx);Ty=Find(Ny,ny,Ty);
		for (int i=1;i<=n;i++) A[i]=Find(Nx,nx,A[i]),B[i]=Find(Ny,ny,B[i]),C[i]=Find(Nx,nx,C[i]),D[i]=Find(Ny,ny,D[i]);

		//cout<<Sx<<" "<<Sy<<" "<<Tx<<" "<<Ty<<endl;
		//for (int i=1;i<=n;i++) cout<<"("<<A[i]<<","<<B[i]<<") ("<<C[i]<<","<<D[i]<<")"<<endl;

		for (int i=1;i<=n;i++){
			if (Exi[i]==0) continue;
			for (int j=A[i];j<=C[i];j++) stu[j][B[i]]=1,stu[j][D[i]]=2;
			for (int j=B[i];j<=D[i];j++) stu[A[i]][j]=1,stu[C[i]][j]=2;
			stu[A[i]][B[i]]=stu[A[i]][D[i]]=stu[C[i]][B[i]]=stu[C[i]][D[i]]=-1;
		}
		stu[Sx][Sy]=stu[Tx][Ty]=-1;
		/*
		for (int i=1;i<=nx;i++){
			for (int j=1;j<=ny;j++)
				cout<<setw(4)<<stu[i][j];
			cout<<endl;
		}
		//*/
		for (int i=1;i<=n;i++){
			if (Exi[i]==0) continue;
			Go(A[i],B[i],-1,0);Go(A[i],B[i],0,-1);Go(A[i],D[i],-1,0);Go(A[i],D[i],0,1);
			Go(C[i],B[i],1,0);Go(C[i],B[i],0,-1);Go(C[i],D[i],1,0);Go(C[i],D[i],0,1);
			Id[A[i]][B[i]]=Id[A[i]][D[i]]=Id[C[i]][B[i]]=Id[C[i]][D[i]]=1;
		}
		Id[Sx][Sy]=Id[Tx][Ty]=1;
		Go(Sx,Sy,0,1);Go(Sx,Sy,1,0);Go(Sx,Sy,0,-1);Go(Sx,Sy,-1,0);
		Go(Tx,Ty,0,1);Go(Tx,Ty,1,0);Go(Tx,Ty,0,-1);Go(Tx,Ty,-1,0);

		/*
		cout<<endl;
		for (int i=1;i<=nx;i++){
			for (int j=1;j<=ny;j++)
				cout<<setw(4)<<Id[i][j];
			cout<<endl;
		}
		//*/
		for (int i=1;i<=nx;i++)
			for (int j=1;j<=ny;j++){
				if (Id[i][j]) P[++pcnt]=((Point){i,j,pcnt});
				if ((i==Sx)&&(j==Sy)) S=pcnt;
				if ((i==Tx)&&(j==Ty)) T=pcnt;
				//if (Id[i][j]) cout<<pcnt<<":"<<P[i].x<<" "<<P[i].y<<endl;
			}
		sort(&P[1],&P[pcnt+1],cmpx);

		//for (int i=1;i<=pcnt;i++) cout<<"("<<P[i].x<<" "<<P[i].y<<") ";cout<<endl;

		for (int i=1,j;i<=pcnt;i=j){
			j=i+1;
			while (P[j].x==P[i].x){
				if ((stu[P[j-1].x][P[j-1].y]==-1)||(stu[P[j].x][P[j].y]==-1)||((stu[P[j-1].x][P[j-1].y]==2)&&(stu[P[j].x][P[j].y]==1)))
					Add_Edge(P[j-1].id,P[j].id,Ny[P[j].y]-Ny[P[j-1].y]);
				j++;
			}
		}
		sort(&P[1],&P[pcnt+1],cmpy);
		for (int i=1,j;i<=pcnt;i=j){
			j=i+1;
			while (P[j].y==P[i].y){
				if ((stu[P[j-1].x][P[j-1].y]==-1)||(stu[P[j].x][P[j].y]==-1)||((stu[P[j-1].x][P[j-1].y]==2)&&(stu[P[j].x][P[j].y]==1)))
					Add_Edge(P[j-1].id,P[j].id,Nx[P[j].x]-Nx[P[j-1].x]);
				j++;
			}
		}
		Spfa();
		if (Dist[T]==inf) printf("No Path\n");
		else printf("%d\n",Dist[T]);
	}
	return 0;
}

void Add_Edge(int u,int v,int w){
	//cout<<"Add:"<<u<<" "<<v<<" "<<w<<endl;
	Next[++edgecnt]=Head[u];Head[u]=edgecnt;V[edgecnt]=v;W[edgecnt]=w;
	Next[++edgecnt]=Head[v];Head[v]=edgecnt;V[edgecnt]=u;W[edgecnt]=w;
	return;
}

void Go(int x,int y,int dx,int dy){
	x+=dx;y+=dy;
	while (stu[x][y]==0){
		if ((x<1)||(y<1)||(x>nx)||(y>ny)) return;
		x+=dx;y+=dy;
	}
	Id[x][y]=1;return;
}

bool cmpx(Point P1,Point P2){
	if (P1.x!=P2.x) return P1.x<P2.x;
	return P1.y<P2.y;
}

bool cmpy(Point P1,Point P2){
	if (P1.y!=P2.y) return P1.y<P2.y;
	return P1.x<P2.x;
}

void Spfa(){
	for (int i=1;i<=pcnt;i++) Dist[i]=inf;
	Dist[S]=0;inq[S]=1;Q.push(S);
	while (!Q.empty()){
		int u=Q.front();Q.pop();//cout<<u<<endl;
		for (int i=Head[u];i!=-1;i=Next[i])
			if (Dist[V[i]]>Dist[u]+W[i]){
				Dist[V[i]]=Dist[u]+W[i];
				if (inq[V[i]]==0){
					Q.push(V[i]);inq[V[i]]=1;
				}
			}
		inq[u]=0;
	}
	return;
}
/*
2
1 7 7 8
2
2 5 3 8
4 10 6 7
2 1 5 4
1
3 1 4 3

1
1 7 7 8
2
2 5 3 8
4 10 6 7
//*/
<|endoftext|>


<commit_before>/** @file
    @brief Implementation

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2015 Sensics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include <osvr/ClientKit/Context.h>
#include <osvr/Common/ApplyPathNodeVisitor.h>
#include <osvr/Common/ClientContext.h>
#include <osvr/Common/PathElementTools.h>
#include <osvr/Common/PathElementTypes.h>
#include <osvr/Common/PathNode.h>
#include <osvr/Common/PathTreeFull.h>
#include <osvr/Common/ResolveFullTree.h>
#include <osvr/Util/IndentingStream.h>
#include <osvr/Util/ProgramOptionsToggleFlags.h>
#include <osvr/Util/TreeTraversalVisitor.h>

// Library/third-party includes
#include <boost/noncopyable.hpp>
#include <boost/program_options.hpp>
#include <boost/variant.hpp>

// Standard includes
#include <chrono>
#include <iomanip>
#include <iostream>
#include <string>
#include <thread>
#include <unordered_set>
#include <vector>

struct Options {
    bool showAliasSource;
    bool showAliasPriority;
    bool showDeviceDetails;
    bool showDeviceDescriptor;
    bool showSensors;
    bool showStringData;
};

using osvr::common::PathNode;
namespace elements = osvr::common::elements;

/// This functor is applied at each node to get the (type-safe variant) value
/// out of it (hence the numerous overloads of the function call operator - one
/// for each node element type we want to treat differently.)
///
/// As a "visitor", this visitor visits just a single node - it's used by a
/// simple lambda to visit every node in the path tree.
class TreeNodePrinter : public boost::static_visitor<>, boost::noncopyable {
  public:
    /// @brief Constructor
    TreeNodePrinter(Options opts, std::vector<std::string> const &badAliases)
        : boost::static_visitor<>(), m_opts(opts),
          m_maxTypeLen(elements::getMaxTypeNameLength()), m_os(std::cout),
          m_indentStream(m_maxTypeLen + 2 + 1 + 2, m_os),
          m_badAliases(begin(badAliases), end(badAliases)) {
        // Computation for initializing the indent stream above:
        // Indents type name size, +2 for the brackets, +1 for the space, and +2
        // so it doesn't line up with the path.

        // Some initial space to set the output off.
        m_os << "\n\n";
    }

    /// @brief print nothing for a null element.
    void operator()(PathNode const &, elements::NullElement const &) {}

    /// @brief We might print something for a sensor element.
    void operator()(PathNode const &node, elements::SensorElement const &elt) {
        if (m_opts.showSensors) {
            outputBasics(node, elt) << "\n";
        }
    }

    /// @brief Print aliases
    void operator()(PathNode const &node, elements::AliasElement const &elt) {
        outputBasics(node, elt) << std::endl;

        /// Check to see if this alias fully resolved, and warn if it didn't.
        auto fullPath = osvr::common::getFullPath(node);
        if (m_badAliases.find(fullPath) != m_badAliases.end()) {
            m_indentStream << "WARNING: this alias does not fully resolve to a "
                              "device/sensor!\n";
        }

        if (m_opts.showAliasSource) {
            m_indentStream << "-> " << elt.getSource() << std::endl;
        }
        if (m_opts.showAliasPriority) {
            m_indentStream << "Priority: "
                           << osvr::common::outputPriority(elt.priority())
                           << std::endl;
        }
    }
    /// @brief Print Devices
    void operator()(PathNode const &node, elements::DeviceElement const &elt) {
        outputBasics(node, elt) << std::endl;
        if (m_opts.showDeviceDetails) {
            m_indentStream << "- corresponds to " << elt.getFullDeviceName()
                           << std::endl;
        }
        if (m_opts.showDeviceDescriptor) {
            m_indentStream << "- Descriptor: "
                           << elt.getDescriptor().toStyledString() << std::endl;
        }
    }

    /// @brief We might print something for a sensor element.
    void operator()(PathNode const &node, elements::StringElement const &elt) {
        outputBasics(node, elt) << std::endl;
        if (m_opts.showStringData) {
            m_indentStream << "- Contained value: " << elt.getString()
                           << std::endl;
        }
    }

    /// @brief Catch-all for other element types.
    template <typename T> void operator()(PathNode const &node, T const &elt) {
        outputBasics(node, elt) << "\n";
    }

  private:
    /// @brief shared implementation: prints type name in brackets padded to
    /// fixed width, then the full path.
    template <typename T>
    std::ostream &outputBasics(PathNode const &node, T const &elt) {
        m_os << "[" << std::setw(m_maxTypeLen) << osvr::common::getTypeName(elt)
             << "] " << osvr::common::getFullPath(node);
        return m_os;
    }
    Options m_opts;
    size_t m_maxTypeLen;
    std::ostream &m_os;
    osvr::util::IndentingStream m_indentStream;

    /// The set of paths that are aliases that don't completely resolve.
    std::unordered_set<std::string> m_badAliases;
};

int main(int argc, char *argv[]) {
    Options opts;
    namespace po = boost::program_options;
    // clang-format off
    po::options_description desc("Options");
    desc.add_options()
        ("help,h", "produce help message")
        ("alias-source", po::value<bool>(&opts.showAliasSource)->default_value(true), "Whether or not to show the source associated with each alias")
        ("alias-priority", po::value<bool>(&opts.showAliasPriority)->default_value(false), "Whether or not to show the priority associated with each alias")
        ("device-details", po::value<bool>(&opts.showDeviceDetails)->default_value(true), "Whether or not to show the basic details associated with each device")
        ("device-descriptors", po::value<bool>(&opts.showDeviceDescriptor)->default_value(false), "Whether or not to show the JSON descriptors associated with each device")
        ("sensors", po::value<bool>(&opts.showSensors)->default_value(true), "Whether or not to show the 'sensor' nodes")
        ("string-data", po::value<bool>(&opts.showStringData)->default_value(true), "Whether or not to show the data in 'string' nodes")
        ;
    // clang-format on
    po::variables_map vm;
    bool usage = false;
    try {
        po::store(po::command_line_parser(argc, argv)
                      .options(desc)
                      .extra_parser(
                          osvr::util::convertProgramOptionShowHideIntoTrueFalse)
                      .run(),
                  vm);
        po::notify(vm);
    } catch (std::exception &e) {
        std::cerr << "\nError parsing command line: " << e.what() << "\n\n";
        usage = true;
    }
    if (usage || vm.count("help")) {
        std::cerr << "\nTraverses the path tree and outputs it as text for "
                     "human consumption. See\nPathTreeExport for structured "
                     "output for graphical display.\n";
        std::cerr << "Usage: " << argv[0] << " [options]\n\n";
        std::cerr << "All options are shown as being --option 1/0 (true/false) "
                     "but may be expressed\nas --show-option or --hide-option "
                     "instead (e.g. --show-alias-priority)\n\n";
        std::cerr << desc << "\n";
        return 1;
    }

    osvr::common::PathTree pathTree;
    std::vector<std::string> badAliases;

    {
        /// We only actually need the client open for long enough to get the
        /// path tree and clone it.
        osvr::clientkit::ClientContext context("org.osvr.tools.printtree");

        if (!context.checkStatus()) {
            context.log(OSVR_LOGLEVEL_NOTICE,
                        "Client context has not yet started up - waiting. "
                        "Make sure the server is running.");
            do {
                std::this_thread::sleep_for(std::chrono::milliseconds(1));
                context.update();
            } while (!context.checkStatus());
            context.log(OSVR_LOGLEVEL_NOTICE,
                        "OK, client context ready. Proceeding.");
        }
        /// Get a non-const copy of the path tree.
        osvr::common::clonePathTree(context.get()->getPathTree(), pathTree);
        /// Resolve all aliases, keeping track of those that don't fully
        /// resolve.
        badAliases = osvr::common::resolveFullTree(pathTree);
    }

    /// Before we print anything, we should flush the logger so it doesn't
    /// intermix with our output.
    osvr::util::log::flush();

    TreeNodePrinter printer{opts, badAliases};
    /// Now traverse for output - traverse every node in the path tree and apply
    /// the node visitor to get the type-safe variant data out of the nodes. The
    /// lambda will be called (and thus the TreeNodePrinter applied) at every
    /// PathNode in the tree.
    osvr::util::traverseWith(
        pathTree.getRoot(), [&printer](PathNode const &node) {
            osvr::common::applyPathNodeVisitor(printer, node);
        });

    return 0;
}
<commit_msg>add show articulation to print tree<commit_after>/** @file
    @brief Implementation

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2015 Sensics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include <osvr/ClientKit/Context.h>
#include <osvr/Common/ApplyPathNodeVisitor.h>
#include <osvr/Common/ClientContext.h>
#include <osvr/Common/PathElementTools.h>
#include <osvr/Common/PathElementTypes.h>
#include <osvr/Common/PathNode.h>
#include <osvr/Common/PathTreeFull.h>
#include <osvr/Common/ResolveFullTree.h>
#include <osvr/Util/IndentingStream.h>
#include <osvr/Util/ProgramOptionsToggleFlags.h>
#include <osvr/Util/TreeTraversalVisitor.h>

// Library/third-party includes
#include <boost/noncopyable.hpp>
#include <boost/program_options.hpp>
#include <boost/variant.hpp>

// Standard includes
#include <chrono>
#include <iomanip>
#include <iostream>
#include <string>
#include <thread>
#include <unordered_set>
#include <vector>

struct Options {
    bool showAliasSource;
    bool showAliasPriority;
    bool showDeviceDetails;
    bool showDeviceDescriptor;
    bool showSensors;
    bool showStringData;
    bool showArticulations;
};

using osvr::common::PathNode;
namespace elements = osvr::common::elements;

/// This functor is applied at each node to get the (type-safe variant) value
/// out of it (hence the numerous overloads of the function call operator - one
/// for each node element type we want to treat differently.)
///
/// As a "visitor", this visitor visits just a single node - it's used by a
/// simple lambda to visit every node in the path tree.
class TreeNodePrinter : public boost::static_visitor<>, boost::noncopyable {
  public:
    /// @brief Constructor
    TreeNodePrinter(Options opts, std::vector<std::string> const &badAliases)
        : boost::static_visitor<>(), m_opts(opts),
          m_maxTypeLen(elements::getMaxTypeNameLength()), m_os(std::cout),
          m_indentStream(m_maxTypeLen + 2 + 1 + 2, m_os),
          m_badAliases(begin(badAliases), end(badAliases)) {
        // Computation for initializing the indent stream above:
        // Indents type name size, +2 for the brackets, +1 for the space, and +2
        // so it doesn't line up with the path.

        // Some initial space to set the output off.
        m_os << "\n\n";
    }

    /// @brief print nothing for a null element.
    void operator()(PathNode const &, elements::NullElement const &) {}

    /// @brief We might print something for a sensor element.
    void operator()(PathNode const &node, elements::SensorElement const &elt) {
        if (m_opts.showSensors) {
            outputBasics(node, elt) << "\n";
        }
    }

    /// @brief Print aliases
    void operator()(PathNode const &node, elements::AliasElement const &elt) {
        outputBasics(node, elt) << std::endl;

        /// Check to see if this alias fully resolved, and warn if it didn't.
        auto fullPath = osvr::common::getFullPath(node);
        if (m_badAliases.find(fullPath) != m_badAliases.end()) {
            m_indentStream << "WARNING: this alias does not fully resolve to a "
                              "device/sensor!\n";
        }

        if (m_opts.showAliasSource) {
            m_indentStream << "-> " << elt.getSource() << std::endl;
        }
        if (m_opts.showAliasPriority) {
            m_indentStream << "Priority: "
                           << osvr::common::outputPriority(elt.priority())
                           << std::endl;
        }
    }
    /// @brief Print Devices
    void operator()(PathNode const &node, elements::DeviceElement const &elt) {
        outputBasics(node, elt) << std::endl;
        if (m_opts.showDeviceDetails) {
            m_indentStream << "- corresponds to " << elt.getFullDeviceName()
                           << std::endl;
        }
        if (m_opts.showDeviceDescriptor) {
            m_indentStream << "- Descriptor: "
                           << elt.getDescriptor().toStyledString() << std::endl;
        }
    }

    /// @brief We might print something for a sensor element.
    void operator()(PathNode const &node, elements::StringElement const &elt) {
        outputBasics(node, elt) << std::endl;
        if (m_opts.showStringData) {
            m_indentStream << "- Contained value: " << elt.getString()
                           << std::endl;
        }
    }

    void operator()(osvr::common::PathNode const &node,
                    osvr::common::elements::ArticulationElement const &elt) {
        m_outputBasics(node, elt) << std::endl;
        // if (m_opts.showStringData) {
        m_indentStream << "- Contained value: Articulation Type = " << elt.getArticulationType()
            << "; Tracker path = " << elt.getTrackerPath() << "; Bone Name = " << elt.getBoneName() << std::endl;
        //}
    }

    /// @brief Catch-all for other element types.
    template <typename T> void operator()(PathNode const &node, T const &elt) {
        outputBasics(node, elt) << "\n";
    }

  private:
    /// @brief shared implementation: prints type name in brackets padded to
    /// fixed width, then the full path.
    template <typename T>
    std::ostream &outputBasics(PathNode const &node, T const &elt) {
        m_os << "[" << std::setw(m_maxTypeLen) << osvr::common::getTypeName(elt)
             << "] " << osvr::common::getFullPath(node);
        return m_os;
    }
    Options m_opts;
    size_t m_maxTypeLen;
    std::ostream &m_os;
    osvr::util::IndentingStream m_indentStream;

    /// The set of paths that are aliases that don't completely resolve.
    std::unordered_set<std::string> m_badAliases;
};

int main(int argc, char *argv[]) {
    Options opts;
    namespace po = boost::program_options;
    // clang-format off
    po::options_description desc("Options");
    desc.add_options()
        ("help,h", "produce help message")
        ("alias-source", po::value<bool>(&opts.showAliasSource)->default_value(true), "Whether or not to show the source associated with each alias")
        ("alias-priority", po::value<bool>(&opts.showAliasPriority)->default_value(false), "Whether or not to show the priority associated with each alias")
        ("device-details", po::value<bool>(&opts.showDeviceDetails)->default_value(true), "Whether or not to show the basic details associated with each device")
        ("device-descriptors", po::value<bool>(&opts.showDeviceDescriptor)->default_value(false), "Whether or not to show the JSON descriptors associated with each device")
        ("sensors", po::value<bool>(&opts.showSensors)->default_value(true), "Whether or not to show the 'sensor' nodes")
        ("string-data", po::value<bool>(&opts.showStringData)->default_value(true), "Whether or not to show the data in 'string' nodes")
        ("articulations", po::value<bool>(&opts.showArticulations)->default_value(true), "Whether or not to show the articulations")
        ;
    // clang-format on
    po::variables_map vm;
    bool usage = false;
    try {
        po::store(po::command_line_parser(argc, argv)
                      .options(desc)
                      .extra_parser(
                          osvr::util::convertProgramOptionShowHideIntoTrueFalse)
                      .run(),
                  vm);
        po::notify(vm);
    } catch (std::exception &e) {
        std::cerr << "\nError parsing command line: " << e.what() << "\n\n";
        usage = true;
    }
    if (usage || vm.count("help")) {
        std::cerr << "\nTraverses the path tree and outputs it as text for "
                     "human consumption. See\nPathTreeExport for structured "
                     "output for graphical display.\n";
        std::cerr << "Usage: " << argv[0] << " [options]\n\n";
        std::cerr << "All options are shown as being --option 1/0 (true/false) "
                     "but may be expressed\nas --show-option or --hide-option "
                     "instead (e.g. --show-alias-priority)\n\n";
        std::cerr << desc << "\n";
        return 1;
    }

    osvr::common::PathTree pathTree;
    std::vector<std::string> badAliases;

    {
        /// We only actually need the client open for long enough to get the
        /// path tree and clone it.
        osvr::clientkit::ClientContext context("org.osvr.tools.printtree");

        if (!context.checkStatus()) {
            context.log(OSVR_LOGLEVEL_NOTICE,
                        "Client context has not yet started up - waiting. "
                        "Make sure the server is running.");
            do {
                std::this_thread::sleep_for(std::chrono::milliseconds(1));
                context.update();
            } while (!context.checkStatus());
            context.log(OSVR_LOGLEVEL_NOTICE,
                        "OK, client context ready. Proceeding.");
        }
        /// Get a non-const copy of the path tree.
        osvr::common::clonePathTree(context.get()->getPathTree(), pathTree);
        /// Resolve all aliases, keeping track of those that don't fully
        /// resolve.
        badAliases = osvr::common::resolveFullTree(pathTree);
    }

    /// Before we print anything, we should flush the logger so it doesn't
    /// intermix with our output.
    osvr::util::log::flush();

    TreeNodePrinter printer{opts, badAliases};
    /// Now traverse for output - traverse every node in the path tree and apply
    /// the node visitor to get the type-safe variant data out of the nodes. The
    /// lambda will be called (and thus the TreeNodePrinter applied) at every
    /// PathNode in the tree.
    osvr::util::traverseWith(
        pathTree.getRoot(), [&printer](PathNode const &node) {
            osvr::common::applyPathNodeVisitor(printer, node);
        });

    return 0;
}
<|endoftext|>


<commit_before>#include "stdsneezy.h"
#include "games.h"

HiLoGame gHiLo;

const float WIN_INIT=0.10;

bool HiLoGame::enter(const TBeing *ch)
{
  if(inuse){
    ch->sendTo("This table is already in use.\n\r");
    return false;
  }

  inuse = true;
  hilo_shuffle(ch);
  bet = 0;
  name=ch->name;

  return true;
}

void HiLoGame::hilo_shuffle(const TBeing *ch)
{
  act("The dealer shuffles the deck.",FALSE, ch, 0, 0, TO_CHAR);
  act("The dealer shuffles the deck.",FALSE, ch, 0, 0, TO_ROOM);

  shuffle();
  deck_inx = 0;
}

bool TBeing::checkHiLo(bool inGame = false) const
{
  if (in_room == ROOM_HILO && (inGame || (gHiLo.index(this) > -1)))
    return true;
  else
    return false;
}

void HiLoGame::BetHi(TBeing *ch, int new_card)
{
  sstring buf;

  if(CARD_NUM_ACEHI(new_card) > CARD_NUM_ACEHI(card)){
    win_perc*=2;
    ch->sendTo("You win!  Your winnings are now at %i talens.\n\r",
	       (int)((float)bet * (1.0 + win_perc)));
    ssprintf(buf, "$n wins!  $n's winnings are now at %i talens.",
	       (int)((float)bet * (1.0 + win_perc)));
    act(buf.c_str(), TRUE, ch, 0, 0, TO_ROOM);
    observerReaction(ch, GAMBLER_HILO_BET);
  } else {
    ch->sendTo("You lose!\n\r");
    act("$n loses!", TRUE, ch, 0, 0, TO_ROOM);
    observerReaction(ch, GAMBLER_LOST);
    bet = 0;
    card = 0;
  }
}

void HiLoGame::BetLo(TBeing *ch, int new_card)
{
  sstring buf;

  if(CARD_NUM_ACEHI(new_card) < CARD_NUM_ACEHI(card)){
    win_perc*=2;
    ch->sendTo("You win!  Your winnings are now at %i talens.\n\r",
	       (int)((float)bet * (1.0 + win_perc)));
    ssprintf(buf, "$n wins!  $n's winnings are now at %i talens.",
	       (int)((float)bet * (1.0 + win_perc)));
    act(buf.c_str(), TRUE, ch, 0, 0, TO_ROOM);
    observerReaction(ch, GAMBLER_HILO_BET);
  } else {
    ch->sendTo("You lose!\n\r");
    act("$n loses!", TRUE, ch, 0, 0, TO_ROOM);
    observerReaction(ch, GAMBLER_LOST);
    bet = 0;
    card = 0;
  }
}

void HiLoGame::stay(TBeing *ch)
{
  if(win_perc==WIN_INIT){
    ch->sendTo("You just started, you can't quit now!\n\r");
    return;
  }

  ch->sendTo("You give up and cash out your winnings.\n\r");
  act("$n gives up and cashes out $s winnings.",
      TRUE, ch, 0, 0, TO_ROOM);

  payout(ch, (int)((double)bet * (1.0 + win_perc)));
  bet = 0;
  card = 0;
  observerReaction(ch, GAMBLER_WON);
}

void HiLoGame::Bet(TBeing *ch, const sstring &arg)
{
  int inx, new_card;
  sstring coin_str;
  sstring log_msg;
  sstring buf;
  TObj *chip;

  if (ch->checkHiLo()) {
    inx = index(ch);
    if (inx < 0) {
      ch->sendTo("You are not sitting at the table yet.\n\r");
      return;
    }
    if (bet > 0) {
      if(arg=="hi" || arg=="lo"){
	if (deck_inx > 10)
	  hilo_shuffle(ch);

	new_card=deck[deck_inx++];

	ssprintf(buf, "$n bets %s.", arg.c_str());
	act(buf.c_str(), TRUE, ch, 0, 0, TO_ROOM);

	ssprintf(log_msg, "You are dealt:\n\r%s\n\r", pretty_card_printout(ch, new_card).c_str());
	ch->sendTo(COLOR_BASIC, log_msg.c_str());

	ssprintf(log_msg, "$n is dealt:\n\r%s", pretty_card_printout(ch, new_card).c_str());
	act(log_msg.c_str(), TRUE, ch, 0, 0, TO_ROOM);

	if(arg=="hi"){
	  BetHi(ch, new_card);
	} else if(arg=="lo"){
	  BetLo(ch, new_card);
	}
	card=new_card;
	return;
      } else {
	ch->sendTo("You can't change your bet now.\n\r");
	ch->sendTo("You must either bet 'hi' or 'lo' for the next card.\n\r");
	return;
      }
    }
    argument_parser(arg, coin_str);
    if (coin_str.empty()){
      ch->sendTo("Bet which chip?\n\r");
      return;
    }

    if(!(chip=find_chip(ch, coin_str))){
      ch->sendTo("You don't have that chip!\n\r");
      return;
    }

    bet = chip->obj_flags.cost;
    ch->doSave(SILENT_YES);

    sstring buf;
    ssprintf(buf, "$n bets %s.", chip->getName());
    act(buf.c_str(), TRUE, ch, 0, 0, TO_ROOM);
    ssprintf(buf, "You bet %s.", chip->getName());
    act(buf.c_str(), TRUE, ch, 0, 0, TO_CHAR);

    (*chip)--;
    delete chip;

    win_perc=WIN_INIT;
    card=0;
    if (deck_inx > 10)
      hilo_shuffle(ch);

    card = deck[deck_inx++];

    ssprintf(log_msg, "You are dealt:\n\r%s\n\r", pretty_card_printout(ch, card).c_str());
    ch->sendTo(COLOR_BASIC, log_msg.c_str());

    ssprintf(log_msg, "$n is dealt:\n\r%s\n\r", pretty_card_printout(ch, card).c_str());
    act(log_msg.c_str(), TRUE, ch, 0, 0, TO_ROOM);

    observerReaction(ch, GAMBLER_HILO_BET);
  }
}

void HiLoGame::peek(const TBeing *ch) const
{
  sstring log_msg;

  if (index(ch) < 0) {
    ch->sendTo("You are not sitting at the table yet.\n\r");
    return;
  }
  if (!bet) {
    ch->sendTo("You are not playing a game.\n\r");
    return;
  }
  ssprintf(log_msg, "You peek at your hand:\n\r%s\n\r", pretty_card_printout(ch, card).c_str());
  ch->sendTo(COLOR_BASIC, log_msg.c_str());
}

int HiLoGame::exitGame(const TBeing *ch)
{
  int inx;

  if ((inx = index(ch)) < 0) {
    forceCrash("%s left a table he was not at!", ch->name);
    return FALSE;
  }
  inuse = FALSE;
  name="";
  deck_inx = 0;
  bet = 0;
  card = 0;
  win_perc=0;
  setup_deck();
  ch->sendTo("You leave the hi-lo table.\n\r");
  return TRUE;
}

int HiLoGame::index(const TBeing *ch) const
{
  if(ch->name == name)
    return 0;

  return -1;
}
<commit_msg>put payout back down added display of next card when you stay<commit_after>#include "stdsneezy.h"
#include "games.h"

HiLoGame gHiLo;

const float WIN_INIT=0.05;
bool HiLoGame::enter(const TBeing *ch)
{
  if(inuse){
    ch->sendTo("This table is already in use.\n\r");
    return false;
  }

  inuse = true;
  hilo_shuffle(ch);
  bet = 0;
  name=ch->name;

  return true;
}

void HiLoGame::hilo_shuffle(const TBeing *ch)
{
  act("The dealer shuffles the deck.",FALSE, ch, 0, 0, TO_CHAR);
  act("The dealer shuffles the deck.",FALSE, ch, 0, 0, TO_ROOM);

  shuffle();
  deck_inx = 0;
}

bool TBeing::checkHiLo(bool inGame = false) const
{
  if (in_room == ROOM_HILO && (inGame || (gHiLo.index(this) > -1)))
    return true;
  else
    return false;
}

void HiLoGame::BetHi(TBeing *ch, int new_card)
{
  sstring buf;

  if(CARD_NUM_ACEHI(new_card) > CARD_NUM_ACEHI(card)){
    win_perc*=2;
    ch->sendTo("You win!  Your winnings are now at %i talens.\n\r",
	       (int)((float)bet * (1.0 + win_perc)));
    ssprintf(buf, "$n wins!  $n's winnings are now at %i talens.",
	       (int)((float)bet * (1.0 + win_perc)));
    act(buf.c_str(), TRUE, ch, 0, 0, TO_ROOM);
    observerReaction(ch, GAMBLER_HILO_BET);
  } else {
    ch->sendTo("You lose!\n\r");
    act("$n loses!", TRUE, ch, 0, 0, TO_ROOM);
    observerReaction(ch, GAMBLER_LOST);
    bet = 0;
    card = 0;
  }
}

void HiLoGame::BetLo(TBeing *ch, int new_card)
{
  sstring buf;

  if(CARD_NUM_ACEHI(new_card) < CARD_NUM_ACEHI(card)){
    win_perc*=2;
    ch->sendTo("You win!  Your winnings are now at %i talens.\n\r",
	       (int)((float)bet * (1.0 + win_perc)));
    ssprintf(buf, "$n wins!  $n's winnings are now at %i talens.",
	       (int)((float)bet * (1.0 + win_perc)));
    act(buf.c_str(), TRUE, ch, 0, 0, TO_ROOM);
    observerReaction(ch, GAMBLER_HILO_BET);
  } else {
    ch->sendTo("You lose!\n\r");
    act("$n loses!", TRUE, ch, 0, 0, TO_ROOM);
    observerReaction(ch, GAMBLER_LOST);
    bet = 0;
    card = 0;
  }
}

void HiLoGame::stay(TBeing *ch)
{
  if(win_perc==WIN_INIT){
    ch->sendTo("You just started, you can't quit now!\n\r");
    return;
  }

  ch->sendTo("You give up and cash out your winnings.\n\r");
  act("$n gives up and cashes out $s winnings.",
      TRUE, ch, 0, 0, TO_ROOM);

  int next_card=deck[deck_inx++];
  sstring buf;
  ch->sendTo(COLOR_BASIC, "The next card was the %s.\n\r", pretty_card_printout(ch, next_card).c_str());
  ssprintf(buf, "The next card was the %s.", pretty_card_printout(ch, next_card).c_str());
  act(buf.c_str(), TRUE, ch, 0, 0, TO_ROOM);

  payout(ch, (int)((double)bet * (1.0 + win_perc)));
  bet = 0;
  card = 0;
  observerReaction(ch, GAMBLER_WON);
}

void HiLoGame::Bet(TBeing *ch, const sstring &arg)
{
  int inx, new_card;
  sstring coin_str;
  sstring log_msg;
  sstring buf;
  TObj *chip;

  if (ch->checkHiLo()) {
    inx = index(ch);
    if (inx < 0) {
      ch->sendTo("You are not sitting at the table yet.\n\r");
      return;
    }
    if (bet > 0) {
      if(arg=="hi" || arg=="lo"){
	if (deck_inx > 10)
	  hilo_shuffle(ch);

	new_card=deck[deck_inx++];

	ssprintf(buf, "$n bets %s.", arg.c_str());
	act(buf.c_str(), TRUE, ch, 0, 0, TO_ROOM);

	ssprintf(log_msg, "You are dealt:\n\r%s\n\r", pretty_card_printout(ch, new_card).c_str());
	ch->sendTo(COLOR_BASIC, log_msg.c_str());

	ssprintf(log_msg, "$n is dealt:\n\r%s", pretty_card_printout(ch, new_card).c_str());
	act(log_msg.c_str(), TRUE, ch, 0, 0, TO_ROOM);

	if(arg=="hi"){
	  BetHi(ch, new_card);
	} else if(arg=="lo"){
	  BetLo(ch, new_card);
	}
	card=new_card;
	return;
      } else {
	ch->sendTo("You can't change your bet now.\n\r");
	ch->sendTo("You must either bet 'hi' or 'lo' for the next card.\n\r");
	return;
      }
    }
    argument_parser(arg, coin_str);
    if (coin_str.empty()){
      ch->sendTo("Bet which chip?\n\r");
      return;
    }

    if(!(chip=find_chip(ch, coin_str))){
      ch->sendTo("You don't have that chip!\n\r");
      return;
    }

    bet = chip->obj_flags.cost;
    ch->doSave(SILENT_YES);

    sstring buf;
    ssprintf(buf, "$n bets %s.", chip->getName());
    act(buf.c_str(), TRUE, ch, 0, 0, TO_ROOM);
    ssprintf(buf, "You bet %s.", chip->getName());
    act(buf.c_str(), TRUE, ch, 0, 0, TO_CHAR);

    (*chip)--;
    delete chip;

    win_perc=WIN_INIT;
    card=0;
    if (deck_inx > 10)
      hilo_shuffle(ch);

    card = deck[deck_inx++];

    ssprintf(log_msg, "You are dealt:\n\r%s\n\r", pretty_card_printout(ch, card).c_str());
    ch->sendTo(COLOR_BASIC, log_msg.c_str());

    ssprintf(log_msg, "$n is dealt:\n\r%s\n\r", pretty_card_printout(ch, card).c_str());
    act(log_msg.c_str(), TRUE, ch, 0, 0, TO_ROOM);

    observerReaction(ch, GAMBLER_HILO_BET);
  }
}

void HiLoGame::peek(const TBeing *ch) const
{
  sstring log_msg;

  if (index(ch) < 0) {
    ch->sendTo("You are not sitting at the table yet.\n\r");
    return;
  }
  if (!bet) {
    ch->sendTo("You are not playing a game.\n\r");
    return;
  }
  ssprintf(log_msg, "You peek at your hand:\n\r%s\n\r", pretty_card_printout(ch, card).c_str());
  ch->sendTo(COLOR_BASIC, log_msg.c_str());
}

int HiLoGame::exitGame(const TBeing *ch)
{
  int inx;

  if ((inx = index(ch)) < 0) {
    forceCrash("%s left a table he was not at!", ch->name);
    return FALSE;
  }
  inuse = FALSE;
  name="";
  deck_inx = 0;
  bet = 0;
  card = 0;
  win_perc=0;
  setup_deck();
  ch->sendTo("You leave the hi-lo table.\n\r");
  return TRUE;
}

int HiLoGame::index(const TBeing *ch) const
{
  if(ch->name == name)
    return 0;

  return -1;
}
<|endoftext|>


<commit_before>#include "prov_info.h"

#include "../helper.h"

using namespace crypt;

NTSTATUS FreeKey(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE handle) {
    if (NCryptIsKeyHandle(handle)) {
        return NCryptFreeObject(handle);
    }
    else {
        if (!CryptReleaseContext(handle, 0)) {
            return GetLastError();
        }
    }
    return ERROR_SUCCESS;
}

NTSTATUS OpenKey(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE* handle, PCRYPT_KEY_PROV_INFO provInfo, BOOL fSilent) {
    if (provInfo->dwProvType) {
        // CAPI
        if (!CryptAcquireContextW(handle, provInfo->pwszContainerName, provInfo->pwszProvName, provInfo->dwProvType, fSilent ? CRYPT_SILENT : 0)) {
            return GetLastError();
        }
    }
    else {
        // CNG
        NTSTATUS status = ERROR_SUCCESS;
        NCRYPT_PROV_HANDLE hProv = 0;

        while (true) {
            status = NCryptOpenStorageProvider(&hProv, provInfo->pwszProvName, 0);
            if (status) {
                break;
            }

            status = NCryptOpenKey(hProv, handle, provInfo->pwszContainerName, provInfo->dwKeySpec, fSilent ? NCRYPT_SILENT_FLAG : 0);
            if (status) {
                break;
            }

            break;
        }

        if (hProv) {
            NCryptFreeObject(hProv);
        }

        return status;
    }
    return ERROR_SUCCESS;
}

ProviderInfo::ProviderInfo(Scoped<Buffer> info) :
    buffer(info),
    info((CRYPT_KEY_PROV_INFO*)info->data())
{
}

ProviderInfo::~ProviderInfo()
{
}

bool crypt::ProviderInfo::IsAccassible()
{
    HCRYPTPROV_OR_NCRYPT_KEY_HANDLE handle = 0;
    NTSTATUS status = ERROR_SUCCESS;
    status = OpenKey(&handle, info, true);
    if (status) {
        return false;
    }
    return true;
}

CRYPT_KEY_PROV_INFO * ProviderInfo::Get()
{
    return info;
}

Scoped<Buffer> crypt::ProviderInfo::GetSmartCardGUID()
{
    try {
        return GetBytes(PP_SMARTCARD_GUID);
    }
    CATCH_EXCEPTION
}

Scoped<std::string> crypt::ProviderInfo::GetSmartCardReader()
{
    try {
        auto buf = GetBytes(PP_SMARTCARD_READER);
        return Scoped<std::string>(new std::string((PCHAR)buf->data()));
    }
    CATCH_EXCEPTION
}

Scoped<Buffer> crypt::ProviderInfo::GetBytes(DWORD dwParam)
{
    try {
        HCRYPTPROV_OR_NCRYPT_KEY_HANDLE handle = 0;
        NTSTATUS status = 0;
        Scoped<Buffer> res(new Buffer(0));

        status = OpenKey(&handle, info, true);
        if (status) {
            THROW_NT_EXCEPTION(status, "OpenKey");
        }
        if (NCryptIsKeyHandle(handle)) {
            // CNG
            THROW_EXCEPTION("Not implemented");
        }
        else {
            // CAPI
            DWORD dataLen = 0;
            if (!CryptGetProvParam(handle, dwParam, NULL, &dataLen, 0)) {
                status = GetLastError();
                FreeKey(handle);
                THROW_MSCAPI_CODE_ERROR(MSCAPI_EXCEPTION_NAME, "CryptGetProvParam", status);
            }
            res->resize(dataLen);
            if (!CryptGetProvParam(handle, dwParam, res->data(), &dataLen, 0)) {
                status = GetLastError();
                FreeKey(handle);
                THROW_MSCAPI_CODE_ERROR(MSCAPI_EXCEPTION_NAME, "CryptGetProvParam", status);
            }
        }

        FreeKey(handle);
        return res;
    }
    CATCH_EXCEPTION
}
<commit_msg>Ыгззщке ProviderInfo::GetBytes for CNG<commit_after>#include "prov_info.h"

#include "../helper.h"

using namespace crypt;

NTSTATUS FreeKey(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE handle) {
    if (NCryptIsKeyHandle(handle)) {
        return NCryptFreeObject(handle);
    }
    else {
        if (!CryptReleaseContext(handle, 0)) {
            return GetLastError();
        }
    }
    return ERROR_SUCCESS;
}

NTSTATUS OpenKey(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE* handle, PCRYPT_KEY_PROV_INFO provInfo, BOOL fSilent) {
    if (provInfo->dwProvType) {
        // CAPI
        if (!CryptAcquireContextW(handle, provInfo->pwszContainerName, provInfo->pwszProvName, provInfo->dwProvType, fSilent ? CRYPT_SILENT : 0)) {
            return GetLastError();
        }
    }
    else {
        // CNG
        NTSTATUS status = ERROR_SUCCESS;
        NCRYPT_PROV_HANDLE hProv = 0;

        while (true) {
            status = NCryptOpenStorageProvider(&hProv, provInfo->pwszProvName, 0);
            if (status) {
                break;
            }

            status = NCryptOpenKey(hProv, handle, provInfo->pwszContainerName, provInfo->dwKeySpec, fSilent ? NCRYPT_SILENT_FLAG : 0);
            if (status) {
                break;
            }

            break;
        }

        if (hProv) {
            NCryptFreeObject(hProv);
        }

        return status;
    }
    return ERROR_SUCCESS;
}

ProviderInfo::ProviderInfo(Scoped<Buffer> info) :
    buffer(info),
    info((CRYPT_KEY_PROV_INFO*)info->data())
{
}

ProviderInfo::~ProviderInfo()
{
}

bool crypt::ProviderInfo::IsAccassible()
{
    HCRYPTPROV_OR_NCRYPT_KEY_HANDLE handle = 0;
    NTSTATUS status = ERROR_SUCCESS;
    status = OpenKey(&handle, info, true);
    if (status) {
        return false;
    }
    return true;
}

CRYPT_KEY_PROV_INFO * ProviderInfo::Get()
{
    return info;
}

Scoped<Buffer> crypt::ProviderInfo::GetSmartCardGUID()
{
    try {
        return GetBytes(PP_SMARTCARD_GUID);
    }
    CATCH_EXCEPTION
}

Scoped<std::string> crypt::ProviderInfo::GetSmartCardReader()
{
    try {
        auto buf = GetBytes(PP_SMARTCARD_READER);
        return Scoped<std::string>(new std::string((PCHAR)buf->data()));
    }
    CATCH_EXCEPTION
}

Scoped<Buffer> crypt::ProviderInfo::GetBytes(DWORD dwParam)
{
    try {
        HCRYPTPROV_OR_NCRYPT_KEY_HANDLE handle = 0;
        NTSTATUS status = 0;
        Scoped<Buffer> res(new Buffer(0));

        status = OpenKey(&handle, info, true);
        if (status) {
            THROW_NT_EXCEPTION(status, "OpenKey");
        }

        if (NCryptIsKeyHandle(handle)) {
            // CNG
            LPCWSTR propID;
            switch (dwParam) {
            case PP_SMARTCARD_GUID:
                propID = NCRYPT_SMARTCARD_GUID_PROPERTY;
                break;
            case PP_SMARTCARD_READER:
                propID = NCRYPT_READER_PROPERTY;
                break;
            default:
                FreeKey(handle);
                THROW_EXCEPTION("Unsupported property of Provider dwParam:%d", dwParam);
            }
            DWORD dataLen = 0;
            status = NCryptGetProperty(handle, propID, NULL, 0, &dataLen, 0);
            if (status) {
                FreeKey(handle);
                THROW_MSCAPI_CODE_ERROR(MSCAPI_EXCEPTION_NAME, "CryptGetProvParam", status);
            }
            res->resize(dataLen);
            status = NCryptGetProperty(handle, propID, res->data(), res->size(), &dataLen, 0);
            if (status) {
                FreeKey(handle);
                THROW_MSCAPI_CODE_ERROR(MSCAPI_EXCEPTION_NAME, "CryptGetProvParam", status);
            }
        }
        else {
            // CAPI
            DWORD dataLen = 0;
            if (!CryptGetProvParam(handle, dwParam, NULL, &dataLen, 0)) {
                status = GetLastError();
                FreeKey(handle);
                THROW_MSCAPI_CODE_ERROR(MSCAPI_EXCEPTION_NAME, "CryptGetProvParam", status);
            }
            res->resize(dataLen);
            if (!CryptGetProvParam(handle, dwParam, res->data(), &dataLen, 0)) {
                status = GetLastError();
                FreeKey(handle);
                THROW_MSCAPI_CODE_ERROR(MSCAPI_EXCEPTION_NAME, "CryptGetProvParam", status);
            }
        }

        return res;
    }
    CATCH_EXCEPTION
}
<|endoftext|>