smutnyjoe

Untitled

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