smutnyjoe

Untitled

Dec 14th, 2016
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.05 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include <map>
  4. #include <cassert>
  5. #include <algorithm>
  6. #include <vector>
  7. #include <set>
  8. #include <memory>
  9.  
  10. // 1. All needed exception classes:
  11.  
  12. class VirusNotFound : public std::exception {
  13. public:
  14.     char const * what() const throw() {
  15.         return "Exception: VirusNotFound";
  16.     }
  17. };
  18.  
  19. class VirusAlreadyCreated : public std::exception {
  20. public:
  21.     char const * what () const throw() {
  22.         return "Exception: VirusAlreadyCreated";
  23.     }
  24. };
  25.  
  26. class TriedToRemoveStemVirus : public std::exception {
  27. public:
  28.     char const * what () const throw() {
  29.         return "Exception: TriedToRemoveStemVirus";
  30.     }
  31. };
  32.  
  33.  
  34. // 2. Wrapper class for VirusGenealogy with additional containers with parents and children of the virus
  35. //    and functions that return vectors of parents and children (for use by VirusGenealogy implementation)
  36. //TODO byc moze wlozyc to w jakiegos namespace'a
  37.  
  38. template <class Virus>
  39. class VirusGenealogyWrapper {
  40.     Virus virus;
  41.  
  42.     // Children and parents are converted to vector when returned, but elements are held in set due to search complexity
  43.     // demand to be faster than O(n) that vector offers.
  44.     typedef std::set<typename Virus::id_type> container;
  45.     container children;
  46.     container parents;
  47.  
  48.     VirusGenealogyWrapper(typename Virus::id_type id) :
  49.             virus(id), //a virus itself
  50.             children(), //with a empty container of children
  51.             parents() //and parents
  52.     {}
  53.  
  54.     Virus& getVirus() {
  55.         return virus;
  56.     }
  57.  
  58.     // Simply creates vector of all elements in container children //TODO a może od razu trzymać w wektorze a nie secie?
  59.     std::vector<typename Virus::id_type> getChildren() {
  60.         std::vector<typename Virus::id_type> vector;
  61.         std::copy(children.begin(), children.end(), std::back_inserter(vector));
  62.         return vector;
  63.     }
  64.  
  65.     // Simply creates vector of all elements in container parents //TODO a może od razu trzymać w wektorze a nie secie?
  66.     std::vector<typename Virus::id_type> getParents() {
  67.         std::vector<typename Virus::id_type> vector;
  68.         std::copy(parents.begin(), parents.end(), std::back_inserter(vector));
  69.         return vector;
  70.     }
  71.  
  72. };
  73.  
  74.  
  75. // 3. The main class of VirusGenealogy:
  76.  
  77. template <class Virus>
  78. class VirusGenealogy
  79. {
  80.  
  81. private :
  82.     const typename Virus::id_type _stem_id;
  83.     std::map<typename Virus::id_type, std::shared_ptr<VirusGenealogyWrapper<Virus>>> virus_map;
  84.  
  85.     // for simplicity when adding elements to the virus_map in functions:
  86.     typedef std::pair<typename Virus::id_type, std::shared_ptr<VirusGenealogyWrapper<Virus>>> virus_map_pair;
  87.  
  88.  
  89. public :
  90.     //TODO * próba użycia konstruktora kopiującego lub operatora przypisania dla obiektów klasy VirusGenealogy powinna zakończyć się błędem kompilacji;
  91.  
  92.     // Creates new genealogy.
  93.     // Creates new stem virus with id "stem_id".
  94.     // Implementation note: inserts new pair of stem_id and shared pointer to it into just initialized virus_map.
  95.     VirusGenealogy(typename Virus::id_type const &stem_id) : _stem_id(stem_id), virus_map()
  96.     {
  97.         virus_map_pair new_pair = std::make_pair(stem_id, std::make_shared<VirusGenealogyWrapper<Virus>>);
  98.         virus_map.insert(new_pair);
  99.     }
  100.  
  101.     // Returns id of stem virus.
  102.     typename Virus::id_type get_stem_id() const
  103.     {
  104.         return _stem_id;
  105.     }
  106.  
  107.     // Returns logical value dependent on if virus of given id exists.
  108.     bool exists(typename Virus::id_type const &id) const
  109.     {
  110.         return virus_map.find(id) != virus_map.end();
  111.     }
  112.  
  113.     // Returns the vector containing id's of immediate descendants (i.e. children) of the virus of given id.
  114.     // Throws VirusNotFound exception if virus of given id doesn't exist.
  115.     std::vector<typename Virus::id_type> get_children(typename Virus::id_type const &id) const
  116.     {
  117.         // Checks if virus of given id exists:
  118.         if(!exists(id)) {
  119.             throw VirusNotFound();
  120.         }
  121.  
  122.         // Found virus points to element in virus_map which second element points to wrapper of the virus which children
  123.         // we want to return
  124.         return virus_map.find(id)->second.getChildren();
  125.     }
  126.  
  127.     // Returns the vector containing id's of immediate ancestors (i.e. parents) of the virus of given id.
  128.     // Throws VirusNotFound exception if virus of given id doesn't exist.
  129.     std::vector<typename Virus::id_type> get_parents(typename Virus::id_type const &id) const
  130.     {
  131.         // Checks if virus of given id exists:
  132.         if(!exists(id)) {
  133.             throw VirusNotFound();
  134.         }
  135.  
  136.         // Found virus points to element in virus_map which second element points to wrapper of the virus which parents
  137.         // we want to return
  138.         return virus_map.find(id)->second.getParents();
  139.     }
  140.  
  141.     // Returns reference to object representing virus of given id.
  142.     // Throws VirusNotFound exception if virus of given id doesn't exist.
  143.     Virus& operator[](typename Virus::id_type const &id) const
  144.     {
  145.         if(!exists(id)) {
  146.             throw VirusNotFound();
  147.         }
  148.  
  149.         return virus_map.find(id)->second->getVirus();
  150.     }
  151.  
  152.     // Creates node representing virus of given id by constructing it from one parent.
  153.     // Throws VirusAlreadyCreated if virus of given id already exists.
  154.     // Throws VirusNotFound if given parent doesn't exist.
  155.     void create(typename Virus::id_type const &id, typename Virus::id_type const &parent_id)
  156.     {
  157.         if (exists(id)) {
  158.             throw VirusAlreadyCreated();
  159.         }
  160.         else if(!exists(parent_id)) {
  161.             throw VirusNotFound();
  162.         }
  163.         else {
  164.             auto new_virus = virus_map.find(id)->getVirus();
  165.             auto new_virus_parent = virus_map.find(parent_id)->getVirus();
  166.  
  167.             // Creates pair of new virus and smart pointer to it to be inserted into virus_map.
  168.             virus_map_pair new_pair = std::make_pair(id, std::make_shared<VirusGenealogyWrapper<Virus>>(new_virus));
  169.  
  170.             // Inserts newly created pair into virus_map:
  171.             virus_map.insert(new_pair);
  172.  
  173.             // When new virus is inserted into the map, its parent's children container must be appended:
  174.             virus_map.find(parent_id)->second->children.insert
  175.                     (std::make_shared<VirusGenealogyWrapper<Virus>>(new_virus));
  176.  
  177.             // When new virus is inserted into the map, its parent has to be inserted into virus' parents container:
  178.             virus_map_pair virus_parent_pair =
  179.                     std::make_pair(parent_id, std::make_shared<VirusGenealogyWrapper<Virus>>(new_virus_parent));
  180.             new_pair.first->second->parents.insert(virus_parent_pair);
  181.  
  182.             //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
  183.         }
  184.     }
  185.  
  186.     // Creates node representing virus of given id by constructing it from vector of parents.
  187.     // Throws VirusAlreadyCreated if virus of given id already exists.
  188.     // Throws VirusNotFound if any of given parents doesn't exist.
  189.     void create(typename Virus::id_type const &id, std::vector<typename Virus::id_type> const &parent_ids)
  190.     {
  191.         if (exists(id)) {
  192.             throw VirusAlreadyCreated();
  193.         }
  194.         else if(parent_ids.empty() ||
  195.                 !std::all_of(parent_ids.begin(), parent_ids.end(),
  196.                              [this](typename Virus::id_type id){ return exists(id);})) {
  197.             // If not all of viruses in parent_ids vector fulfill the predicate exists(id) == true then not all of given
  198.             // parents exist in virus_map.
  199.             //TODO nie wiem czy to jest dobrze nigdy tak nie robiłem :D http://www.cplusplus.com/reference/algorithm/all_of/
  200.             throw VirusNotFound();
  201.         }
  202.         else {
  203.             auto new_virus = virus_map.find(id)->getVirus();
  204.  
  205.             // Creates pair of new virus and smart pointer to it to be inserted into virus_map.
  206.             virus_map_pair new_pair = std::make_pair(id, std::make_shared<VirusGenealogyWrapper<Virus>>(new_virus));
  207.  
  208.             // Inserts newly created pair into virus_map:
  209.             virus_map.insert(new_pair);
  210.  
  211.             //TODO nie wiem czy karkolomna konstrukcja ponizej zadziala
  212.             for(auto parent_id_ : parent_ids) {
  213.                 auto new_virus_parent = virus_map.find(parent_id_)->getVirus();
  214.                 // When new virus is inserted into the map, its parent's children container must be appended:
  215.                 virus_map.find(parent_id_)->second->children.insert
  216.                         (std::make_shared<VirusGenealogyWrapper<Virus>>(new_virus));
  217.  
  218.                 // When new virus is inserted into the map, its parent has to be inserted into virus' parents container:
  219.                 virus_map_pair virus_parent_pair =
  220.                         std::make_pair(parent_id_, std::make_shared<VirusGenealogyWrapper<Virus>>(new_virus_parent));
  221.                 new_pair.first->second->parents.insert(virus_parent_pair);
  222.             }
  223.  
  224.             //TODO trzeba zlapac wyjatek z drugiego inserta bo gdy sie nie powiedzie rodzic bedzie mial nowe dziecko a dziecko nie bedzie mialo rodzica
  225.         }
  226.     }
  227.  
  228.  
  229.     // Adds a new edge in genealogy tree between virus with "child_id" and virus with "parent_id".
  230.     // Throws VirusNotFound exception if any of viruses doesn't exist.
  231.     void connect(typename Virus::id_type const &child_id, typename Virus::id_type const &parent_id)
  232.     {
  233.         if (!exists(child_id) || (!exists(parent_id))) {
  234.             throw VirusNotFound();
  235.         }
  236.             //TODO co jesli krawedz juz istnieje?
  237.         else {
  238.             // Adding the child to the parent's children list:
  239.             virus_map.find(parent_id)->second->children.insert(
  240.                     std::make_shared<VirusGenealogyWrapper<Virus>>(virus_map.find(child_id)));
  241.             // Adding the parent to the child's parents list:
  242.             virus_map.find(child_id)->second->parent.insert(
  243.                     std::make_shared<VirusGenealogyWrapper<Virus>>(virus_map.find(parent_id)));
  244.             //TODO trzeba zlapac wyjatek z drugiego inserta bo gdy sie nie powiedzie rodzic bedzie mial nowe dziecko a dziecko nie bedzie mialo rodzica
  245.         }
  246.     }
  247.  
  248.     // Removes virus of given id.
  249.     // Throws VirusNotFound exception if virus of given id doesn't exist.
  250.     // Throws TriedToRemoveStemVirus if virus of given id is stem virus.
  251.     void remove(typename Virus::id_type const &id)
  252.     {
  253.         if (!exists(id)) {
  254.             throw VirusNotFound();
  255.         }
  256.         else if (id == _stem_id) {
  257.             throw TriedToRemoveStemVirus();
  258.         }
  259.         else {
  260.  
  261.             // TODO jeszcze nie wiem jak ma dzialac usuniecie
  262. //
  263. //            for (typename Virus::id_type parent : parents[id])
  264. //                children[parent].erase(id);
  265. //            for (typename Virus::id_type child : children[id])
  266. //                parents[child].erase(id);
  267. //            parents.erase(id);
  268. //            children.erase(id);
  269.         }
  270.     }
  271.  
  272. };
Add Comment
Please, Sign In to add comment