class Paging:
    def __init__(self, memory, instructions_per_frame, hdd):
        self._memory = memory
        self._instructions_per_frame = instructions_per_frame
        self._frames = []
        self._frame_manager = FrameManager(self._frames, hdd)
        self._page_creator = PageCreator(instructions_per_frame)
        self.generate_frames()

    def assign_to_hdd(self, hdd, pcb):
        self._page_creator.create(pcb, self._instructions_per_frame)

    def memory_size(self):
        return self._memory.size()

    def get_amount_of_frames(self):
        return len(self._frames)

    def __can_create(self):
        return self.memory_size() % self._instructions_per_frame == 0

    def get_frame_for_current_instruction(self, pcb):
        self._frame_manager.get_frames_of_pcb(pcb)

    def generate_frames(self):
        if self.__can_create():
            self.__create_frames()

    def __create_frames(self):
        index = 0
        print("Creating frames...")
        for split in range(0, self.memory_size(), self._instructions_per_frame):
            self._frames.append(Frame(index, split, split + self._instructions_per_frame - 1))
            index += 1

    def assign_to_memory(self, pcb):
        if pcb.get_memory_policy_for_pcb().has_no_data():
            self._page_creator.create(pcb, self._instructions_per_frame)

        policy_result = self.pages_for_pcb(pcb)
        return policy_result

    def pages_for_pcb(self, pcb):
        return self._frame_manager.map_page_to_frame(pcb)

    def can_serve(self, pcb):
        return self.get_amount_of_free_frames() >= self.frames_per_pcb(pcb)

    def frames_per_pcb(self, pcb):
        return pcb.get_amount_of_instructions() / self._page_creator.get_instructions_per_frame()

    def get_amount_of_free_frames(self):
        return len(FunctionsForLists.filterList(lambda f: not f.is_in_use(), self._frames))

    def set_memory_manager(self, memory_manager):
        self._memory_manager = memory_manager

    def get_info_holder(self, program):
        return PageHolder(program)
 def __init__(self, memory, instructions_per_frame, hdd):
     self._memory = memory
     self._instructions_per_frame = instructions_per_frame
     self._frames = []
     self._frame_manager = FrameManager(self._frames, hdd)
     self._page_creator = PageCreator(instructions_per_frame)
     self.generate_frames()
 def setUp(self):
     program = Program('Excel')
     pageHolder = PageHolder(program)
     self.frame1 = Frame(0, 9, -1)
     self.frame2 = Frame(1, 9, -1)
     self.frame3 = Frame(2, 9, -1)
     self.frame4 = Frame(3, 9, -1)
     self.frames = [self.frame1, self.frame2, self.frame3, self.frame4]
     self.hdd = HDD(50)
     self.frame_manager = FrameManager(self.frames, self.hdd)
     self.page_creator = PageCreator()
     self.pcb = PCB(0, 30, pageHolder)
     self.page_creator.create(self.pcb, 5)
class FrameManagerTest(unittest.TestCase):

    # Arrange
    def setUp(self):
        program = Program('Excel')
        pageHolder = PageHolder(program)
        self.frame1 = Frame(0, 9, -1)
        self.frame2 = Frame(1, 9, -1)
        self.frame3 = Frame(2, 9, -1)
        self.frame4 = Frame(3, 9, -1)
        self.frames = [self.frame1, self.frame2, self.frame3, self.frame4]
        self.hdd = HDD(50)
        self.frame_manager = FrameManager(self.frames, self.hdd)
        self.page_creator = PageCreator()
        self.pcb = PCB(0, 30, pageHolder)
        self.page_creator.create(self.pcb, 5)

    def test_whenIAssignAPCBTheFirstTime_ThenFrameManagerUsesTheFirstFrame(self):
        # Pages
        first_frame = self.frame_manager.get_frames()[0]
        self.frame_manager.map_page_to_frame(self.pcb)
        first_pcb_page = self.pcb.get_page_assigned_by_number(0)
        self.assertEquals(first_frame.get_page(), first_pcb_page)

    def test_whenTheFirstPCBPageIsUsedAndPCBIsAssigned_ThenFrameManagerUsesTheSecondFrame(self):
        # Pages
        first_pcb_page = self.pcb.get_page_assigned_by_number(0)
        second_pcb_page =self.pcb.get_page_assigned_by_number(1)

        self.frame_manager.map_page_to_frame(self.pcb)
        first_pcb_page.set_used()

        self.frame_manager.map_page_to_frame(self.pcb)
        second_frame = self.frame_manager.get_frames()[1]
        self.assertEquals(second_frame.get_page(), second_pcb_page)

    def test_whenAllFramesAreUsedAndPCBAssignsOneMorePage_ThenTheYoungestFrameGetsEmpty(self):
        # Pages
        first_pcb_page = self.pcb.get_page_assigned_by_number(0)
        second_pcb_page = self.pcb.get_page_assigned_by_number(1)
        assert (second_pcb_page != None)
        third_pcb_page = self.pcb.get_page_assigned_by_number(2)
        forth_pcb_page = self.pcb.get_page_assigned_by_number(3)
        fifth_pcb_page = self.pcb.get_page_assigned_by_number(4)

        self.frame_manager.map_page_to_frame(self.pcb)
        first_pcb_page.set_used()
        self.frame_manager.map_page_to_frame(self.pcb)
        second_pcb_page.set_used()
        self.frame_manager.map_page_to_frame(self.pcb)
        third_pcb_page.set_used()
        self.frame_manager.map_page_to_frame(self.pcb)
        forth_pcb_page.set_used()

        forth_frame = self.frame_manager.get_frames()[3]

        self.frame_manager.map_page_to_frame(self.pcb)
        self.assertEqual(forth_frame.get_page(), fifth_pcb_page)