--- /dev/null
+#include "AForm.h"
+#include "Bureaucrat.h"
+
+AForm::AForm()
+ : m_name("")
+ , m_is_signed(0)
+ , m_signatory_grade(0)
+ , m_executor_grade(0)
+{
+}
+
+AForm::AForm(const std::string &name, int signatory_grade, int executor_grade, std::string target)
+ : m_name(name)
+ , m_is_signed(0)
+ , m_signatory_grade(signatory_grade)
+ , m_executor_grade(executor_grade)
+ , m_target(target)
+{
+ if (signatory_grade < Bureaucrat::HIGHEST_GRADE || executor_grade < Bureaucrat::HIGHEST_GRADE)
+ throw (Bureaucrat::GradeTooHighException());
+ else if (signatory_grade > Bureaucrat::LOWEST_GRADE || executor_grade > Bureaucrat::LOWEST_GRADE)
+ throw (Bureaucrat::GradeTooLowException());
+}
+
+AForm::AForm(const AForm &other)
+ : m_name(other.m_name)
+ , m_is_signed(0)
+ , m_signatory_grade(other.m_signatory_grade)
+ , m_executor_grade(other.m_executor_grade)
+{
+}
+
+AForm::~AForm() { }
+
+AForm &AForm::operator=(const AForm &other)
+{
+ if (this == &other)
+ return (*this);
+ return (*this);
+}
+
+const std::string &AForm::getName() const
+{
+ return (m_name);
+}
+
+bool AForm::isSigned() const
+{
+ return (m_is_signed);
+}
+
+int AForm::getSignatoryGrade() const
+{
+ return (m_signatory_grade);
+}
+
+int AForm::getExecutorGrade() const
+{
+ return (m_executor_grade);
+}
+
+const std::string &AForm::getTarget() const
+{
+ return (m_target);
+}
+
+void AForm::beSigned(const Bureaucrat &bureaucrat)
+{
+ if (bureaucrat.getGrade() > m_signatory_grade)
+ throw (Bureaucrat::GradeTooLowException());
+ if (m_is_signed)
+ throw (std::runtime_error("AForm is already signed"));
+ m_is_signed = 1;
+}
+
+void AForm::checkExecutorGrade(const Bureaucrat &bureaucrat) const
+{
+ if (!m_is_signed)
+ throw (AForm::FormNotSignedException());
+ if (bureaucrat.getGrade() > m_executor_grade)
+ throw (Bureaucrat::GradeTooLowException());
+}
+
+std::ostream &operator<<(std::ostream &ostream, const AForm &form)
+{
+ ostream << "AForm " << form.getName() << ":\n\n";
+ ostream << "\tMinimum grade of signatory:\t" << form.getSignatoryGrade() << '\n';
+ ostream << "\tMinimum grade of executor:\t" << form.getExecutorGrade() << "\n\n";
+ if (form.isSigned())
+ ostream << "\t\t\t\tBureaucrat\n";
+ else
+ ostream << "\n";
+ ostream << "\t\t\t\tSignature\n";
+ return (ostream);
+}
+
+AForm::FormNotSignedException::FormNotSignedException()
+ : std::runtime_error::runtime_error("The form is not signed")
+{
+}
+
+AForm::FormNotSignedException::FormNotSignedException(const AForm::FormNotSignedException &other)
+ : std::runtime_error::runtime_error(other.what())
+{
+}
+
+AForm::FormNotSignedException::~FormNotSignedException() throw()
+{
+}
+
+AForm::FormNotSignedException &AForm::FormNotSignedException::operator=(const AForm::FormNotSignedException &other)
+{
+ std::runtime_error::operator = (other);
+ return (*this);
+}
--- /dev/null
+#ifndef AFORM_H
+# define AFORM_H
+
+#include "Bureaucrat.h"
+#include <string>
+#include <iostream>
+
+class AForm
+{
+ private:
+ const std::string m_name;
+ bool m_is_signed;
+ const int m_signatory_grade;
+ const int m_executor_grade;
+ const std::string m_target;
+
+ // These are protected only so that inheriting classes can use them
+ // in their "non implementations" of there functions
+ protected:
+ AForm();
+
+ AForm &operator=(const AForm &other);
+
+ public:
+ AForm(const std::string &name, int signatory_grade, int executor_grade, std::string target);
+ AForm(const AForm &other);
+ virtual ~AForm();
+
+ const std::string &getName() const;
+ bool isSigned() const;
+ int getSignatoryGrade() const;
+ int getExecutorGrade() const;
+ const std::string &getTarget() const;
+ void beSigned(const Bureaucrat &bureaucrat);
+ void checkExecutorGrade(const Bureaucrat &bureaucrat) const;
+ void virtual execute(const Bureaucrat &bureaucrat) const = 0;
+
+ class FormNotSignedException;
+};
+
+std::ostream &operator<<(std::ostream &ostream, const AForm &form);
+
+class AForm::FormNotSignedException : public std::runtime_error
+{
+ public:
+ FormNotSignedException();
+ FormNotSignedException(const FormNotSignedException &other);
+ ~FormNotSignedException() throw();
+
+ FormNotSignedException &operator=(const FormNotSignedException &other);
+};
+
+#endif // AFORM_H
--- /dev/null
+#include "Bureaucrat.h"
+#include "AForm.h"
+
+Bureaucrat::Bureaucrat()
+{
+}
+
+Bureaucrat::Bureaucrat(const std::string &name, int grade)
+ : m_name(name)
+ , m_grade(grade)
+{
+ if (grade < HIGHEST_GRADE)
+ throw (Bureaucrat::GradeTooHighException());
+ else if (grade > LOWEST_GRADE)
+ throw (Bureaucrat::GradeTooLowException());
+}
+
+Bureaucrat::Bureaucrat(const Bureaucrat &other)
+{
+ *this = other;
+}
+
+Bureaucrat::~Bureaucrat()
+{
+}
+
+Bureaucrat &Bureaucrat::operator=(const Bureaucrat &other)
+{
+ if (this == &other)
+ return (*this);
+ return (*this);
+}
+
+const std::string &Bureaucrat::getName() const
+{
+ return (m_name);
+}
+
+int Bureaucrat::getGrade() const
+{
+ return (m_grade);
+}
+
+void Bureaucrat::promote()
+{
+ if (m_grade == HIGHEST_GRADE)
+ throw (Bureaucrat::GradeTooHighException());
+ --m_grade;
+}
+
+void Bureaucrat::demote()
+{
+ if (m_grade == LOWEST_GRADE)
+ throw (Bureaucrat::GradeTooLowException());
+ ++m_grade;
+}
+
+void Bureaucrat::signForm(AForm &form) const
+{
+ try
+ {
+ form.beSigned(*this);
+ std::cout << m_name << " signed the form " << form.getName() << '\n';
+ }
+ catch (const Bureaucrat::GradeTooLowException &exception)
+ {
+ std::cout << m_name << " couldn't sign the form " << form.getName()
+ << " because his grade " << m_grade << " is lower than the necessary "
+ << form.getSignatoryGrade() << '\n';
+ }
+ catch (const std::runtime_error &exception)
+ {
+ std::cout << m_name << " couldn't sign the form " << form.getName()
+ << " because it is already signed.\n";
+ }
+}
+
+void Bureaucrat::executeForm(const AForm &form) const
+{
+ try
+ {
+ form.execute(*this);
+ std::cout << m_name << " executed the form " << form.getName() << '\n';
+ }
+ catch (const Bureaucrat::GradeTooLowException &exception)
+ {
+ std::cout << m_name << " couldn't execute the form " << form.getName()
+ << " because his grade " << m_grade << " is lower than the necessary "
+ << form.getSignatoryGrade() << '\n';
+ }
+ catch (const AForm::FormNotSignedException &exception)
+ {
+ std::cout << m_name << " couldn't execute the form " << form.getName()
+ << " because the norm has not yet been signed.\n";
+ }
+}
+
+std::ostream &operator<<(std::ostream &ostream, const Bureaucrat &bureaucrat)
+{
+ ostream << bureaucrat.getName() << ", bureaucrat of grade " << bureaucrat.getGrade();
+ return (ostream);
+}
+
+Bureaucrat::GradeTooLowException::GradeTooLowException()
+ : std::runtime_error::runtime_error("Grade cannot be lower")
+{
+}
+
+Bureaucrat::GradeTooLowException::GradeTooLowException(const Bureaucrat::GradeTooLowException &other)
+ : std::runtime_error::runtime_error(other.what())
+{
+}
+
+Bureaucrat::GradeTooLowException::~GradeTooLowException() throw()
+{
+}
+
+Bureaucrat::GradeTooLowException &Bureaucrat::GradeTooLowException::operator=(const Bureaucrat::GradeTooLowException &other)
+{
+ std::runtime_error::operator = (other);
+ return (*this);
+}
+
+Bureaucrat::GradeTooHighException::GradeTooHighException()
+ : std::runtime_error::runtime_error("Grade cannot be higher")
+{
+}
+
+Bureaucrat::GradeTooHighException::GradeTooHighException(const Bureaucrat::GradeTooHighException &other)
+ : std::runtime_error::runtime_error(other.what())
+{
+}
+
+Bureaucrat::GradeTooHighException::~GradeTooHighException() throw()
+{
+}
+
+Bureaucrat::GradeTooHighException &Bureaucrat::GradeTooHighException::operator=(const Bureaucrat::GradeTooHighException &other)
+{
+ std::runtime_error::operator = (other);
+ return (*this);
+}
--- /dev/null
+#ifndef BUREAUCRAT_H
+# define BUREAUCRAT_H
+
+#include <string>
+#include <stdexcept>
+#include <iostream>
+
+class AForm;
+
+class Bureaucrat
+{
+ private:
+ const std::string m_name;
+ int m_grade;
+
+ Bureaucrat();
+ Bureaucrat(const Bureaucrat &other);
+
+ Bureaucrat &operator=(const Bureaucrat &other);
+
+ public:
+ Bureaucrat(const std::string &name, int grade);
+ ~Bureaucrat();
+
+ static const int LOWEST_GRADE = 150;
+ static const int HIGHEST_GRADE = 1;
+
+ const std::string &getName() const;
+ int getGrade() const;
+ void promote();
+ void demote();
+ void signForm(AForm &form) const;
+ void executeForm(const AForm &form) const;
+
+ class GradeTooLowException;
+ class GradeTooHighException;
+};
+
+std::ostream &operator<<(std::ostream &ostream, const Bureaucrat &bureaucrat);
+
+class Bureaucrat::GradeTooLowException : public std::runtime_error
+{
+ public:
+ GradeTooLowException();
+ GradeTooLowException(const GradeTooLowException &other);
+ ~GradeTooLowException() throw();
+
+ GradeTooLowException &operator=(const GradeTooLowException &other);
+};
+
+class Bureaucrat::GradeTooHighException : public std::runtime_error
+{
+ public:
+ GradeTooHighException();
+ GradeTooHighException(const GradeTooHighException &other);
+ ~GradeTooHighException() throw();
+
+ GradeTooHighException &operator=(const GradeTooHighException &other);
+};
+
+#endif // BUREAUCRAT_H
--- /dev/null
+CC := c++
+CFLAGS = -std=c++98 -Wall -Wextra -Werror -Wpedantic
+
+ifneq ("$(wildcard .debug)","")
+ CFLAGS += -g
+endif
+
+RM := rm -f
+
+INCDIR := inc
+INCDIR += $(addsuffix /inc, $(SUBPROJECTS));
+ifneq ($(INCLUDE),)
+ INCLUDE := $(addprefix -I, $(INCDIR))
+endif
+
+SRCDIR := .
+
+SOURCES := main.cpp \
+ Bureaucrat.cpp \
+ AForm.cpp \
+ ShrubberyCreationForm.cpp \
+ RobotomyRequestForm.cpp \
+ PresidentialPardonForm.cpp \
+
+SOURCES := $(addprefix $(SRCDIR)/, $(SOURCES))
+
+OBJECTS := $(SOURCES:.cpp=.o)
+
+NAME := bureaucrat
+
+all : $(NAME)
+
+debug : .debug
+ $(MAKE) all
+
+nodebug :
+ $(RM) .debug
+ $(MAKE) re
+
+.% :
+ $(MAKE) fclean
+ touch $@
+
+$(NAME) : $(OBJECTS)
+ $(CC) $(CFLAGS) -o $@ $^ $(LINKS)
+
+%.o : %.cpp
+ $(CC) $(CFLAGS) -o $@ -c $< $(INCLUDE)
+
+clean :
+ $(RM) $(OBJECTS)
+
+fclean : clean
+ $(RM) $(NAME)
+
+re : fclean
+ $(MAKE) all
--- /dev/null
+#include "PresidentialPardonForm.h"
+
+PresidentialPardonForm::PresidentialPardonForm()
+ : AForm()
+{
+}
+
+PresidentialPardonForm::PresidentialPardonForm(const std::string &target)
+ : AForm("Presidential Pardon Form", 25, 5, target)
+{
+}
+
+PresidentialPardonForm::PresidentialPardonForm(const PresidentialPardonForm &other)
+ : AForm(other)
+{
+}
+
+PresidentialPardonForm::~PresidentialPardonForm()
+{
+}
+
+void PresidentialPardonForm::execute(Bureaucrat const &executor) const
+{
+ checkExecutorGrade(executor);
+ std::cout << getTarget() << " has been pardoned by Zaphod Beeblebrox.\n";
+}
--- /dev/null
+#ifndef PRESIDENTIALPARDONFORM_H
+# define PRESIDENTIALPARDONFORM_H
+
+#include "AForm.h"
+#include <string>
+
+class PresidentialPardonForm : public AForm
+{
+ // These are protected only so that inheriting classes can use them
+ // in their "non implementations" of there functions
+ protected:
+ PresidentialPardonForm();
+
+ using AForm::operator=;
+
+ public:
+ PresidentialPardonForm(const std::string &target);
+ PresidentialPardonForm(const PresidentialPardonForm &other);
+ ~PresidentialPardonForm();
+
+ void execute(Bureaucrat const &executor) const;
+};
+
+#endif // PRESIDENTIALPARDONFORM_H
--- /dev/null
+#include "RobotomyRequestForm.h"
+#include <iostream>
+#include <cstdlib>
+#include <ctime>
+
+RobotomyRequestForm::RobotomyRequestForm()
+ : AForm()
+{
+}
+
+RobotomyRequestForm::RobotomyRequestForm(const std::string &target)
+ : AForm("Robotomy Request Form", 72, 45, target)
+{
+}
+
+RobotomyRequestForm::RobotomyRequestForm(const RobotomyRequestForm &other)
+ : AForm(other)
+{
+}
+
+RobotomyRequestForm::~RobotomyRequestForm()
+{
+}
+
+void RobotomyRequestForm::execute(Bureaucrat const &executor) const
+{
+ checkExecutorGrade(executor);
+ if (getRandomBit())
+ std::cout << "The robotomy on " << getTarget() << " was successful.\n";
+ else
+ std::cout << "The robotomy on " << getTarget() << " failed.\n";
+}
+
+bool RobotomyRequestForm::getRandomBit()
+{
+ static bool is_seeded = 0;
+
+ if (!is_seeded)
+ {
+ std::srand(std::time(0));
+ is_seeded = 1;
+ }
+ return (std::rand() > (RAND_MAX / 2));
+}
--- /dev/null
+#ifndef ROBOTOMYREQUESTFORM_H
+# define ROBOTOMYREQUESTFORM_H
+
+#include "AForm.h"
+#include <string>
+
+class RobotomyRequestForm : public AForm
+{
+ private:
+ static bool getRandomBit();
+ // These are protected only so that inheriting classes can use them
+ // in their "non implementations" of there functions
+ protected:
+ RobotomyRequestForm();
+
+ using AForm::operator=;
+
+ public:
+ RobotomyRequestForm(const std::string &target);
+ RobotomyRequestForm(const RobotomyRequestForm &other);
+ ~RobotomyRequestForm();
+
+ void execute(Bureaucrat const &executor) const;
+};
+
+#endif // ROBOTOMYREQUESTFORM_H
--- /dev/null
+#include "ShrubberyCreationForm.h"
+#include <string>
+#include <iostream>
+#include <fstream>
+
+ShrubberyCreationForm::ShrubberyCreationForm()
+ : AForm()
+{
+}
+
+ShrubberyCreationForm::ShrubberyCreationForm(const std::string &target)
+ : AForm("Shrubbery Creation Form", 145, 137, target)
+{
+}
+
+ShrubberyCreationForm::ShrubberyCreationForm(const ShrubberyCreationForm &other)
+ : AForm(other)
+{
+}
+
+ShrubberyCreationForm::~ShrubberyCreationForm()
+{
+}
+
+void ShrubberyCreationForm::execute(Bureaucrat const &executor) const
+{
+ std::ofstream target_file;
+
+ checkExecutorGrade(executor);
+ target_file.open((getTarget() + std::string("_shrubbery")).c_str());
+ target_file
+ << " * * \n"
+ << " * o * * o * \n"
+ << " * * * * * * \n"
+ << " * o * * * o * * \n"
+ << " * o o* * * o o* * \n"
+ << " * o * * * o * * \n"
+ << " * # # # * * # # # * \n"
+ << " * ##' * * ##' * \n"
+ << " ### ### \n"
+ << " ### ### \n"
+ << " ,###, ,###, \n"
+ << " ,#####. ,#####. \n";
+ target_file.close();
+}
--- /dev/null
+#ifndef SHRUBBERYCREATIONFORM_H
+# define SHRUBBERYCREATIONFORM_H
+
+#include "AForm.h"
+#include <string>
+
+class ShrubberyCreationForm : public AForm
+{
+ // These are protected only so that inheriting classes can use them
+ // in their "non implementations" of there functions
+ protected:
+ ShrubberyCreationForm();
+
+ using AForm::operator=;
+
+ public:
+ ShrubberyCreationForm(const std::string &target);
+ ShrubberyCreationForm(const ShrubberyCreationForm &other);
+ ~ShrubberyCreationForm();
+
+ void execute(Bureaucrat const &executor) const;
+};
+
+#endif // SHRUBBERYCREATIONFORM_H
--- /dev/null
+#include "Bureaucrat.h"
+#include "AForm.h"
+#include "ShrubberyCreationForm.h"
+#include "RobotomyRequestForm.h"
+#include "PresidentialPardonForm.h"
+#include <iostream>
+
+int main(void)
+{
+ Bureaucrat employee0("Employee0", 1);
+ Bureaucrat employee1("Employee1", 20);
+ Bureaucrat employee2("Employee2", 50);
+ Bureaucrat employee3("Employee3", 140);
+ Bureaucrat employee4("Employee4", 150);
+ ShrubberyCreationForm shrub("test_sh");
+ RobotomyRequestForm robot("test_rob");
+ PresidentialPardonForm pres("test_pres");
+
+ employee4.signForm(shrub);
+ employee3.signForm(robot);
+ employee2.signForm(pres);
+ std::cout << '\n';
+ employee3.executeForm(shrub);
+ employee2.executeForm(robot);
+ employee1.executeForm(pres);
+ std::cout << '\n';
+ employee2.executeForm(shrub);
+ employee1.executeForm(robot);
+ employee0.executeForm(pres);
+ std::cout << '\n';
+ employee3.signForm(shrub);
+ employee2.signForm(robot);
+ employee1.signForm(pres);
+ std::cout << '\n';
+ employee3.executeForm(shrub);
+ employee2.executeForm(robot);
+ employee1.executeForm(pres);
+ std::cout << '\n';
+ employee2.executeForm(shrub);
+ std::cout << '\n';
+ employee1.executeForm(robot);
+ employee1.executeForm(robot);
+ employee1.executeForm(robot);
+ employee1.executeForm(robot);
+ employee1.executeForm(robot);
+ employee1.executeForm(robot);
+ employee1.executeForm(robot);
+ employee1.executeForm(robot);
+ employee1.executeForm(robot);
+ employee1.executeForm(robot);
+ std::cout << '\n';
+ employee0.executeForm(pres);
+ return (0);
+}