{"id":215,"date":"2023-10-12T12:24:56","date_gmt":"2023-10-12T10:24:56","guid":{"rendered":"https:\/\/thewoodfordspider.com\/?p=215"},"modified":"2023-10-25T12:05:32","modified_gmt":"2023-10-25T10:05:32","slug":"cpu-scheduler-simulation","status":"publish","type":"post","link":"https:\/\/thewoodfordspider.com\/index.php\/2023\/10\/12\/cpu-scheduler-simulation\/","title":{"rendered":"CPU Scheduler Simulation"},"content":{"rendered":"\n<p>This is an assignment written for Noroff University to simulate different CPU scheduler methods.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">FIFO<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>from openpyxl import load_workbook  \nworkbook = load_workbook(filename='cpu-scheduling.xlsx')  \nsheet = workbook.active\n\nall_data = {}\n\n#This program was initially written across several files. It used a \"CoreConfig.py\" file to hold the class Info, a \"CoreFunctions.py\", a get_data.py  \n#as well as the four scheduling algorithms and finally a main.py file. The Config held the class Info, which used a Borg Deisgn Pattern class  \n#to hold all the variables the program needed, while letting any file access and update the variables.  \n#CoreFunctions held all the functions needed to simulate the core  \n#The main file was written to run the algorithm the user would input.  \n#This allowed the program to be very modular, and changing an algorithm required very little editing.  \n#This also allows the program to be robust, as it can handle a change in the data source without breaking.\n\n#Due to the way the assessment is delivered, I could not keep the program in its original form, and this is why it looks the way it looks.  \n#I have simply copy and pasted the \"CoreConfig\", \"CoreFunctions\" and \"get_data\" into each algorithm. This lets each run as it should on its own.  \n#This is written simply to explain why the code might look messy.\n\ndef create_process():  \n# A function to order the data from excel into a dictionary using the PID as a key, and a list as the values  \n# Then placing those dictionaries into a larger dictionary, letting the program access the info it needs, using the PID as reference\n\nfor row in sheet.iter_rows(min_row=2, values_only=True):  \nprocessID = row&#91;0]  \nprocess = &#91;row&#91;1], row&#91;2], row&#91;3], 0]  \nprocessToDict = {processID: process}  \nall_data.update(processToDict)\n\n  \n\nclass Info():  \n# A class made to have several variables needed in the program globally available  \n# Originally used a Singleton Design Pattern, but opted for a Borg Design Pattern instead, as it functioned better for my program  \ninstance = None\n\ndef __new__(cls):  \nif cls.instance is None:  \ncls.instance = super(Info, cls).__new__(cls)  \nreturn cls.instance\n\nPID = 0  \nreferenceDict = all_data  \ntimeUnit = 0  \nqueueDict = {}  \nactiveCore = {}  \nqueuePrint = ''  \nwaitPrint = ''  \ninstructionLoad = 0  \nprocessInfo = &#91;]  \nqueueSize = len(queueDict)  \ncoreStatus = len(activeCore)  \ncompleted = {}  \nq = 4  \ntimeInCore = 0\n\n  \n\ndef processCore():  \n# Prints status of the \"core\", counts down instruction load and counts up time in core by one time slice  \n# Time in core is only used for the Round Robin algorithm  \ninf = Info()  \nactiveCore = inf.activeCore  \ntimeUnit = inf.timeUnit  \nqueuePrint = inf.queuePrint  \nPID = next(iter(activeCore))  \nstartingInst = inf.referenceDict&#91;PID]&#91;1]  \nprint('Time Unit \ntimeUnit, PID, startingInst, inf.instructionLoad, queuePrint))  \ninf.instructionLoad -= 1  \ninf.timeInCore += 1  \n# If the process is finished, the process is removed from the \"core\", and creates an entry in the completed dictionary, for reference  \nif inf.instructionLoad == 0:  \ndel inf.activeCore&#91;PID]  \ninf.completed&#91;PID] = inf.referenceDict&#91;PID]\n\n  \n\ndef enterCore():  \n# A function used to move the active process into the \"core\".\n\ninf = Info()  \nPID = inf.PID  \nqueueDict = inf.queueDict  \nactiveCore = inf.activeCore  \ninf.timeInCore = 0  \n# If there is no queue, the process is entered directly into the core  \nif len(queueDict) == 0:  \ninf.activeCore&#91;PID] = inf.referenceDict&#91;PID]  \n# If the PID chosen is in the queue, the function moves the process from the queue to the \"core\"  \nelif inf.PID in inf.queueDict:  \ninf.activeCore&#91;PID] = inf.queueDict&#91;PID]  \ndel inf.queueDict&#91;PID]  \n# Sets current instruction load  \nif activeCore:  \ninf.instructionLoad = activeCore&#91;PID]&#91;1]\n\n  \n\ndef processWait():  \n# A Function to manage the queue  \ninf = Info()  \nreferenceDict = inf.referenceDict  \ntimeUnit = inf.timeUnit  \nactiveCore = inf.activeCore  \nqueueDict = inf.queueDict  \nPID = inf.PID\n\n# Iterates through all processes, and checks if they should arrive in this timeslice. If it should, it adds it to the queue  \n# It also checks if the process in question is currently in the core, and if it is, it removes it from the queue again.  \n# This is done so the queue does not contain a process currently being processed.  \n# Also changes the print message depending on the size of the queue  \nfor check in referenceDict:  \narrivalTime = referenceDict&#91;check]&#91;0]  \nif arrivalTime == timeUnit:  \ninf.queueDict&#91;check] = inf.referenceDict&#91;check]  \nif activeCore:  \nif queueDict&#91;check] == activeCore&#91;PID]:  \ndel inf.queueDict&#91;check]  \nif len(queueDict) == 0:  \ninf.queuePrint = 'No queue.'  \nelse:  \ninf.queuePrint = '\n\n  \n\ndef system_cycle():  \n# A function used to represent one time unit.  \n# It adds one to the timer, then processes the current process in the core, and checks and updates the queue  \ninf = Info()  \ninf.timeUnit += 1  \nprocessWait()  \nprocessCore()\n\n  \n\ndef check_Shortest():  \n# A simple function used to set the active PID to be the process with the shortest instruction load that is also in queue  \ninf = Info()  \nshortestJobPID = min(inf.queueDict, key=lambda k: inf.queueDict&#91;k]&#91;1])  \ninf.PID = shortestJobPID\n\n  \n\ndef check_Priority():  \n# The same function as check_shortest, but used for priority  \ninf = Info()  \nlowestPrio = min(inf.queueDict, key=lambda k: inf.queueDict&#91;k]&#91;2])  \ninf.PID = lowestPrio\n\n  \n\ndef time_slice_check():  \n# Checks if the process currently in the core has been there for the alloted timeslices  \n# If it has, it removes the process from the core, and places it back in the queue  \n# Updates the process` instruction load accordingly  \n# Ticks through one timeslice, to simulate the context switch  \n# Finally resets the instruction load, required for the loop to function  \ninf = Info()  \nPID = inf.PID\n\nif (inf.timeInCore == inf.q):  \nif inf.activeCore:  \ninf.queueDict&#91;PID] = inf.activeCore&#91;PID]  \ndel inf.activeCore&#91;PID]  \ninf.queueDict&#91;PID]&#91;1] = inf.instructionLoad  \ninf.timeUnit += 1  \nprocessWait()  \ninf.instructionLoad = 0\n\n  \n\ndef check_q():  \n# Simple check to find the first process in the queue with an instruction load shorter than the alotted timeslice  \ninf = Info()  \nwithinQ = np.where(lambda k: inf.queueDict&#91;k]&#91;1] &lt;= inf.q)  \nif withinQ&#91;0] != 0:  \ninf.PID = int(withinQ&#91;0])\n\ndef run_fifo():  \ninf = Info()  \ncompleted = inf.completed  \nreferenceDict = inf.referenceDict\n\nprint('system running')  \nwhile len(completed) != len(referenceDict):  \nfor process in referenceDict:  \ninf.PID = process  \ncoreStatus = inf.coreStatus  \nif coreStatus == 0:  \nenterCore()  \nwhile inf.instructionLoad &gt; 0:  \nsystem_cycle()  \nif inf.PID &lt; len(completed):  \nbreak\n\nprint('system finished')\n\ncreate_process()  \nrun_fifo()<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">SJF<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>from openpyxl import load_workbook  \nworkbook = load_workbook(filename='cpu-scheduling.xlsx')  \nsheet = workbook.active\n\nall_data = {}\n\ndef create_process():  \n#A function to order the data from excel into a dictionary using the PID as a key, and a list as the values  \n#Then placing those dictionaries into a larger dictionary, letting the program access the info it needs, using the PID as reference\n\nfor row in sheet.iter_rows(min_row=2, values_only=True):\n\nprocessID = row&#91;0]  \nprocess = &#91;row&#91;1], row&#91;2], row&#91;3], 0]  \nprocessToDict = {processID:process}  \nall_data.update(processToDict)\n\n  \n\nclass Info():  \n# A class made to have several variables needed in the program globally available  \n# Originally used a Singleton Design Pattern, but opted for a Borg Design Pattern instead, as it functioned better for my program  \ninstance = None  \ndef __new__(cls):  \nif cls.instance is None:  \ncls.instance = super(Info, cls).__new__(cls)  \nreturn cls.instance\n\nPID = 0  \nreferenceDict = all_data  \ntimeUnit = 0  \nqueueDict = {}  \nactiveCore = {}  \nqueuePrint = ''  \nwaitPrint = ''  \ninstructionLoad = 0  \nprocessInfo = &#91;]  \nqueueSize = len(queueDict)  \ncoreStatus = len(activeCore)  \ncompleted = {}  \nq = 4  \ntimeInCore = 0\n\ndef processCore():  \n#Prints status of the \"core\", counts down instruction load and counts up time in core by one time slice  \n#Time in core is only used for the Round Robin algorithm  \ninf = Info()  \nactiveCore = inf.activeCore  \ntimeUnit = inf.timeUnit  \nqueuePrint = inf.queuePrint  \nPID = next(iter(activeCore))  \nstartingInst = inf.referenceDict&#91;PID]&#91;1]  \nprint('Time Unit \ninf.instructionLoad -= 1  \ninf.timeInCore += 1  \n#If the process is finished, the process is removed from the \"core\", and creates an entry in the completed dictionary, for reference  \nif inf.instructionLoad == 0:  \ndel inf.activeCore&#91;PID]  \ninf.completed&#91;PID] = inf.referenceDict&#91;PID]\n\ndef enterCore():  \n#A function used to move the active process into the \"core\".\n\ninf = Info()  \nPID = inf.PID  \nqueueDict = inf.queueDict  \nactiveCore = inf.activeCore  \ninf.timeInCore = 0  \n#If there is no queue, the process is entered directly into the core  \nif len(queueDict) == 0:  \ninf.activeCore&#91;PID] = inf.referenceDict&#91;PID]  \n#If the PID chosen is in the queue, the function moves the process from the queue to the \"core\"  \nelif inf.PID in inf.queueDict:  \ninf.activeCore&#91;PID] = inf.queueDict&#91;PID]  \ndel inf.queueDict&#91;PID]  \n#Sets current instruction load  \nif activeCore:  \ninf.instructionLoad = activeCore&#91;PID]&#91;1]\n\ndef processWait():  \n#A Function to manage the queue  \ninf = Info()  \nreferenceDict = inf.referenceDict  \ntimeUnit = inf.timeUnit  \nactiveCore = inf.activeCore  \nqueueDict = inf.queueDict  \nPID = inf.PID\n\n#Iterates through all processes, and checks if they should arrive in this timeslice. If it should, it adds it to the queue  \n#It also checks if the process in question is currently in the core, and if it is, it removes it from the queue again.  \n#This is done so the queue does not contain a process currently being processed.  \n#Also changes the print message depending on the size of the queue  \nfor check in referenceDict:  \narrivalTime = referenceDict&#91;check]&#91;0]  \nif arrivalTime == timeUnit:  \ninf.queueDict&#91;check] = inf.referenceDict&#91;check]  \nif activeCore:  \nif queueDict&#91;check] == activeCore&#91;PID]:  \ndel inf.queueDict&#91;check]  \nif len(queueDict) == 0:  \ninf.queuePrint = 'No queue.'  \nelse:  \ninf.queuePrint = '\n\n  \n  \n\ndef system_cycle():  \n#A function used to represent one time unit.  \n#It adds one to the timer, then processes the current process in the core, and checks and updates the queue  \ninf = Info()  \ninf.timeUnit += 1  \nprocessWait()  \nprocessCore()\n\ndef check_Shortest():  \n#A simple function used to set the active PID to be the process with the shortest instruction load that is also in queue  \ninf = Info()  \nshortestJobPID = min(inf.queueDict, key = lambda k: inf.queueDict&#91;k]&#91;1])  \ninf.PID = shortestJobPID\n\ndef check_Priority():  \n#The same function as check_shortest, but used for priority  \ninf = Info()  \nlowestPrio = min(inf.queueDict, key = lambda k: inf.queueDict&#91;k]&#91;2])  \ninf.PID = lowestPrio\n\ndef time_slice_check():  \n#Checks if the process currently in the core has been there for the alloted timeslices  \n#If it has, it removes the process from the core, and places it back in the queue  \n#Updates the process` instruction load accordingly  \n#Ticks through one timeslice, to simulate the context switch  \n#Finally resets the instruction load, required for the loop to function  \ninf = Info()  \nPID = inf.PID\n\nif (inf.timeInCore == inf.q):  \nif inf.activeCore:  \ninf.queueDict&#91;PID] = inf.activeCore&#91;PID]  \ndel inf.activeCore&#91;PID]  \ninf.queueDict&#91;PID]&#91;1] = inf.instructionLoad  \ninf.timeUnit += 1  \nprocessWait()  \ninf.instructionLoad = 0\n\ndef check_q():  \n#Simple check to find the first process in the queue with an instruction load shorter than the alotted timeslice  \ninf = Info()  \nwithinQ = np.where(lambda k: inf.queueDict&#91;k]&#91;1] &lt;= inf.q)  \nif withinQ&#91;0] != 0:  \ninf.PID = int(withinQ&#91;0])\n\n  \n  \n\ndef run_SJF():  \ninf = Info()  \ncompleted = inf.completed  \nreferenceDict = inf.referenceDict\n\nprint('system running')  \nwhile len(completed) != len(referenceDict):  \nfor process in referenceDict:  \ninf.PID = process  \ncoreStatus = inf.coreStatus  \nif coreStatus == 0:  \nif len(inf.queueDict) != 0:  \ncheck_Shortest()  \nenterCore()  \nwhile inf.instructionLoad &gt; 0:  \nsystem_cycle()  \nif inf.PID &lt; len(completed):  \nbreak\n\nprint('system finished')\n\ncreate_process()  \nrun_SJF()<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Priority<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>from openpyxl import load_workbook  \nworkbook = load_workbook(filename='cpu-scheduling.xlsx')  \nsheet = workbook.active\n\nall_data = {}\n\ndef create_process():\n\nfor row in sheet.iter_rows(min_row=2, values_only=True):\n\nprocessID = row&#91;0]  \nprocess = &#91;row&#91;1], row&#91;2], row&#91;3], 0]  \nprocessToDict = {processID:process}  \nall_data.update(processToDict)\n\n  \n\nclass Info():  \ninstance = None  \ndef __new__(cls):  \nif cls.instance is None:  \ncls.instance = super(Info, cls).__new__(cls)  \nreturn cls.instance\n\nPID = 0  \nreferenceDict = all_data  \ntimeUnit = 0  \nqueueDict = {}  \nactiveCore = {}  \nqueuePrint = ''  \nwaitPrint = ''  \ninstructionLoad = 0  \nprocessInfo = &#91;]  \nqueueSize = len(queueDict)  \ncoreStatus = len(activeCore)  \ncompleted = {}  \nq = 4  \ntimeInCore = 0\n\ndef processCore():  \ninf = Info()  \nactiveCore = inf.activeCore  \ntimeUnit = inf.timeUnit  \nqueuePrint = inf.queuePrint  \nPID = next(iter(activeCore))  \nstartingInst = inf.referenceDict&#91;PID]&#91;1]  \nprint('Time Unit \ninf.instructionLoad -= 1  \ninf.timeInCore += 1  \nif inf.instructionLoad == 0:  \ndel inf.activeCore&#91;PID]  \ninf.completed&#91;PID] = inf.referenceDict&#91;PID]\n\ndef enterCore():\n\ninf = Info()  \nPID = inf.PID  \nqueueDict = inf.queueDict  \nactiveCore = inf.activeCore  \ninf.timeInCore = 0  \nif len(queueDict) == 0:  \ninf.activeCore&#91;PID] = inf.referenceDict&#91;PID]  \nelif inf.PID in inf.queueDict:  \ninf.activeCore&#91;PID] = inf.queueDict&#91;PID]  \ndel inf.queueDict&#91;PID]  \nif activeCore:  \ninf.instructionLoad = activeCore&#91;PID]&#91;1]\n\ndef processWait():  \ninf = Info()  \nreferenceDict = inf.referenceDict  \ntimeUnit = inf.timeUnit  \nactiveCore = inf.activeCore  \nqueueDict = inf.queueDict  \nPID = inf.PID\n\nfor check in referenceDict:  \narrivalTime = referenceDict&#91;check]&#91;0]  \nif arrivalTime == timeUnit:  \ninf.queueDict&#91;check] = inf.referenceDict&#91;check]  \nif activeCore:  \nif queueDict&#91;check] == activeCore&#91;PID]:  \ndel inf.queueDict&#91;check]  \nif len(queueDict) == 0:  \ninf.queuePrint = 'No queue.'  \nelse:  \ninf.queuePrint = '\n\n  \n  \n\ndef system_cycle():  \ninf = Info()\n\ninf.timeUnit += 1  \nprocessWait()  \nprocessCore()\n\ndef check_Shortest():  \ninf = Info()  \nshortestJobPID = min(inf.queueDict, key = lambda k: inf.queueDict&#91;k]&#91;1])  \ninf.PID = shortestJobPID\n\ndef check_Priority():  \ninf = Info()  \nlowestPrio = min(inf.queueDict, key = lambda k: inf.queueDict&#91;k]&#91;2])  \ninf.PID = lowestPrio\n\ndef time_slice_check():  \ninf = Info()  \nPID = inf.PID\n\nif (inf.timeInCore == inf.q):  \nif inf.activeCore:  \ninf.queueDict&#91;PID] = inf.activeCore&#91;PID]  \ndel inf.activeCore&#91;PID]  \ninf.queueDict&#91;PID]&#91;1] = inf.instructionLoad  \ninf.timeUnit += 1  \nprocessWait()  \ninf.instructionLoad = 0\n\ndef check_q():  \ninf = Info()  \nwithinQ = np.where(lambda k: inf.queueDict&#91;k]&#91;1] &lt;= inf.q)  \nif withinQ&#91;0] != 0:  \ninf.PID = int(withinQ&#91;0])\n\n  \n\ndef run_Priority():  \ninf = Info()  \ncompleted = inf.completed  \nreferenceDict = inf.referenceDict\n\nprint('system running')  \nwhile len(completed) != len(referenceDict):  \nfor process in referenceDict:  \ninf.PID = process  \ncoreStatus = inf.coreStatus  \nif coreStatus == 0:  \nif len(inf.queueDict) != 0:  \ncheck_Priority()  \nenterCore()  \nwhile inf.instructionLoad &gt; 0:  \nsystem_cycle()  \nif inf.PID &lt; len(completed):  \nbreak\n\nprint('system finished')\n\ncreate_process()  \nrun_Priority()<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Round Robin<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>from openpyxl import load_workbook\nimport numpy as np\nworkbook = load_workbook(filename='cpu-scheduling.xlsx')\nsheet = workbook.active\n\nall_data = {}\n\ndef create_process():\n\n    for row in sheet.iter_rows(min_row=2, values_only=True):\n\n        processID = row&#91;0]\n        process = &#91;row&#91;1], row&#91;2], row&#91;3], 0]\n        processToDict = {processID:process}\n        all_data.update(processToDict)\n\n\nclass Info():\n    instance = None\n    def __new__(cls):\n        if cls.instance is None:\n            cls.instance = super(Info, cls).__new__(cls)\n        return cls.instance\n\n    PID = 0\n    referenceDict = all_data\n    timeUnit = 0\n    queueDict = {}\n    activeCore = {}\n    queuePrint = ''\n    waitPrint = ''\n    instructionLoad = 0\n    processInfo = &#91;]\n    queueSize = len(queueDict)\n    coreStatus = len(activeCore)\n    completed = {}\n    q = 4\n    timeInCore = 0\n\ndef processCore():\n    inf = Info()\n    activeCore = inf.activeCore\n    timeUnit = inf.timeUnit\n    queuePrint = inf.queuePrint\n    PID = next(iter(activeCore))\n    startingInst = inf.referenceDict&#91;PID]&#91;1]\n    print('Time Unit \n    inf.instructionLoad -= 1\n    inf.timeInCore += 1\n    if inf.instructionLoad == 0:\n        del inf.activeCore&#91;PID]\n        inf.completed&#91;PID] = inf.referenceDict&#91;PID]\n\ndef enterCore():\n\n    inf = Info()\n    PID = inf.PID\n    queueDict = inf.queueDict\n    activeCore = inf.activeCore\n    inf.timeInCore = 0\n    if len(queueDict) == 0:\n        inf.activeCore&#91;PID] = inf.referenceDict&#91;PID]\n    elif inf.PID in inf.queueDict:\n        inf.activeCore&#91;PID] = inf.queueDict&#91;PID]\n        del inf.queueDict&#91;PID]\n    if activeCore:\n        inf.instructionLoad = activeCore&#91;PID]&#91;1]\n\ndef processWait():\n    inf = Info()\n    referenceDict = inf.referenceDict\n    timeUnit = inf.timeUnit\n    activeCore = inf.activeCore\n    queueDict = inf.queueDict\n    PID = inf.PID\n\n    for check in referenceDict:\n        arrivalTime = referenceDict&#91;check]&#91;0]\n        if arrivalTime == timeUnit:\n            inf.queueDict&#91;check] = inf.referenceDict&#91;check]\n            if activeCore:\n                if queueDict&#91;check] == activeCore&#91;PID]:\n                    del inf.queueDict&#91;check]\n    if len(queueDict) == 0:\n        inf.queuePrint = 'No queue.'\n    else:\n        inf.queuePrint = '\n\n\n\ndef system_cycle():\n    inf = Info()\n\n    inf.timeUnit += 1\n    processWait()\n    processCore()\n\ndef check_Shortest():\n    inf = Info()\n    shortestJobPID = min(inf.queueDict, key = lambda k: inf.queueDict&#91;k]&#91;1])\n    inf.PID = shortestJobPID\n\ndef check_Priority():\n    inf = Info()\n    lowestPrio = min(inf.queueDict, key = lambda k: inf.queueDict&#91;k]&#91;2])\n    inf.PID = lowestPrio\n\ndef time_slice_check():\n    inf = Info()\n    PID = inf.PID\n\n    if (inf.timeInCore == inf.q):\n        if inf.activeCore:\n            inf.queueDict&#91;PID] = inf.activeCore&#91;PID]\n            del inf.activeCore&#91;PID]\n            inf.queueDict&#91;PID]&#91;1] = inf.instructionLoad\n            inf.timeUnit += 1\n            processWait()\n            inf.instructionLoad = 0\n\ndef check_q():\n    inf = Info()\n    withinQ = np.where(lambda k: inf.queueDict&#91;k]&#91;1] &lt;= inf.q)\n    if withinQ&#91;0] != 0:\n        inf.PID = int(withinQ&#91;0])\n\n\ndef run_Priority():\n    inf = Info()\n    completed = inf.completed\n    referenceDict = inf.referenceDict\n\n    print('system running')\n    while len(completed) != len(referenceDict):\n        for process in referenceDict:\n            inf.PID = process\n            coreStatus = inf.coreStatus\n            if coreStatus == 0:\n                if len(inf.queueDict) != 0:\n                    check_Priority()\n                enterCore()\n            while inf.instructionLoad &gt; 0:\n                system_cycle()\n            if inf.PID &lt; len(completed):\n                break\n\n    print('system finished')\n\ncreate_process()\nrun_Priority()<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>This is an assignment written for Noroff University to simulate different CPU scheduler methods.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[38,39],"class_list":["post-215","post","type-post","status-publish","format-standard","hentry","category-cyber-security","tag-code","tag-python"],"_links":{"self":[{"href":"https:\/\/thewoodfordspider.com\/index.php\/wp-json\/wp\/v2\/posts\/215","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thewoodfordspider.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thewoodfordspider.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thewoodfordspider.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/thewoodfordspider.com\/index.php\/wp-json\/wp\/v2\/comments?post=215"}],"version-history":[{"count":3,"href":"https:\/\/thewoodfordspider.com\/index.php\/wp-json\/wp\/v2\/posts\/215\/revisions"}],"predecessor-version":[{"id":251,"href":"https:\/\/thewoodfordspider.com\/index.php\/wp-json\/wp\/v2\/posts\/215\/revisions\/251"}],"wp:attachment":[{"href":"https:\/\/thewoodfordspider.com\/index.php\/wp-json\/wp\/v2\/media?parent=215"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thewoodfordspider.com\/index.php\/wp-json\/wp\/v2\/categories?post=215"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thewoodfordspider.com\/index.php\/wp-json\/wp\/v2\/tags?post=215"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}