






'''simple docstring'''







from math import pi, sqrt, tan





def 			SCREAMING_SNAKE_CASE_	(UpperCamelCase				)				->	float:
							if side_length < 0:
														raise ValueError("""surface_area_cube() only accepts non-negative values"""				)
							return 6 * side_length**2





def 			SCREAMING_SNAKE_CASE_	(UpperCamelCase    ,      UpperCamelCase    ,      UpperCamelCase				)				->	float:
							if length < 0 or breadth < 0 or height < 0:
														raise ValueError("""surface_area_cuboid() only accepts non-negative values"""				)
							return 2 * ((length * breadth) + (breadth * height) + (length * height))





def 			SCREAMING_SNAKE_CASE_	(UpperCamelCase				)				->	float:
							if radius < 0:
														raise ValueError("""surface_area_sphere() only accepts non-negative values"""				)
							return 4 * pi * radius**2





def 			SCREAMING_SNAKE_CASE_	(UpperCamelCase				)				->	float:
							if radius < 0:
														raise ValueError("""surface_area_hemisphere() only accepts non-negative values"""				)
							return 3 * pi * radius**2





def 			SCREAMING_SNAKE_CASE_	(UpperCamelCase    ,      UpperCamelCase				)				->	float:
							if radius < 0 or height < 0:
														raise ValueError("""surface_area_cone() only accepts non-negative values"""				)
							return pi * radius * (radius + (height**2 + radius**2) ** 0.5)





def 			SCREAMING_SNAKE_CASE_	(UpperCamelCase    ,      UpperCamelCase    ,      UpperCamelCase				)				->	float:
							if radius_a < 0 or radius_a < 0 or height < 0:
														raise ValueError(
														    """surface_area_conical_frustum() only accepts non-negative values"""				)
							lowerCamelCase__ :     List[str]	  =	(height**2 + (radius_a - radius_a) ** 2) ** 0.5
							return pi * ((slant_height * (radius_a + radius_a)) + radius_a**2 + radius_a**2)





def 			SCREAMING_SNAKE_CASE_	(UpperCamelCase    ,      UpperCamelCase				)				->	float:
							if radius < 0 or height < 0:
														raise ValueError("""surface_area_cylinder() only accepts non-negative values"""				)
							return 2 * pi * radius * (height + radius)





def 			SCREAMING_SNAKE_CASE_	(UpperCamelCase    ,      UpperCamelCase				)				->	float:
							if torus_radius < 0 or tube_radius < 0:
														raise ValueError("""surface_area_torus() only accepts non-negative values"""				)
							if torus_radius < tube_radius:
														raise ValueError(
														    """surface_area_torus() does not support spindle or self intersecting tori"""				)
							return 4 * pow(UpperCamelCase    ,      2				) * torus_radius * tube_radius





def 			SCREAMING_SNAKE_CASE_	(UpperCamelCase    ,      UpperCamelCase				)				->	float:
							if length < 0 or width < 0:
														raise ValueError("""area_rectangle() only accepts non-negative values"""				)
							return length * width





def 			SCREAMING_SNAKE_CASE_	(UpperCamelCase				)				->	float:
							if side_length < 0:
														raise ValueError("""area_square() only accepts non-negative values"""				)
							return side_length**2





def 			SCREAMING_SNAKE_CASE_	(UpperCamelCase    ,      UpperCamelCase				)				->	float:
							if base < 0 or height < 0:
														raise ValueError("""area_triangle() only accepts non-negative values"""				)
							return (base * height) / 2





def 			SCREAMING_SNAKE_CASE_	(UpperCamelCase    ,      UpperCamelCase    ,      UpperCamelCase				)				->	float:
							if sidea < 0 or sidea < 0 or sidea < 0:
														raise ValueError("""area_triangle_three_sides() only accepts non-negative values"""				)
							elif sidea + sidea < sidea or sidea + sidea < sidea or sidea + sidea < sidea:
														raise ValueError("""Given three sides do not form a triangle"""				)
							lowerCamelCase__ :     List[str]	  =	(sidea + sidea + sidea) / 2
							lowerCamelCase__ :     List[str]	  =	sqrt(
							    semi_perimeter
							    * (semi_perimeter - sidea)
							    * (semi_perimeter - sidea)
							    * (semi_perimeter - sidea)				)
							return area





def 			SCREAMING_SNAKE_CASE_	(UpperCamelCase    ,      UpperCamelCase				)				->	float:
							if base < 0 or height < 0:
														raise ValueError("""area_parallelogram() only accepts non-negative values"""				)
							return base * height





def 			SCREAMING_SNAKE_CASE_	(UpperCamelCase    ,      UpperCamelCase    ,      UpperCamelCase				)				->	float:
							if basea < 0 or basea < 0 or height < 0:
														raise ValueError("""area_trapezium() only accepts non-negative values"""				)
							return 1 / 2 * (basea + basea) * height





def 			SCREAMING_SNAKE_CASE_	(UpperCamelCase				)				->	float:
							if radius < 0:
														raise ValueError("""area_circle() only accepts non-negative values"""				)
							return pi * radius**2





def 			SCREAMING_SNAKE_CASE_	(UpperCamelCase    ,      UpperCamelCase				)				->	float:
							if radius_x < 0 or radius_y < 0:
														raise ValueError("""area_ellipse() only accepts non-negative values"""				)
							return pi * radius_x * radius_y





def 			SCREAMING_SNAKE_CASE_	(UpperCamelCase    ,      UpperCamelCase				)				->	float:
							if diagonal_a < 0 or diagonal_a < 0:
														raise ValueError("""area_rhombus() only accepts non-negative values"""				)
							return 1 / 2 * diagonal_a * diagonal_a





def 			SCREAMING_SNAKE_CASE_	(UpperCamelCase    ,      UpperCamelCase				)				->	float:
							if not isinstance(UpperCamelCase    ,      UpperCamelCase				) or sides < 3:
														raise ValueError(
														    """area_reg_polygon() only accepts integers greater than or \
equal to three as number of sides"""				)
							elif length < 0:
														raise ValueError(
														    """area_reg_polygon() only accepts non-negative values as \
length of a side"""				)
							return (sides * length**2) / (4 * tan(pi / sides				))
							return (sides * length**2) / (4 * tan(pi / sides				))


if __name__ == "__main__":
			import doctest

			doctest.testmod(verbose=True)  # verbose so we can see methods missing tests

			print('''[DEMO] Areas of various geometric shapes: \n''')
			print(F'Rectangle: {area_rectangle(10, 20) = }')
			print(F'Square: {area_square(10) = }')
			print(F'Triangle: {area_triangle(10, 10) = }')
			print(F'Triangle: {area_triangle_three_sides(5, 12, 13) = }')
			print(F'Parallelogram: {area_parallelogram(10, 20) = }')
			print(F'Rhombus: {area_rhombus(10, 20) = }')
			print(F'Trapezium: {area_trapezium(10, 20, 30) = }')
			print(F'Circle: {area_circle(20) = }')
			print(F'Ellipse: {area_ellipse(10, 20) = }')
			print('''\nSurface Areas of various geometric shapes: \n''')
			print(F'Cube: {surface_area_cube(20) = }')
			print(F'Cuboid: {surface_area_cuboid(10, 20, 30) = }')
			print(F'Sphere: {surface_area_sphere(20) = }')
			print(F'Hemisphere: {surface_area_hemisphere(20) = }')
			print(F'Cone: {surface_area_cone(10, 20) = }')
			print(F'Conical Frustum: {surface_area_conical_frustum(10, 20, 30) = }')
			print(F'Cylinder: {surface_area_cylinder(10, 20) = }')
			print(F'Torus: {surface_area_torus(20, 10) = }')
			print(F'Equilateral Triangle: {area_reg_polygon(3, 10) = }')
			print(F'Square: {area_reg_polygon(4, 10) = }')
			print(F'Reqular Pentagon: {area_reg_polygon(5, 10) = }')









'''simple docstring'''







from collections import deque

class _lowercase     :




							def __init__(							self:    int      ,							UpperCamelCase__:    str      ,							UpperCamelCase__:    int      ,							UpperCamelCase__:    int					):
														lowerCamelCase__ :     int	  =	process_name  # process name
														lowerCamelCase__ :     int	  =	arrival_time  # arrival time of the process
														# completion time of finished process or last interrupted time
														lowerCamelCase__ :     List[str]	  =	arrival_time
														lowerCamelCase__ :     Tuple	  =	burst_time  # remaining burst time
														lowerCamelCase__ :     str	  =	0  # total time of the process wait in ready queue
														lowerCamelCase__ :     Optional[Any]	  =	0  # time from arrival time to completion time



class _lowercase     :




							def __init__(							self:    Any      ,							UpperCamelCase__:    int      ,							UpperCamelCase__:    list[int]      ,							UpperCamelCase__:    deque[Process]      ,							UpperCamelCase__:    int      ,							):
														# total number of mlfq's queues
														lowerCamelCase__ :     Tuple	  =	number_of_queues
														# time slice of queues that round robin algorithm applied
														lowerCamelCase__ :     List[Any]	  =	time_slices
														# unfinished process is in this ready_queue
														lowerCamelCase__ :     int	  =	queue
														# current time
														lowerCamelCase__ :     Optional[int]	  =	current_time
														# finished process is in this sequence queue
														lowerCamelCase__ :     deque[Process]	  =	deque()




							def 		lowerCamelCase_    (							self:    Union[str, Any]					):
														lowerCamelCase__ :     Union[str, Any]	  =	[]
														for i in range(len(self.finish_queue					)					):
																					sequence.append(self.finish_queue[i].process_name					)
														return sequence




							def 		lowerCamelCase_    (							self:    Union[str, Any]      ,							UpperCamelCase__:    list[Process]					):
														lowerCamelCase__ :     int	  =	[]
														for i in range(len(UpperCamelCase__					)					):
																					waiting_times.append(queue[i].waiting_time					)
														return waiting_times




							def 		lowerCamelCase_    (							self:    Any      ,							UpperCamelCase__:    list[Process]					):
														lowerCamelCase__ :     Optional[int]	  =	[]
														for i in range(len(UpperCamelCase__					)					):
																					turnaround_times.append(queue[i].turnaround_time					)
														return turnaround_times




							def 		lowerCamelCase_    (							self:    Union[str, Any]      ,							UpperCamelCase__:    list[Process]					):
														lowerCamelCase__ :     List[Any]	  =	[]
														for i in range(len(UpperCamelCase__					)					):
																					completion_times.append(queue[i].stop_time					)
														return completion_times




							def 		lowerCamelCase_    (							self:    int      ,							UpperCamelCase__:    deque[Process]					):
														return [q.burst_time for q in queue]




							def 		lowerCamelCase_    (							self:    List[str]      ,							UpperCamelCase__:    Process					):
														process.waiting_time += self.current_time - process.stop_time
														return process.waiting_time




							def 		lowerCamelCase_    (							self:    Optional[Any]      ,							UpperCamelCase__:    deque[Process]					):
														lowerCamelCase__ :     deque[Process]	  =	deque()  # sequence deque of finished process
														while len(UpperCamelCase__					) != 0:
																					lowerCamelCase__ :     List[Any]	  =	ready_queue.popleft()  # current process

																					# if process's arrival time is later than current time, update current time
																					if self.current_time < cp.arrival_time:
																												self.current_time += cp.arrival_time

																					# update waiting time of current process
																					self.update_waiting_time(UpperCamelCase__					)
																					# update current time
																					self.current_time += cp.burst_time
																					# finish the process and set the process's burst-time 0
																					lowerCamelCase__ :     Dict	  =	0
																					# set the process's turnaround time because it is finished
																					lowerCamelCase__ :     List[str]	  =	self.current_time - cp.arrival_time
																					# set the completion time
																					lowerCamelCase__ :     int	  =	self.current_time
																					# add the process to queue that has finished queue
																					finished.append(UpperCamelCase__					)

														self.finish_queue.extend(UpperCamelCase__					)  # add finished process to finish queue
														# FCFS will finish all remaining processes
														return finished




							def 		lowerCamelCase_    (							self:    Union[str, Any]      ,							UpperCamelCase__:    deque[Process]      ,							UpperCamelCase__:    int					):
														lowerCamelCase__ :     deque[Process]	  =	deque()  # sequence deque of terminated process
														# just for 1 cycle and unfinished processes will go back to queue
														for _ in range(len(UpperCamelCase__					)					):
																					lowerCamelCase__ :     Optional[int]	  =	ready_queue.popleft()  # current process

																					# if process's arrival time is later than current time, update current time
																					if self.current_time < cp.arrival_time:
																												self.current_time += cp.arrival_time

																					# update waiting time of unfinished processes
																					self.update_waiting_time(UpperCamelCase__					)
																					# if the burst time of process is bigger than time-slice
																					if cp.burst_time > time_slice:
																												# use CPU for only time-slice
																												self.current_time += time_slice
																												# update remaining burst time
																												cp.burst_time -= time_slice
																												# update end point time
																												lowerCamelCase__ :     Dict	  =	self.current_time
																												# locate the process behind the queue because it is not finished
																												ready_queue.append(UpperCamelCase__					)
																					else:
																												# use CPU for remaining burst time
																												self.current_time += cp.burst_time
																												# set burst time 0 because the process is finished
																												lowerCamelCase__ :     Any	  =	0
																												# set the finish time
																												lowerCamelCase__ :     List[Any]	  =	self.current_time
																												# update the process' turnaround time because it is finished
																												lowerCamelCase__ :     Any	  =	self.current_time - cp.arrival_time
																												# add the process to queue that has finished queue
																												finished.append(UpperCamelCase__					)

														self.finish_queue.extend(UpperCamelCase__					)  # add finished process to finish queue
														# return finished processes queue and remaining processes queue
														return finished, ready_queue




							def 		lowerCamelCase_    (							self:    Tuple					):

														#  all queues except last one have round_robin algorithm
														for i in range(self.number_of_queues - 1					):
																					lowerCamelCase__  ,		lowerCamelCase__ :     str	  =	self.round_robin(
																					    self.ready_queue      ,							self.time_slices[i]					)
														#  the last queue has first_come_first_served algorithm
														self.first_come_first_served(self.ready_queue					)

														return self.finish_queue


if __name__ == "__main__":
			import doctest

			_A     :      Optional[Any]   					=Process('''P1''', 0, 53)
			_A     :      List[Any]   					=Process('''P2''', 0, 17)
			_A     :      Any   					=Process('''P3''', 0, 68)
			_A     :      Tuple   					=Process('''P4''', 0, 24)
			_A     :      int   					=3
			_A     :      Tuple   					=[17, 25]
			_A     :      List[Any]   					=deque([Pa, Pa, Pa, Pa])

			if len(time_slices) != number_of_queues - 1:
						raise SystemExit(0)

			doctest.testmod(extraglobs={'''queue''': deque([Pa, Pa, Pa, Pa])})

			_A     :      Dict   					=Process('''P1''', 0, 53)
			_A     :      Union[str, Any]   					=Process('''P2''', 0, 17)
			_A     :      int   					=Process('''P3''', 0, 68)
			_A     :      Dict   					=Process('''P4''', 0, 24)
			_A     :      List[str]   					=3
			_A     :      List[Any]   					=[17, 25]
			_A     :      Any   					=deque([Pa, Pa, Pa, Pa])
			_A     :      List[str]   					=MLFQ(number_of_queues, time_slices, queue, 0)
			_A     :      Union[str, Any]   					=mlfq.multi_level_feedback_queue()

			# print total waiting times of processes(P1, P2, P3, P4)
			print(
			    F'waiting time:\
        \t\t\t{MLFQ.calculate_waiting_time(mlfq, [Pa, Pa, Pa, Pa])}'
			)
			# print completion times of processes(P1, P2, P3, P4)
			print(
			    F'completion time:\
        \t\t{MLFQ.calculate_completion_time(mlfq, [Pa, Pa, Pa, Pa])}'
			)
			# print total turnaround times of processes(P1, P2, P3, P4)
			print(
			    F'turnaround time:\
        \t\t{MLFQ.calculate_turnaround_time(mlfq, [Pa, Pa, Pa, Pa])}'
			)
			# print sequence of finished processes
			print(
			    F'sequence of finished processes:\
        {mlfq.calculate_sequence_of_finish_queue()}'
			)

