Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include <iostream>
- #include <algorithm>
- #include <cassert>
- #include <memory>
- #include <map>
- #include <vector>
- #include <set>
- // 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
- // Thanks to use of wrapper the logic of virus node and connections between nodes are separated
- template <class Virus>
- class VirusGenealogyWrapper {
- Virus virus;
- public:
- // Children and parents sets contain smart pointers to appropriate virus nodes.
- // Due to parents set graph is no longer directed (as in description), but the logic of a program is the same.
- std::set<std::shared_ptr<VirusGenealogyWrapper<Virus>>> children;
- std::set<std::shared_ptr<VirusGenealogyWrapper<Virus>>> parents;
- VirusGenealogyWrapper(typename Virus::id_type id) : virus(id) {}
- Virus& getVirus() {
- return virus;
- }
- };
- // 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;
- public:
- // 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.insert(std::make_pair(stem_id, std::make_shared<VirusGenealogyWrapper<Virus> > (stem_id)));
- }
- // Requirements say that any attempt to use copy constructor...
- VirusGenealogy(const VirusGenealogy &) = delete;
- // or assignment operator for objects of class VirusGenealogy should result in compilation error
- VirusGenealogy & operator=(const VirusGenealogy &) = delete;
- VirusGenealogy & operator=(VirusGenealogy &&) = delete;
- // 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 successors (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
- {
- if(!exists(id)) {
- throw VirusNotFound();
- }
- std::vector<typename Virus::id_type> children;
- for (auto c : virus_map.find(id)->second->children) {
- children.push_back(c->getVirus().get_id());
- }
- return children;
- }
- // Returns the vector containing id's of immediate prodecessors (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
- {
- if(!exists(id)) {
- throw VirusNotFound();
- }
- std::vector<typename Virus::id_type> parents;
- for (auto p : virus_map.find(id)->second->parents) {
- parents.push_back(p->getVirus().get_id());
- }
- return parents;
- }
- // 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();
- }
- if(!exists(parent_id)) {
- throw VirusNotFound();
- }
- // Creates new virus as a pair of id and smart pointer to its wrapper to be inserted to virus_map:
- std::pair<typename Virus::id_type, std::shared_ptr<VirusGenealogyWrapper<Virus>>>
- n(id, std::make_shared<VirusGenealogyWrapper<Virus> >(id));
- // Inserts new pair into virus_map;
- virus_map.insert(n);
- // Adds to new virus wrapper's parents list pointer to node of given "parent_id":
- n.second->parents.insert(virus_map.find(parent_id)->second);
- // After insertion the parent wrapper's children list must be appended fresh virus node:
- virus_map.find(parent_id)->second->children.insert(virus_map.find(id)->second);
- //TODO exceptions during second operation!
- }
- // 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();
- }
- if (parent_ids.empty()) {
- throw VirusNotFound();
- }
- for(typename Virus::id_type id : parent_ids) {
- if(!exists(id)) {
- throw VirusNotFound();
- }
- }
- // Creates new virus as a pair of id and smart pointer to its wrapper to be inserted to virus_map:
- std::pair<typename Virus::id_type, std::shared_ptr<VirusGenealogyWrapper<Virus>>>
- n(id, std::make_shared<VirusGenealogyWrapper<Virus> >(id));
- // Inserts new pair into virus_map;
- virus_map.insert(n);
- // For every given parent...
- for (auto parent_id : parent_ids) {
- // Adds to new virus wrapper's parents list pointer to node of given "parent_id":
- n.second->parents.insert(virus_map.find(parent_id)->second);
- // After insertion the parent wrapper's children list must be appended fresh virus node:
- virus_map.find(parent_id)->second->children.insert(virus_map.find(id)->second);
- }
- //TODO exceptions during second operation!
- }
- // Adds a new edge in genealogy graph 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();
- }
- // Explanation: for found child/parent node in set, by its pointer to wrapper (second in pair),
- // it appends wrapper's list of parents/children with pointer to parent/children of given id:
- virus_map.find(parent_id)->second->children.insert(virus_map.find(child_id)->second);
- virus_map.find(child_id)->second->parents.insert(virus_map.find(parent_id)->second);
- }
- //TODO remove
- };
Add Comment
Please, Sign In to add comment