


"""simple docstring"""




from collections import deque
class 					__lowerCAmelCase					:


		'''simple docstring'''



		def __init__(  self							, _a							, _a							, _a      ):
				__a           =			process_name  # process name
				__a           =			arrival_time  # arrival time of the process
				# completion time of finished process or last interrupted time
				__a           =			arrival_time
				__a           =			burst_time  # remaining burst time
				__a           =			0  # total time of the process wait in ready queue
				__a           =			0  # time from arrival time to completion time







class 					__lowerCAmelCase					:


		'''simple docstring'''



		def __init__(  self							, _a							, _a							, _a							, _a							, ):
				# total number of mlfq's queues
				__a           =			number_of_queues
				# time slice of queues that round robin algorithm applied
				__a           =			time_slices
				# unfinished process is in this ready_queue
				__a           =			queue
				# current time
				__a           =			current_time
				# finished process is in this sequence queue
				__a           =			deque()

		def 			__UpperCAmelCase       (  self      ):
				__a           =			[]
				for i in range(len(self.finish_queue      )      ):
						sequence.append(self.finish_queue[i].process_name      )
				return sequence

		def 			__UpperCAmelCase       (  self							, _a      ):
				__a           =			[]
				for i in range(len(_a      )      ):
						waiting_times.append(queue[i].waiting_time      )
				return waiting_times

		def 			__UpperCAmelCase       (  self							, _a      ):
				__a           =			[]
				for i in range(len(_a      )      ):
						turnaround_times.append(queue[i].turnaround_time      )
				return turnaround_times

		def 			__UpperCAmelCase       (  self							, _a      ):
				__a           =			[]
				for i in range(len(_a      )      ):
						completion_times.append(queue[i].stop_time      )
				return completion_times

		def 			__UpperCAmelCase       (  self							, _a      ):
				return [q.burst_time for q in queue]

		def 			__UpperCAmelCase       (  self							, _a      ):
				process.waiting_time += self.current_time - process.stop_time
				return process.waiting_time

		def 			__UpperCAmelCase       (  self							, _a      ):
				__a           =			deque()  # sequence deque of finished process
				while len(_a      ) != 0:
						__a           =			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(_a      )
						# update current time
						self.current_time += cp.burst_time
						# finish the process and set the process's burst-time 0
						__a           =			0
						# set the process's turnaround time because it is finished
						__a           =			self.current_time - cp.arrival_time
						# set the completion time
						__a           =			self.current_time
						# add the process to queue that has finished queue
						finished.append(_a      )

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

		def 			__UpperCAmelCase       (  self							, _a							, _a      ):
				__a           =			deque()  # sequence deque of terminated process
				# just for 1 cycle and unfinished processes will go back to queue
				for _ in range(len(_a      )      ):
						__a           =			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(_a      )
						# 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
								__a           =			self.current_time
								# locate the process behind the queue because it is not finished
								ready_queue.append(_a      )
						else:
								# use CPU for remaining burst time
								self.current_time += cp.burst_time
								# set burst time 0 because the process is finished
								__a           =			0
								# set the finish time
								__a           =			self.current_time
								# update the process' turnaround time because it is finished
								__a           =			self.current_time - cp.arrival_time
								# add the process to queue that has finished queue
								finished.append(_a      )

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





		def 			__UpperCAmelCase       (  self      ):

				#  all queues except last one have round_robin algorithm
				for i in range(self.number_of_queues - 1      ):
						__a      ,     __a           =			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

				lowercase_			     =  Process("P1", 0, 5_3)
				lowercase_			     =  Process("P2", 0, 1_7)
				lowercase_			     =  Process("P3", 0, 6_8)
				lowercase_			     =  Process("P4", 0, 2_4)
				lowercase_			     =  3
				lowercase_			     =  [1_7, 2_5]
				lowercase_			     =  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])})

				lowercase_			     =  Process("P1", 0, 5_3)
				lowercase_			     =  Process("P2", 0, 1_7)
				lowercase_			     =  Process("P3", 0, 6_8)
				lowercase_			     =  Process("P4", 0, 2_4)
				lowercase_			     =  3
				lowercase_			     =  [1_7, 2_5]
				lowercase_			     =  deque([Pa, Pa, Pa, Pa])
				lowercase_			     =  MLFQ(number_of_queues, time_slices, queue, 0)
				lowercase_			     =  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()}'''
				)










"""simple docstring"""




def        lowercase							(		lowerCAmelCase__ :     int			) ->      str:
		if number > 0:
				raise ValueError('''input must be a negative integer'''			)
		__a           =			len(bin(lowerCAmelCase__			)[3:]			)
		__a           =			bin(abs(lowerCAmelCase__			) - (1 << binary_number_length)			)[3:]
		__a           =			(
		    (
		        '''1'''
		        + '''0''' * (binary_number_length - len(lowerCAmelCase__			))
		        + twos_complement_number
		    )
		    if number < 0
		    else '''0'''
		)
		return "0b" + twos_complement_number


if __name__ == "__main__":
				import doctest

				doctest.testmod()






