diff --git a/src/request_load_estimator.py b/src/request_load_estimator.py index 6567e3d..b51fc43 100644 --- a/src/request_load_estimator.py +++ b/src/request_load_estimator.py @@ -55,11 +55,11 @@ class RequestLoadEstimator: AVERAGE_PROBLEM_LEVEL_IN_PERCENT = 0.1 def __init__(self): - self._weeks_cycle = 4 + self._days_cycle = 4 self.service_desk_employees = 0 self.documentation_level = 0 - self._service_desk_knowledge_level = 0 - self._systems_complexity = 0 + self.service_desk_knowledge_level = 0 + self.systems_complexity = 0 self.nr_of_applications = 0 self.nr_of_employees = 0 self.new_application_problems = 0 @@ -70,10 +70,14 @@ class RequestLoadEstimator: self.actual_week = 0 self.data_set = DataFrame() self.initialize_data() + self.prev_dict = {"day": 0, "days_cycle": 0, "service_desk_employees": 0, "documentation_level": 0, + "service_desk_knowledge_level": 0, "systems_complexity": 0, "nr_of_applications": 0, + "new_application_problems": 0, "nr_of_open_service_requests": 0, "request_working_time": 0, + "personal_available_time": 0, "processed_service_requests": 0, "nr_of_employees": 0} pass def set_weeks_cycle(self, days: int): - self._weeks_cycle = days + self._days_cycle = days def add_new_applications(self, nr: int): if nr > 0: @@ -83,31 +87,31 @@ class RequestLoadEstimator: if self.documentation_level < DOCUMENTATION_LEVEL_MIN: self.documentation_level = DOCUMENTATION_LEVEL_MIN complexity_increase = (nr / self.nr_of_applications) * 0.2 - self._systems_complexity += complexity_increase + self.systems_complexity += complexity_increase self.nr_of_applications += nr elif nr < 0: logger.info(MODULE_LOGGER_HEAD + "Removing applications: " + str(nr)) complexity_reduction = (nr / self.nr_of_applications) * 0.2 - self._systems_complexity -= complexity_reduction + self.systems_complexity -= complexity_reduction self.nr_of_applications += nr def add_new_employees(self, nr: int): if nr > 0: logger.info(MODULE_LOGGER_HEAD + "Adding new employees: " + str(nr)) - self._systems_complexity += nr / self.nr_of_employees + self.systems_complexity += nr / self.nr_of_employees self.nr_of_employees += nr elif nr < 0: logger.info(MODULE_LOGGER_HEAD + "Removing employees: " + str(nr)) - self._systems_complexity -= nr / self.nr_of_employees + self.systems_complexity -= nr / self.nr_of_employees self.nr_of_employees += nr def add_service_desk_employees(self, nr: int): if nr > 0: logger.info(MODULE_LOGGER_HEAD + "Adding new service desk employees: " + str(nr)) knowledge_level_reduction = (nr / self.service_desk_employees) * 0.2 - self._service_desk_knowledge_level = limit_value(self._service_desk_knowledge_level - knowledge_level_reduction, - KNOWLEDGE_LEVEL_MIN, - KNOWLEDGE_LEVEL_MAX) + self.service_desk_knowledge_level = limit_value(self.service_desk_knowledge_level - knowledge_level_reduction, + KNOWLEDGE_LEVEL_MIN, + KNOWLEDGE_LEVEL_MAX) self.service_desk_employees += nr elif nr < 0: logger.info(MODULE_LOGGER_HEAD + "Removing service desk employees: " + str(nr)) @@ -115,7 +119,7 @@ class RequestLoadEstimator: def process_weeks(self): logger.info(MODULE_LOGGER_HEAD + "Processing weeks") - for week in range(self._weeks_cycle): + for day in range(self._days_cycle): self._calc_nr_of_service_requests() self._calc_request_working_time() self._calc_personal_available_time() @@ -127,11 +131,11 @@ class RequestLoadEstimator: def initialize_data(self): logger.info(MODULE_LOGGER_HEAD + "Initializing data") - self._weeks_cycle = 7 + self._days_cycle = 7 self.service_desk_employees = START_NR_OF_SERVICE_DESK_EMPLOYEES self.documentation_level = START_DOCUMENTATION_LEVEL - self._service_desk_knowledge_level = START_KNOWLEDGE_LEVEL - self._systems_complexity = START_SYSTEMS_COMPLEXITY + self.service_desk_knowledge_level = START_KNOWLEDGE_LEVEL + self.systems_complexity = START_SYSTEMS_COMPLEXITY self.nr_of_applications = START_NR_OF_APPLICATIONS self.nr_of_employees = START_NR_OF_EMPLOYEES self.new_application_problems = 0 @@ -144,7 +148,7 @@ class RequestLoadEstimator: def _calc_application_problems(self): self.new_application_problems = ((self.nr_of_employees * self.nr_of_applications * - self._systems_complexity / self.documentation_level) + self.systems_complexity / self.documentation_level) * self.AVERAGE_PROBLEM_LEVEL_IN_PERCENT) if self.new_application_problems < 0: self.new_application_problems = 0 @@ -155,7 +159,7 @@ class RequestLoadEstimator: def _calc_request_working_time(self): self._desired_request_working_time = (self.nr_of_open_service_requests * - (self.AVERAGE_REQUEST_WORKING_TIME / self._service_desk_knowledge_level)) + (self.AVERAGE_REQUEST_WORKING_TIME / self.service_desk_knowledge_level)) if self._desired_request_working_time < 0: self._desired_request_working_time = 0 @@ -166,7 +170,7 @@ class RequestLoadEstimator: else: self.processed_service_requests = int((self.service_desk_employees * self.AVERAGE_DAY_WORKING_TIME) / ( - self.AVERAGE_REQUEST_WORKING_TIME / self._service_desk_knowledge_level)) + self.AVERAGE_REQUEST_WORKING_TIME / self.service_desk_knowledge_level)) self.nr_of_open_service_requests -= self.processed_service_requests @@ -188,21 +192,21 @@ class RequestLoadEstimator: self.nr_of_employees * self.service_desk_employees) - self._service_desk_knowledge_level += know_how_reduction if know_how_reduction >= 0 else know_how_reduction / 10 + self.service_desk_knowledge_level += know_how_reduction if know_how_reduction >= 0 else know_how_reduction / 10 self.documentation_level = limit_value(self.documentation_level, DOCUMENTATION_LEVEL_MIN, DOCUMENTATION_LEVEL_MAX) - self._service_desk_knowledge_level = limit_value(self._service_desk_knowledge_level, KNOWLEDGE_LEVEL_MIN, - KNOWLEDGE_LEVEL_MAX) + self.service_desk_knowledge_level = limit_value(self.service_desk_knowledge_level, KNOWLEDGE_LEVEL_MIN, + KNOWLEDGE_LEVEL_MAX) def _process_data_set(self): row = { - "week": self.actual_week, - "weeks_cycle": self._weeks_cycle, + "day": self.actual_week, + "days_cycle": self._days_cycle, "service_desk_employees": self.service_desk_employees, "documentation_level": self.documentation_level, - "service_desk_knowledge_level": self._service_desk_knowledge_level, - "systems_complexity": self._systems_complexity, + "service_desk_knowledge_level": self.service_desk_knowledge_level, + "systems_complexity": self.systems_complexity, "nr_of_applications": self.nr_of_applications, "new_application_problems": self.new_application_problems, "nr_of_open_service_requests": self.nr_of_open_service_requests, diff --git a/src/start_app.py b/src/start_app.py index 17ad65f..bce9cc5 100644 --- a/src/start_app.py +++ b/src/start_app.py @@ -58,6 +58,14 @@ def get_estimator(): return RequestLoadEstimator() +def write_metric(estimator_object: RequestLoadEstimator, st_object: st, title: str, value_name: str, + delta_color="normal"): + value = getattr(estimator_object, value_name) + delta = value - estimator_object.prev_dict[value_name] + estimator_object.prev_dict[value_name] = value + + st_object.metric(title, f"{value:0.2f}", delta=f"{delta:0.2f}", delta_color=delta_color) + # --------------------------------------- # # classes # # --------------------------------------- # @@ -77,8 +85,8 @@ if __name__ == "__main__": col1, col2, col3, col4 = form.columns(4) form.divider() dis_col1, dis_col2, dis_col3 = form.columns([2, 2, 1]) - weeks_cycle = col1.number_input("Weeks cycle", min_value=1, max_value=20, value=3) - add_new_employee = col2.number_input("Add new employees", min_value=0, max_value=50, value=0) + days_cycle = col1.number_input("Days cycle", min_value=1, max_value=20, value=3) + add_new_employee = col2.number_input("Change number of employees", min_value=-50, max_value=50, value=0) add_new_applications = col3.number_input("Change number of applications", min_value=-10, max_value=10, value=0) add_new_service_desk_employees = col4.number_input("Change number of service desk employees", min_value=-10, max_value=10, @@ -89,46 +97,51 @@ if __name__ == "__main__": request_estimator = get_estimator() if submit_button: - request_estimator.set_weeks_cycle(weeks_cycle) + request_estimator.set_weeks_cycle(days_cycle) request_estimator.add_new_applications(add_new_applications) request_estimator.add_service_desk_employees(add_new_service_desk_employees) request_estimator.add_new_employees(add_new_employee) request_estimator.process_weeks() if not request_estimator.data_set.empty: - fig_requests = px.area(request_estimator.data_set, x="week", y=["nr_of_processed_service_requests", + fig_requests = px.area(request_estimator.data_set, x="day", y=["nr_of_processed_service_requests", "nr_of_open_service_requests"], line_shape="spline") - fig_personal = px.area(request_estimator.data_set, x="week", y=["personal_available_time", + fig_personal = px.area(request_estimator.data_set, x="day", y=["personal_available_time", "request_working_time", "service_desk_employees", "nr_of_employees"], line_shape="spline") - fig_knowledge = px.area(request_estimator.data_set, x="week", y=["documentation_level", + fig_knowledge = px.area(request_estimator.data_set, x="day", y=["documentation_level", "service_desk_knowledge_level", "systems_complexity"], - line_shape="spline") + line_shape="spline") dis_col1.subheader("Service Request Overview") dis_col1.plotly_chart(fig_requests, use_container_width=True) - dis_col2.subheader("Personal and Knowledge Overview") + dis_col1.subheader("Monitoring Metrics") + sub_col1, sub_col2 = dis_col1.columns(2) + dis_col2.subheader("Personal Statistics") dis_col2.plotly_chart(fig_personal, use_container_width=True) + dis_col3.subheader("Knowledge and Complexity") dis_col2.plotly_chart(fig_knowledge, use_container_width=True) detail_expander = dis_col1.expander("Data Table") detail_expander.dataframe(request_estimator.data_set) - dis_col3.metric("Company Employees", request_estimator.nr_of_employees, delta=add_new_employee) - dis_col3.metric("Service Desk Employees", request_estimator.service_desk_employees, delta=add_new_service_desk_employees) - dis_col3.metric("Nr of Applications", request_estimator.nr_of_applications, delta=add_new_applications) - dis_col3.metric("Nr of open Service Requests", request_estimator.nr_of_open_service_requests) - dis_col3.metric("Nr of processed Service Requests", request_estimator.processed_service_requests) - if request_estimator.personal_available_time > 0: - st.info(f"Your team has available time of {request_estimator.personal_available_time:.0f} hours.") - else: - st.error("Your team has no available time. You are in the cycle of death! Hire new Guys!!!!") + write_metric(request_estimator, sub_col1, "Available Working Time", "personal_available_time") + write_metric(request_estimator, sub_col2, "Service Desk Knowledge Level", "service_desk_knowledge_level") + write_metric(request_estimator, sub_col1, "Systems Complexity", "systems_complexity", "inverse") + write_metric(request_estimator, sub_col2, "Documentation Level", "documentation_level") + + write_metric(request_estimator, dis_col3, "Company Employees", "nr_of_employees") + write_metric(request_estimator, dis_col3, "Service Desk Employees", "service_desk_employees") + write_metric(request_estimator, dis_col3, "Nr of Applications", "nr_of_applications") + write_metric(request_estimator, dis_col3, "Nr of open Service Requests", "nr_of_open_service_requests", "inverse") + write_metric(request_estimator, dis_col3, "Nr of processed Service Requests", "processed_service_requests") + else: - form.write(request_estimator.data_set) + st.write("No data available yet! Push the button to process the data.") st.divider()