smutnyjoe

Untitled

Dec 14th, 2016
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.76 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include <iostream>
  4. #include <algorithm>
  5. #include <cassert>
  6. #include <memory>
  7. #include <map>
  8. #include <vector>
  9. #include <set>
  10.  
  11. // 1. All needed exception classes:
  12.  
  13. class VirusNotFound : public std::exception {
  14. public:
  15.     char const * what() const throw() {
  16.         return "Exception: VirusNotFound";
  17.     }
  18. };
  19.  
  20. class VirusAlreadyCreated : public std::exception {
  21. public:
  22.     char const * what () const throw() {
  23.         return "Exception: VirusAlreadyCreated";
  24.     }
  25. };
  26.  
  27. class TriedToRemoveStemVirus : public std::exception {
  28. public:
  29.     char const * what () const throw() {
  30.         return "Exception: TriedToRemoveStemVirus";
  31.     }
  32. };
  33.  
  34.  
  35. // 2. Wrapper class for VirusGenealogy with additional containers with parents and children of the virus
  36. //    Thanks to use of wrapper the logic of virus node and connections between nodes are separated
  37.  
  38. template <class Virus>
  39. class VirusGenealogyWrapper {
  40.     Virus virus;
  41.  
  42. public:
  43.     // Children and parents sets contain smart pointers to appropriate virus nodes.
  44.     // Due to parents set graph is no longer directed (as in description), but the logic of a program is the same.
  45.     std::set<std::shared_ptr<VirusGenealogyWrapper<Virus>>> children;
  46.     std::set<std::shared_ptr<VirusGenealogyWrapper<Virus>>> parents;
  47.  
  48.     VirusGenealogyWrapper(typename Virus::id_type id) : virus(id) {}
  49.  
  50.     Virus& getVirus() {
  51.         return virus;
  52.     }
  53.  
  54. };
  55.  
  56.  
  57. // 3. The main class of VirusGenealogy:
  58.  
  59. template <class Virus>
  60. class VirusGenealogy {
  61. private:
  62.  
  63.     const typename Virus::id_type _stem_id;
  64.     std::map<typename Virus::id_type, std::shared_ptr<VirusGenealogyWrapper<Virus>>> virus_map;
  65.  
  66. public:
  67.  
  68.     // Creates new genealogy.
  69.     // Creates new stem virus with id "stem_id".
  70.     // Implementation note: inserts new pair of stem_id and shared pointer to it into just initialized virus_map.
  71.     VirusGenealogy(typename Virus::id_type const &stem_id)
  72.             : _stem_id(stem_id)
  73.     {
  74.         virus_map.insert(std::make_pair(stem_id, std::make_shared<VirusGenealogyWrapper<Virus> > (stem_id)));
  75.     }
  76.  
  77.     // Requirements say that any attempt to use copy constructor...
  78.     VirusGenealogy(const VirusGenealogy &) = delete;
  79.     // or assignment operator for objects of class VirusGenealogy should result in compilation error
  80.     VirusGenealogy & operator=(const VirusGenealogy &) = delete;
  81.     VirusGenealogy & operator=(VirusGenealogy &&) = delete;
  82.  
  83.     // Returns id of stem virus.
  84.     typename Virus::id_type get_stem_id() const
  85.     {
  86.         return _stem_id;
  87.     }
  88.  
  89.     // Returns logical value dependent on if virus of given id exists.
  90.     bool exists(typename Virus::id_type const &id) const
  91.     {
  92.         return virus_map.find(id) != virus_map.end();
  93.     }
  94.  
  95.     // Returns the vector containing id's of immediate successors (i.e. children) of the virus of given id.
  96.     // Throws VirusNotFound exception if virus of given id doesn't exist.
  97.     std::vector<typename Virus::id_type> get_children(typename Virus::id_type const &id) const
  98.     {
  99.         if(!exists(id)) {
  100.             throw VirusNotFound();
  101.         }
  102.  
  103.         std::vector<typename Virus::id_type> children;
  104.         for (auto c : virus_map.find(id)->second->children) {
  105.             children.push_back(c->getVirus().get_id());
  106.         }
  107.  
  108.         return children;
  109.     }
  110.  
  111.     // Returns the vector containing id's of immediate prodecessors (i.e. parents) of the virus of given id.
  112.     // Throws VirusNotFound exception if virus of given id doesn't exist.
  113.     std::vector<typename Virus::id_type> get_parents(typename Virus::id_type const &id) const
  114.     {
  115.         if(!exists(id)) {
  116.             throw VirusNotFound();
  117.         }
  118.  
  119.         std::vector<typename Virus::id_type> parents;
  120.         for (auto p : virus_map.find(id)->second->parents) {
  121.             parents.push_back(p->getVirus().get_id());
  122.         }
  123.  
  124.         return parents;
  125.     }
  126.  
  127.     // Returns reference to object representing virus of given id.
  128.     // Throws VirusNotFound exception if virus of given id doesn't exist.
  129.     Virus& operator[](typename Virus::id_type const &id) const
  130.     {
  131.         if(!exists(id)) {
  132.             throw VirusNotFound();
  133.         }
  134.  
  135.         return virus_map.find(id)->second->getVirus();
  136.     }
  137.  
  138.     // Creates node representing virus of given id by constructing it from one parent.
  139.     // Throws VirusAlreadyCreated if virus of given id already exists.
  140.     // Throws VirusNotFound if given parent doesn't exist.
  141.     void create(typename Virus::id_type const &id, typename Virus::id_type const &parent_id)
  142.     {
  143.         if (exists(id)) {
  144.             throw VirusAlreadyCreated();
  145.         }
  146.  
  147.         if(!exists(parent_id)) {
  148.             throw VirusNotFound();
  149.         }
  150.  
  151.         // Creates new virus as a pair of id and smart pointer to its wrapper to be inserted to virus_map:
  152.         std::pair<typename Virus::id_type, std::shared_ptr<VirusGenealogyWrapper<Virus>>>
  153.                 n(id, std::make_shared<VirusGenealogyWrapper<Virus> >(id));
  154.         // Inserts new pair into virus_map;
  155.         virus_map.insert(n);
  156.         // Adds to new virus wrapper's parents list pointer to node of given "parent_id":
  157.         n.second->parents.insert(virus_map.find(parent_id)->second);
  158.         // After insertion the parent wrapper's children list must be appended fresh virus node:
  159.         virus_map.find(parent_id)->second->children.insert(virus_map.find(id)->second);
  160.         //TODO exceptions during second operation!
  161.     }
  162.  
  163.     // Creates node representing virus of given id by constructing it from vector of parents.
  164.     // Throws VirusAlreadyCreated if virus of given id already exists.
  165.     // Throws VirusNotFound if any of given parents doesn't exist.
  166.     void create(typename Virus::id_type const &id, std::vector<typename Virus::id_type> const &parent_ids)
  167.     {
  168.         if (exists(id)) {
  169.             throw VirusAlreadyCreated();
  170.         }
  171.  
  172.         if (parent_ids.empty()) {
  173.             throw VirusNotFound();
  174.         }
  175.  
  176.         for(typename Virus::id_type id : parent_ids) {
  177.             if(!exists(id)) {
  178.                 throw VirusNotFound();
  179.             }
  180.         }
  181.  
  182.         // Creates new virus as a pair of id and smart pointer to its wrapper to be inserted to virus_map:
  183.         std::pair<typename Virus::id_type, std::shared_ptr<VirusGenealogyWrapper<Virus>>>
  184.                 n(id, std::make_shared<VirusGenealogyWrapper<Virus> >(id));
  185.         // Inserts new pair into virus_map;
  186.         virus_map.insert(n);
  187.  
  188.         // For every given parent...
  189.         for (auto parent_id : parent_ids) {
  190.             // Adds to new virus wrapper's parents list pointer to node of given "parent_id":
  191.             n.second->parents.insert(virus_map.find(parent_id)->second);
  192.             // After insertion the parent wrapper's children list must be appended fresh virus node:
  193.             virus_map.find(parent_id)->second->children.insert(virus_map.find(id)->second);
  194.         }
  195.         //TODO exceptions during second operation!
  196.     }
  197.  
  198.  
  199.     // Adds a new edge in genealogy graph between virus with "child_id" and virus with "parent_id".
  200.     // Throws VirusNotFound exception if any of viruses doesn't exist.
  201.     void connect(typename Virus::id_type const &child_id, typename Virus::id_type const &parent_id)
  202.     {
  203.         if (!exists(child_id) || (!exists(parent_id))) {
  204.             throw VirusNotFound();
  205.         }
  206.  
  207.         // Explanation: for found child/parent node in set, by its pointer to wrapper (second in pair),
  208.         // it appends wrapper's list of parents/children with pointer to parent/children of given id:
  209.         virus_map.find(parent_id)->second->children.insert(virus_map.find(child_id)->second);
  210.         virus_map.find(child_id)->second->parents.insert(virus_map.find(parent_id)->second);
  211.     }
  212.  
  213.     //TODO remove
  214.  
  215. };
Add Comment
Please, Sign In to add comment