22import threading
33import time
44import tkinter as tk
5+ from collections .abc import Generator
56from tkinter import messagebox , ttk
67
78import matplotlib .pyplot as plt
89from matplotlib .backends .backend_tkagg import FigureCanvasTkAgg
9- from typing import Generator
1010
1111
1212# ===================== Scheduler Engine ===================== #
@@ -29,7 +29,7 @@ def __init__(self, processes: list[dict], algorithm: str, quantum: int = 2) -> N
2929 self .timeline : list [tuple [int , str ]] = [] # [(time, pid)]
3030 self .stats : list [tuple ] = []
3131
32- def simulate (self ) -> Generator [tuple [int , str | None , list [str ]], None , None ]:
32+ def simulate (self ) -> Generator [tuple [int , str | None , list [str ]]]:
3333 """
3434 Runs the selected CPU scheduling algorithm.
3535
@@ -54,7 +54,7 @@ def simulate(self) -> Generator[tuple[int, str | None, list[str]], None, None]:
5454 self ._calculate_stats ()
5555
5656 # first come first serve
57- def _simulate_fcfs (self ) -> Generator [tuple [int , str , list [str ]], None , None ]:
57+ def _simulate_fcfs (self ) -> Generator [tuple [int , str , list [str ]]]:
5858 """
5959 Simulates First Come First Serve scheduling.
6060
@@ -74,7 +74,7 @@ def _simulate_fcfs(self) -> Generator[tuple[int, str, list[str]], None, None]:
7474 process ["completion" ] = t
7575
7676 # shortest job first non preemptive
77- def _simulate_sjf_np (self ) -> Generator [tuple [int , str | None , list [str ]], None , None ]:
77+ def _simulate_sjf_np (self ) -> Generator [tuple [int , str | None , list [str ]]]:
7878 """
7979 Simulates Shortest Job First (Non-Preemptive).
8080
@@ -87,7 +87,11 @@ def _simulate_sjf_np(self) -> Generator[tuple[int, str | None, list[str]], None,
8787 processes = sorted (self .processes , key = lambda process : process ["arrival" ])
8888 done = 0
8989 while done < len (processes ):
90- ready = [process for process in processes if process ["arrival" ] <= t and "completion" not in process ]
90+ ready = [
91+ process
92+ for process in processes
93+ if process ["arrival" ] <= t and "completion" not in process
94+ ]
9195 if not ready :
9296 t += 1
9397 yield (t , None , [])
@@ -101,13 +105,17 @@ def _simulate_sjf_np(self) -> Generator[tuple[int, str | None, list[str]], None,
101105 done += 1
102106
103107 # shortest job first preemptive
104- def _simulate_sjf_p (self ) -> Generator [tuple [int , str | None , list [str ]], None , None ]:
108+ def _simulate_sjf_p (self ) -> Generator [tuple [int , str | None , list [str ]]]:
105109 """Simulates SJF Preemptive scheduling."""
106110 t = 0
107111 processes = sorted (self .processes , key = lambda process : process ["arrival" ])
108112 done = 0
109113 while done < len (processes ):
110- ready = [process for process in processes if process ["arrival" ] <= t and process ["remaining" ] > 0 ]
114+ ready = [
115+ process
116+ for process in processes
117+ if process ["arrival" ] <= t and process ["remaining" ] > 0
118+ ]
111119 if not ready :
112120 t += 1
113121 yield (t , None , [])
@@ -122,12 +130,16 @@ def _simulate_sjf_p(self) -> Generator[tuple[int, str | None, list[str]], None,
122130 t += 1
123131
124132 # priority non preemptive
125- def _simulate_priority_np (self ) -> Generator [tuple [int , str | None , list [str ]], None , None ]:
133+ def _simulate_priority_np (self ) -> Generator [tuple [int , str | None , list [str ]]]:
126134 """Simulates Priority (Non-Preemptive) scheduling."""
127135 t = 0
128136 done = 0
129137 while done < len (self .processes ):
130- ready = [process for process in self .processes if process ["arrival" ] <= t and "completion" not in process ]
138+ ready = [
139+ process
140+ for process in self .processes
141+ if process ["arrival" ] <= t and "completion" not in process
142+ ]
131143 if not ready :
132144 t += 1
133145 yield (t , None , [])
@@ -141,12 +153,16 @@ def _simulate_priority_np(self) -> Generator[tuple[int, str | None, list[str]],
141153 done += 1
142154
143155 # priority preemptive
144- def _simulate_priority_p (self ) -> Generator [tuple [int , str | None , list [str ]], None , None ]:
156+ def _simulate_priority_p (self ) -> Generator [tuple [int , str | None , list [str ]]]:
145157 """Simulates Priority (Preemptive) scheduling."""
146158 t = 0
147159 done = 0
148160 while done < len (self .processes ):
149- ready = [process for process in self .processes if process ["arrival" ] <= t and process ["remaining" ] > 0 ]
161+ ready = [
162+ process
163+ for process in self .processes
164+ if process ["arrival" ] <= t and process ["remaining" ] > 0
165+ ]
150166 if not ready :
151167 t += 1
152168 yield (t , None , [])
@@ -161,7 +177,7 @@ def _simulate_priority_p(self) -> Generator[tuple[int, str | None, list[str]], N
161177 t += 1
162178
163179 # round robin
164- def _simulate_rr (self ) -> Generator [tuple [int , str | None , list [str ]], None , None ]:
180+ def _simulate_rr (self ) -> Generator [tuple [int , str | None , list [str ]]]:
165181 """Simulates Round Robin scheduling."""
166182 t = 0
167183 q : list [dict ] = []
@@ -244,9 +260,16 @@ def setup_ui(self) -> None:
244260 self .arrival_e .grid (row = 1 , column = 1 )
245261 self .burst_e .grid (row = 2 , column = 1 )
246262 self .priority_e .grid (row = 3 , column = 1 )
247- ttk .Button (form , text = "Add" , command = self .add_process ).grid (row = 4 , column = 0 , pady = 5 )
248- ttk .Button (form , text = "Delete" , command = self .delete_process ).grid (row = 4 , column = 1 )
249-
263+ ttk .Button (
264+ form ,
265+ text = "Add" ,
266+ command = self .add_process ,
267+ ).grid (row = 4 , column = 0 , pady = 5 )
268+ ttk .Button (
269+ form ,
270+ text = "Delete" ,
271+ command = self .delete_process ,
272+ ).grid (row = 4 , column = 1 )
250273 algo_frame = ttk .Frame (self .root )
251274 algo_frame .pack (pady = 10 )
252275 ttk .Label (algo_frame , text = "Algorithm:" ).pack (side = "left" )
@@ -267,8 +290,11 @@ def setup_ui(self) -> None:
267290 self .quantum_e = ttk .Entry (algo_frame , width = 5 )
268291 self .quantum_e .insert (0 , "2" )
269292 self .quantum_e .pack (side = "left" )
270- ttk .Button (algo_frame , text = "Run" , command = self .run_scheduling ).pack (side = "left" , padx = 10 )
271-
293+ ttk .Button (
294+ algo_frame ,
295+ text = "Run" ,
296+ command = self .run_scheduling ,
297+ ).pack (side = "left" , padx = 10 )
272298 self .ready_label = ttk .Label (self .root , text = "Ready Queue:" )
273299 self .ready_list = tk .Listbox (self .root , height = 3 )
274300 self .ready_label .pack_forget ()
@@ -338,7 +364,15 @@ def animate(self) -> None:
338364 current_pid = pid
339365 colors .setdefault (pid , plt .cm .tab20 (len (colors ) % 20 ))
340366 self .ax .barh (0 , 1 , left = x , color = colors [pid ])
341- self .ax .text (x + 0.5 , 0 , pid , ha = "center" , va = "center" , color = "white" , fontsize = 9 )
367+ self .ax .text (
368+ x + 0.5 ,
369+ 0 ,
370+ pid ,
371+ ha = "center" ,
372+ va = "center" ,
373+ color = "white" ,
374+ fontsize = 9 ,
375+ )
342376 x += 1
343377 self .ax .set_xticks (range (x + 1 ))
344378 self .ax .set_yticks ([])
@@ -363,10 +397,12 @@ def show_results(self) -> None:
363397 total_rt += row [6 ]
364398 n = len (self .engine .stats ) or 1
365399 self .avg_label .config (
366- text = f"AVG WT = { total_wt / n :.2f} | AVG TAT = { total_tat / n :.2f} | AVG RT = { total_rt / n :.2f} "
400+ text = (
401+ f"AVG WT = { total_wt / n :.2f} | "
402+ f"AVG TAT = { total_tat / n :.2f} | "
403+ f"AVG RT = { total_rt / n :.2f} "
404+ )
367405 )
368-
369-
370406if __name__ == "__main__" :
371407 root = tk .Tk ()
372408 CPUSchedulerGUI (root )
0 commit comments