Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include <map>
- #include <cassert>
- #include <algorithm>
- #include <vector>
- #include <set>
- #include <memory>
- // 1. All needed exception classes:
- class VirusNotFound : public std::exception {
- public:
- char const * what() const throw() {
- return "Exception: VirusNotFound";
- }
- };
- class VirusAlreadyCreated : public std::exception {
- public:
- char const * what () const throw() {
- return "Exception: VirusAlreadyCreated";
- }
- };
- class TriedToRemoveStemVirus : public std::exception {
- public:
- char const * what () const throw() {
- return "Exception: TriedToRemoveStemVirus";
- }
- };
- // 2. Wrapper class for VirusGenealogy with additional containers with parents and children of the virus
- // and functions that return vectors of parents and children (for use by VirusGenealogy implementation)
- //TODO byc moze wlozyc to w jakiegos namespace'a
- template <class Virus>
- class VirusGenealogyWrapper {
- Virus virus;
- // Children and parents are converted to vector when returned, but elements are held in set due to search complexity
- // demand to be faster than O(n) that vector offers.
- typedef std::set<typename Virus::id_type> container;
- container children;
- container parents;
- VirusGenealogyWrapper(typename Virus::id_type id) :
- virus(id), //a virus itself
- children(), //with a empty container of children
- parents() //and parents
- {}
- Virus& getVirus() {
- return virus;
- }
- // Simply creates vector of all elements in container children //TODO a może od razu trzymać w wektorze a nie secie?
- std::vector<typename Virus::id_type> getChildren() {
- std::vector<typename Virus::id_type> vector;
- std::copy(children.begin(), children.end(), std::back_inserter(vector));
- return vector;
- }
- // Simply creates vector of all elements in container parents //TODO a może od razu trzymać w wektorze a nie secie?
- std::vector<typename Virus::id_type> getParents() {
- std::vector<typename Virus::id_type> vector;
- std::copy(parents.begin(), parents.end(), std::back_inserter(vector));
- return vector;
- }
- };
- // 3. The main class of VirusGenealogy:
- template <class Virus>
- class VirusGenealogy
- {
- private :
- const typename Virus::id_type _stem_id;
- std::map<typename Virus::id_type, std::shared_ptr<VirusGenealogyWrapper<Virus>>> virus_map;
- // for simplicity when adding elements to the virus_map in functions:
- typedef std::pair<typename Virus::id_type, std::shared_ptr<VirusGenealogyWrapper<Virus>>> virus_map_pair;
- public :
- //TODO * próba użycia konstruktora kopiującego lub operatora przypisania dla obiektów klasy VirusGenealogy powinna zakończyć się błędem kompilacji;
- // Creates new genealogy.
- // Creates new stem virus with id "stem_id".
- // Implementation note: inserts new pair of stem_id and shared pointer to it into just initialized virus_map.
- VirusGenealogy(typename Virus::id_type const &stem_id) : _stem_id(stem_id), virus_map()
- {
- virus_map_pair new_pair = std::make_pair(stem_id, std::make_shared<VirusGenealogyWrapper<Virus>>);
- virus_map.insert(new_pair);
- }
- // Returns id of stem virus.
- typename Virus::id_type get_stem_id() const
- {
- return _stem_id;
- }
- // Returns logical value dependent on if virus of given id exists.
- bool exists(typename Virus::id_type const &id) const
- {
- return virus_map.find(id) != virus_map.end();
- }
- // Returns the vector containing id's of immediate descendants (i.e. children) of the virus of given id.
- // Throws VirusNotFound exception if virus of given id doesn't exist.
- std::vector<typename Virus::id_type> get_children(typename Virus::id_type const &id) const
- {
- // Checks if virus of given id exists:
- if(!exists(id)) {
- throw VirusNotFound();
- }
- // Found virus points to element in virus_map which second element points to wrapper of the virus which children
- // we want to return
- return virus_map.find(id)->second.getChildren();
- }
- // Returns the vector containing id's of immediate ancestors (i.e. parents) of the virus of given id.
- // Throws VirusNotFound exception if virus of given id doesn't exist.
- std::vector<typename Virus::id_type> get_parents(typename Virus::id_type const &id) const
- {
- // Checks if virus of given id exists:
- if(!exists(id)) {
- throw VirusNotFound();
- }
- // Found virus points to element in virus_map which second element points to wrapper of the virus which parents
- // we want to return
- return virus_map.find(id)->second.getParents();
- }
- // Returns reference to object representing virus of given id.
- // Throws VirusNotFound exception if virus of given id doesn't exist.
- Virus& operator[](typename Virus::id_type const &id) const
- {
- if(!exists(id)) {
- throw VirusNotFound();
- }
- return virus_map.find(id)->second->getVirus();
- }
- // Creates node representing virus of given id by constructing it from one parent.
- // Throws VirusAlreadyCreated if virus of given id already exists.
- // Throws VirusNotFound if given parent doesn't exist.
- void create(typename Virus::id_type const &id, typename Virus::id_type const &parent_id)
- {
- if (exists(id)) {
- throw VirusAlreadyCreated();
- }
- else if(!exists(parent_id)) {
- throw VirusNotFound();
- }
- else {
- auto new_virus = virus_map.find(id)->getVirus();
- auto new_virus_parent = virus_map.find(parent_id)->getVirus();
- // Creates pair of new virus and smart pointer to it to be inserted into virus_map.
- virus_map_pair new_pair = std::make_pair(id, std::make_shared<VirusGenealogyWrapper<Virus>>(new_virus));
- // Inserts newly created pair into virus_map:
- virus_map.insert(new_pair);
- // When new virus is inserted into the map, its parent's children container must be appended:
- virus_map.find(parent_id)->second->children.insert
- (std::make_shared<VirusGenealogyWrapper<Virus>>(new_virus));
- // When new virus is inserted into the map, its parent has to be inserted into virus' parents container:
- virus_map_pair virus_parent_pair =
- std::make_pair(parent_id, std::make_shared<VirusGenealogyWrapper<Virus>>(new_virus_parent));
- new_pair.first->second->parents.insert(virus_parent_pair);
- //TODO inserty do kontenerów parents i children mogą rzucić wyjątkiem - co wtedy bo do rodzica wlozone jest dziecko a do dziecka nie udalo sie wlozyc rodzica
- }
- }
- // Creates node representing virus of given id by constructing it from vector of parents.
- // Throws VirusAlreadyCreated if virus of given id already exists.
- // Throws VirusNotFound if any of given parents doesn't exist.
- void create(typename Virus::id_type const &id, std::vector<typename Virus::id_type> const &parent_ids)
- {
- if (exists(id)) {
- throw VirusAlreadyCreated();
- }
- else if(parent_ids.empty() ||
- !std::all_of(parent_ids.begin(), parent_ids.end(),
- [this](typename Virus::id_type id){ return exists(id);})) {
- // If not all of viruses in parent_ids vector fulfill the predicate exists(id) == true then not all of given
- // parents exist in virus_map.
- //TODO nie wiem czy to jest dobrze nigdy tak nie robiłem :D http://www.cplusplus.com/reference/algorithm/all_of/
- throw VirusNotFound();
- }
- else {
- auto new_virus = virus_map.find(id)->getVirus();
- // Creates pair of new virus and smart pointer to it to be inserted into virus_map.
- virus_map_pair new_pair = std::make_pair(id, std::make_shared<VirusGenealogyWrapper<Virus>>(new_virus));
- // Inserts newly created pair into virus_map:
- virus_map.insert(new_pair);
- //TODO nie wiem czy karkolomna konstrukcja ponizej zadziala
- for(auto parent_id_ : parent_ids) {
- auto new_virus_parent = virus_map.find(parent_id_)->getVirus();
- // When new virus is inserted into the map, its parent's children container must be appended:
- virus_map.find(parent_id_)->second->children.insert
- (std::make_shared<VirusGenealogyWrapper<Virus>>(new_virus));
- // When new virus is inserted into the map, its parent has to be inserted into virus' parents container:
- virus_map_pair virus_parent_pair =
- std::make_pair(parent_id_, std::make_shared<VirusGenealogyWrapper<Virus>>(new_virus_parent));
- new_pair.first->second->parents.insert(virus_parent_pair);
- }
- //TODO trzeba zlapac wyjatek z drugiego inserta bo gdy sie nie powiedzie rodzic bedzie mial nowe dziecko a dziecko nie bedzie mialo rodzica
- }
- }
- // Adds a new edge in genealogy tree between virus with "child_id" and virus with "parent_id".
- // Throws VirusNotFound exception if any of viruses doesn't exist.
- void connect(typename Virus::id_type const &child_id, typename Virus::id_type const &parent_id)
- {
- if (!exists(child_id) || (!exists(parent_id))) {
- throw VirusNotFound();
- }
- //TODO co jesli krawedz juz istnieje?
- else {
- // Adding the child to the parent's children list:
- virus_map.find(parent_id)->second->children.insert(
- std::make_shared<VirusGenealogyWrapper<Virus>>(virus_map.find(child_id)));
- // Adding the parent to the child's parents list:
- virus_map.find(child_id)->second->parent.insert(
- std::make_shared<VirusGenealogyWrapper<Virus>>(virus_map.find(parent_id)));
- //TODO trzeba zlapac wyjatek z drugiego inserta bo gdy sie nie powiedzie rodzic bedzie mial nowe dziecko a dziecko nie bedzie mialo rodzica
- }
- }
- // Removes virus of given id.
- // Throws VirusNotFound exception if virus of given id doesn't exist.
- // Throws TriedToRemoveStemVirus if virus of given id is stem virus.
- void remove(typename Virus::id_type const &id)
- {
- if (!exists(id)) {
- throw VirusNotFound();
- }
- else if (id == _stem_id) {
- throw TriedToRemoveStemVirus();
- }
- else {
- // TODO jeszcze nie wiem jak ma dzialac usuniecie
- //
- // for (typename Virus::id_type parent : parents[id])
- // children[parent].erase(id);
- // for (typename Virus::id_type child : children[id])
- // parents[child].erase(id);
- // parents.erase(id);
- // children.erase(id);
- }
- }
- };
Add Comment
Please, Sign In to add comment