def __init__(self, name: str, subtrees: List[TMTree], authors: str = '', doi: str = '', citations: int = 0, by_year: bool = True, all_papers: bool = False) -> None: """Initialize a new PaperTree with the given <name> and <subtrees>, <authors> and <doi>, and with <citations> as the size of the data. If <all_papers> is True, then this tree is to be the root of the paper tree. In that case, load data about papers from DATA_FILE to build the tree. If <all_papers> is False, Do NOT load new data. <by_year> indicates whether or not the first level of subtrees should be the years, followed by each category, subcategory, and so on. If <by_year> is False, then the year in the dataset is simply ignored. """ # TODO: Complete this initializer. Your implementation must not # TODO: duplicate anything done in the superclass initializer. self._doi = doi self._authors = authors TMTree.__init__(self, name, subtrees, citations) if all_papers: paper_dict = _load_papers_to_dict(by_year) self._subtrees = _build_tree_from_dict(paper_dict) if not self._subtrees: self.data_size = citations else: self.data_size = 0 for t in self._subtrees: self.data_size += t.data_size t._parent_tree = self
def test_two_qual_height_tree(self): leaf = TMTree("leaf", [], 50) leaf2 = TMTree("leaf2", [], 50) leaf3 = TMTree("leaf3", [], 50) leaf4 = TMTree("leaf4", [], 50) internal1 = TMTree("internal1", [leaf, leaf2], 0) internal2 = TMTree("internal2", [leaf3, leaf4], 0) root = TMTree("root", [internal1, internal2], 0) rect = (0, 0, 100, 100) set_expanded(root) root.update_rectangles(rect) self.assertEqual(root.rect, rect, "Root's size should be same with the given argument") self.assertEqual(internal1.rect, (0, 0, 100, 50), "internal1's height should take half of the root") self.assertEqual(internal2.rect, (0, 50, 100, 50), "internal2's height should take half of the root") self.assertEqual( leaf.rect, (0, 0, 50, 50), "leaf(the first leaf of internal1)'s weight should take half of the internal1" ) self.assertEqual( leaf2.rect, (50, 0, 50, 50), "leaf2(the second leaf of internal1)'s weight should take second half of the internal1" ) self.assertEqual( leaf3.rect, (0, 50, 50, 50), "leaf3(the first leaf of internal2)'s weight shoudl take half of the internal2's weight" ) self.assertEqual( leaf4.rect, (50, 50, 50, 50), "leaf4(the second leaf of internal2)'s weight should take half of the internal2's weight" )
def test_tmtree_setup_with_subtrees(self): subtree1 = TMTree('subtree1', [], 10) subtree2 = TMTree('subtree2', [], 20) t = TMTree('Easy4.0', [subtree1, subtree2], 100) self.assertEqual(t.data_size, 30, 'non-leaf data size is wrong') self.assertEqual(subtree1._parent_tree, t, 'parent should be set') self.assertEqual(subtree2._parent_tree, t, 'parent should be set')
def __init__(self, name: str, subtrees: List[TMTree], authors: str = '', doi: str = '', citations: int = 0, by_year: bool = True, all_papers: bool = False) -> None: """Initialize a new PaperTree with the given <name> and <subtrees>, <authors> and <doi>, and with <citations> as the size of the data. If <all_papers> is True, then this tree is to be the root of the paper tree. In that case, load data about papers from DATA_FILE to build the tree. If <all_papers> is False, Do NOT load new data. <by_year> indicates whether or not the first level of subtrees should be the years, followed by each category, subcategory, and so on. If <by_year> is False, then the year in the dataset is simply ignored. """ if all_papers: tree_inf = _load_papers_to_dict(by_year) tree_dict = _build_tree_from_dict(tree_inf) TMTree.__init__(self, name, tree_dict, citations) self._authors, self._doi = authors, doi else: TMTree.__init__(self, name, subtrees, citations) self._authors, self._doi = authors, doi
def test_one_level_tree(self): leaf = TMTree("leaf", [], 30) root = TMTree("root", [leaf], 40) rect = (0, 0, 100, 100) root.update_rectangles(rect) self.assertCountEqual(leaf.rect, rect, "") self.assertCountEqual( root.rect, rect, "Since the tree only contains a leaf so the root's rect should be same with leaf" )
def run_visualisation(tree: TMTree) -> None: """Display an interactive graphical display of the given tree's treemap. """ # Setup pygame pygame.init() screen = pygame.display.set_mode((WIDTH, HEIGHT)) # Render the initial display of the static treemap. render_display(screen, tree, None, None) tree.update_rectangles((0, 0, WIDTH, HEIGHT - FONT_HEIGHT)) # Start an event loop to respond to events. event_loop(screen, tree)
def test_tmtree_setup_no_subtree(self): t = TMTree('Easy4.0', [], 50) self.assertIsInstance(t.data_size, int, 'data_size is not instantiated correctly') self.assertIsInstance(t._colour, tuple, '_colour is not instantiated correctly') self.assertEqual(t.data_size, 50, 'leaf data size is wrong')
def test_different_direction_task5(self): leaf = TMTree("leaf", [], 50) leaf2 = TMTree("leaf2", [], 30) leaf3 = TMTree("leaf3", [], 70) internal = TMTree("internal", [leaf2, leaf3], 0) root = TMTree("root", [internal, leaf], 0) rect = (0, 0, 210, 160) exp = [(0, 0, 140, 160), (140, 0, 70, 160)] root._expanded = True root.update_rectangles(rect) temp = root.get_rectangles() assert len(temp) == 2 act = [sub[0] for sub in temp] self.assertCountEqual( act, exp, "For task5 you should return every leaf of the displayed tree")
def anan() -> None: x = TMTree("Anan", [TMTree("Deden", [], 5), TMTree("Deden", [], 5), TMTree("Deden", [], 5)]) x.update_rectangles((0, 0, 200, 100)) print(x.rect) print(x._subtrees[0].rect) print(x._subtrees[1].rect) print(x._subtrees[2].rect)
def _sort_subtrees(tree: TMTree) -> None: """Sort the subtrees of <tree> in alphabetical order. THIS IS FOR THE PURPOSES OF THE SAMPLE TEST ONLY; This allows the sample test to run on different operating systems. This is recursive, and affects all levels of the tree. """ if not tree.is_empty(): for subtree in tree._subtrees: _sort_subtrees(subtree) tree._subtrees.sort(key=lambda t: t._name)
def __init__(self, name: str, subtrees: List[TMTree], authors: str = '', doi: str = '', citations: int = 0, by_year: bool = True, all_papers: bool = False) -> None: """Initialize a new PaperTree with the given <name> and <subtrees>, <authors> and <doi>, and with <citations> as the size of the data. If <all_papers> is True, then this tree is to be the root of the paper tree. In that case, load data about papers from DATA_FILE to build the tree. If <all_papers> is False, Do NOT load new data. <by_year> indicates whether or not the first level of subtrees should be the years, followed by each category, subcategory, and so on. If <by_year> is False, then the year in the dataset is simply ignored. """ all_sub_tree = [] # all the sub-folders of this folder all_data = _load_papers_to_dict(by_year) if not all_papers: self._authors = authors self._doi = doi TMTree.__init__(self, name, subtrees, citations) else: for key in all_data: temp_subtree = _build_tree_from_dict(all_data[key]) all_sub_tree.append( PaperTree(key, temp_subtree, by_year=by_year)) self._authors = authors self._doi = doi TMTree.__init__(self, name, all_sub_tree)
def test_two_leaves_task5(self): leaf = TMTree("leaf", [], 30) leaf2 = TMTree("leaf", [], 70) root = TMTree("root", [leaf, leaf2], 0) rect = (0, 0, 1000, 100) root.update_rectangles(rect) temp = root.get_rectangles() assert len(temp) == 1 exp = [rect] act = [sub[0] for sub in temp] self.assertCountEqual( act, exp, "For task 5 you should return every leaf of the displayed tree")
def test_get_rectangle_task5(self): leaf = TMTree("leaf", [], 30) root = TMTree("root", [leaf], 40) rect = (0, 0, 100, 100) root.update_rectangles(rect) act = root.get_rectangles() assert len(act) == 1 self.assertEqual( act[0][0], rect, "For task 5 you should return every leaf of the DISPLAYED tree")
def test_two_leaves_task2(self): leaf = TMTree("leaf", [], 30) leaf2 = TMTree("leaf", [], 70) root = TMTree("root", [leaf, leaf2], 0) rect = (0, 0, 1000, 100) set_expanded(root) root.update_rectangles(rect) temp = root.get_rectangles() assert len(temp) == 2 exp = [(0, 0, 300, 100), (300, 0, 700, 100)] act = [sub[0] for sub in temp] self.assertCountEqual( act, exp, "For task 2 you should return every leaf of the data tree")
def _handle_click(button: int, pos: Tuple[int, int], tree: TMTree, old_selected_leaf: Optional[TMTree]) -> Optional[TMTree]: """Return the new selection after handling the mouse event. We need to use old_selected_leaf to handle the case when the selected leaf is left-clicked again. """ if button == 1: selected_leaf = tree.get_tree_at_position(pos) if selected_leaf is None: return old_selected_leaf elif selected_leaf is old_selected_leaf: return None else: return selected_leaf # right click or any other click does nothing else: return old_selected_leaf
def test_two_leaves_round(self): leaf = TMTree("leaf", [], 30) leaf2 = TMTree("leaf", [], 69) root = TMTree("root", [leaf, leaf2], 0) rect = (0, 0, 200, 100) root.update_rectangles(rect) self.assertCountEqual(leaf.rect, (0, 0, 60, 100), "Round down the proportion of the leaf") self.assertCountEqual(leaf2.rect, (60, 0, 140, 100), "Round down the proportion of the leaf") self.assertCountEqual( root.rect, rect, "The root's rect should be exact same with the given argument")
def test_two_leaves_round2(self): leaf = TMTree("leaf", [], 29) leaf2 = TMTree("leaf", [], 70) root = TMTree("root", [leaf, leaf2], 0) rect = (0, 0, 100, 200) root.update_rectangles(rect) self.assertCountEqual( leaf.rect, (0, 0, 100, 58), "You should calculate the correct proportion of the leaf") self.assertCountEqual( leaf2.rect, (0, 58, 100, 142), "You should calculate the correct proportion of the leaf") self.assertCountEqual( root.rect, rect, "The root's rect should be exact same with the given argument")
def test_different_direction(self): leaf = TMTree("leaf", [], 50) leaf2 = TMTree("leaf2", [], 30) leaf3 = TMTree("leaf3", [], 70) internal = TMTree("internal", [leaf2, leaf3], 0) root = TMTree("root", [internal, leaf], 0) rect = (0, 0, 210, 160) set_expanded(root) root.update_rectangles(rect) self.assertEqual(root.rect, rect, "Root's size should be same with the given argument") self.assertEqual( internal.rect, (0, 0, 140, 160), "internal's width takes the 2/3 of the given argument") self.assertEqual(leaf.rect, (140, 0, 70, 160), "leaf's width should take 1/3 of the given argument") self.assertEqual( leaf2.rect, (0, 0, 140, 48), "leaf 2 (The first leaf of internal)'s height should take 3/10 of INTERNAL'S HEIGHT" ) self.assertEqual( leaf3.rect, (0, 48, 140, 112), "leaf3 (The second leaf of internal)'s height should take 7/10 of INTERNAL'S HEIGHT" )
def _handle_click(button: int, pos: Tuple[int, int], tree: TMTree, old_selected_leaf: Optional[TMTree]) -> Optional[TMTree]: """Return the new selection after handling the mouse event. We need to use old_selected_leaf to handle the case when the selected leaf is left-clicked again. """ # TODO: Delete the line below after completing Task 3 # left mouse click if button == 1: for subtree in tree._subtrees: print(subtree.rect) selected_leaf = tree.get_tree_at_position(pos) if selected_leaf is None: return old_selected_leaf elif selected_leaf is old_selected_leaf: return None else: return selected_leaf # right click or any other click does nothing else: return old_selected_leaf
def __init__(self, name: str, subtrees: List[TMTree], authors: str = '', doi: str = '', citations: int = 0, by_year: bool = True, all_papers: bool = False) -> None: self._doi = doi self._authors = authors if all_papers: if by_year: tree = _build_tree_from_dict(_load_papers_to_dict(True)) TMTree.__init__(self, name, tree, citations) else: tree = _build_tree_from_dict(_load_papers_to_dict(False)) TMTree.__init__(self, name, tree, citations) else: TMTree.__init__(self, name, subtrees, citations) """Initialize a new PaperTree with the given <name> and <subtrees>,
def __init__(self, name: str, subtrees: List[TMTree], authors: str = '', doi: str = '', citations: int = 0, by_year: bool = True, all_papers: bool = False) -> None: """Initialize a new PaperTree with the given <name> and <subtrees>, <authors> and <doi>, and with <citations> as the size of the data. If <all_papers> is True, then this tree is to be the root of the paper tree. In that case, load data about papers from DATA_FILE to build the tree. If <all_papers> is False, Do NOT load new data. <by_year> indicates whether or not the first level of subtrees should be the years, followed by each category, subcategory, and so on. If <by_year> is False, then the year in the dataset is simply ignored. """ if subtrees == []: TMTree.__init__(self, name, subtrees, citations) # i.e our file is a self._doi = doi self._authors = authors # self._citation = citations ### Data_size self._by_year = by_year if not all_papers and subtrees != []: TMTree.__init__(self, name, subtrees, citations) self._doi = doi self._authors = authors self._by_year = by_year if all_papers: x = _get_paper_list(by_year) subtrees = _build_tree_from_dict(x) TMTree.__init__(self, name, subtrees, citations) self._doi = doi self._authors = authors self._by_year = by_year
def test_two_qual_height_tree_task5_2(self): leaf = TMTree("leaf", [], 50) leaf2 = TMTree("leaf2", [], 50) leaf3 = TMTree("leaf3", [], 50) leaf4 = TMTree("leaf4", [], 50) internal1 = TMTree("internal1", [leaf, leaf2], 0) internal2 = TMTree("internal2", [leaf3, leaf4], 0) root = TMTree("root", [internal1, internal2], 0) rect = (0, 0, 100, 100) root._expanded = True internal2._expanded = True root.update_rectangles(rect) exp = [(0, 0, 100, 50), (0, 50, 50, 50), (50, 50, 50, 50)] temp = root.get_rectangles() assert len(temp) == 3 act = [sub[0] for sub in temp] self.assertCountEqual( act, exp, "For task 5 you should only return leaf in the DISPLAY tree")
def test_tmtree_setup_recursive_data_size(self): subtree1 = TMTree('subtree1', [TMTree('subtree11', [], 1000)], 10) subtree2 = TMTree('subtree2', [TMTree('subtree21', [], 2000)], 20) t = TMTree('Easy4.0', [subtree1, subtree2], 666) self.assertEqual(t.data_size, 3000, 'non-leaf data size is wrong')
def test_complicate(self): leafI = TMTree("leaf", [], 20) leafJ = TMTree("leaf2", [], 15) folderD = TMTree("folderD", [leafI, leafJ], 50) leafE = TMTree("leaf3", [], 35) folderA = TMTree("folderA", [folderD, leafE], 0) leafK = TMTree("leafK", [], 40) leafL = TMTree("leafL", [], 10) folderF = TMTree("folderF", [leafK, leafL], 0) leafG = TMTree("leafG", [], 10) folderB = TMTree("folderB", [folderF, leafG], 0) leafO = TMTree("leafO", [], 20) leafP = TMTree("leafP", [], 20) folderM = TMTree("leafM", [leafO, leafP], 40) leafN = TMTree("leafN", [], 40) folderH = TMTree("folderH", [folderM, leafN], 0) folderC = TMTree("folderC", [folderH], 0) root = TMTree("root", [folderA, folderB, folderC], 0) set_expanded(root) rect = (0, 0, 210, 60) root.update_rectangles(rect) self.assertEqual( root.rect, rect, "Root's rectangle should be same with given argument") self.assertEqual( folderA.rect, (0, 0, 70, 60), "folderA(The first internal node of root)'s width should be 1/3 of the given argument" ) self.assertEqual( folderB.rect, (70, 0, 60, 60), "folderB(The second internal node of root)'s width should be 6/21 of the given argument" ) self.assertEqual( folderC.rect, (130, 0, 80, 60), "folderC(The third internal node of root)'s width should be 8/21 of the given argument" ) self.assertEqual( folderD.rect, (0, 0, 35, 60), "folderD(The first internal node of folderA)'s width should be 1/2 of folderA's width" ) self.assertEqual( leafE.rect, (35, 0, 35, 60), "leafE(The second element of folderA)'s width should take second half of folderA's width" ) self.assertEqual( leafI.rect, (0, 0, 35, 34), "leafI(The first leaf of folderD)'s height should be 20/35 of the folderD's height" ) self.assertEqual( leafJ.rect, (0, 34, 35, 26), "leafJ(The second leaf of folderD)'s height should be 15/35 of the folderD's height" ) self.assertEqual( folderF.rect, (70, 0, 60, 50), "folderF(The first child of folderB)'s height should be 5/6 of the folderB's height" ) self.assertEqual( leafG.rect, (70, 50, 60, 10), "leafG(The second child of folderB)'s height should be 1/6 of the folderB's hegiht" ) self.assertEqual( leafK.rect, (70, 0, 48, 50), "leafK(The first child of folderF)'s width should be 4/5 of the folderF's width" ) self.assertEqual( leafL.rect, (118, 0, 12, 50), "leafL(The second child of folderF)'s width should be 1/5 of the folderF's width" ) self.assertEqual( folderH.rect, (130, 0, 80, 60), "folderH(The only child of folderC)'s rect should be same with folderC" ) self.assertEqual( folderM.rect, (130, 0, 40, 60), "folderM(The first child of folderH)'s width should be half of the folderH's width" ) self.assertEqual( leafN.rect, (170, 0, 40, 60), "leafN(The second child of folderH)'s width should be the second half of the folderH" ) self.assertEqual( leafO.rect, (130, 0, 40, 30), "leafO(The first child of folderM)'s height should be the half of the folderM's height" ) self.assertEqual( leafP.rect, (130, 30, 40, 30), "leafP(The second child of folderM)'s height should be the half of the folderM's height" )
def test_complicate_task5_3(self): leafI = TMTree("leaf", [], 20) leafJ = TMTree("leaf2", [], 15) folderD = TMTree("folderD", [leafI, leafJ], 50) leafE = TMTree("leaf3", [], 35) folderA = TMTree("folderA", [folderD, leafE], 0) leafK = TMTree("leafK", [], 40) leafL = TMTree("leafL", [], 10) folderF = TMTree("folderF", [leafK, leafL], 0) leafG = TMTree("leafG", [], 10) folderB = TMTree("folderB", [folderF, leafG], 0) leafO = TMTree("leafO", [], 20) leafP = TMTree("leafP", [], 20) folderM = TMTree("leafM", [leafO, leafP], 40) leafN = TMTree("leafN", [], 40) folderH = TMTree("folderH", [folderM, leafN], 0) folderC = TMTree("folderC", [folderH], 0) root = TMTree("root", [folderA, folderB, folderC], 0) root._expanded = True folderA._expanded = True folderB._expanded = True folderC._expanded = True rect = (0, 0, 210, 60) root.update_rectangles(rect) exp = [(0, 0, 35, 60), (35, 0, 35, 60), (70, 0, 60, 50), (70, 50, 60, 10), (130, 0, 80, 60)] temp = root.get_rectangles() assert len(temp) == 5 act = [sub[0] for sub in temp] self.assertCountEqual( act, exp, "For task 5 you should return every leaf in the DISPLAYED tree")
def test_single_leaf(self): leaf = TMTree("leaf", [], 30) rect = (0, 0, 100, 100) leaf.update_rectangles(rect) self.assertCountEqual(leaf.rect, rect, "The leaf should have the exact rect as given")
def test_two_qual_height_tree_task2(self): leaf = TMTree("leaf", [], 50) leaf2 = TMTree("leaf2", [], 50) leaf3 = TMTree("leaf3", [], 50) leaf4 = TMTree("leaf4", [], 50) internal1 = TMTree("internal1", [leaf, leaf2], 0) internal2 = TMTree("internal2", [leaf3, leaf4], 0) root = TMTree("root", [internal1, internal2], 0) rect = (0, 0, 100, 100) set_expanded(root) root.update_rectangles(rect) exp = [(0, 0, 50, 50), (50, 0, 50, 50), (0, 50, 50, 50), (50, 50, 50, 50)] temp = root.get_rectangles() assert len(temp) == 4 act = [sub[0] for sub in temp] self.assertCountEqual( act, exp, "For task 2 you should return every leaf in the DATA tree")
def event_loop(screen: pygame.Surface, tree: TMTree) -> None: """Respond to events (mouse clicks, key presses) and update the display. Note that the event loop is an *infinite loop*: it continually waits for the next event, determines the event's type, and then updates the state of the visualisation or the tree itself, updating the display if necessary. This loop ends only when the user closes the window. """ selected_node = None while True: # Wait for an event event = pygame.event.poll() if event.type == pygame.QUIT: return # get the hover position and the corresponding node hover_node = tree.get_tree_at_position(pygame.mouse.get_pos()) if event.type == pygame.MOUSEBUTTONUP: selected_node = \ _handle_click(event.button, event.pos, tree, selected_node) elif event.type == pygame.KEYUP and selected_node is not None: if event.key == pygame.K_UP: #pass # TODO: Uncomment once you have completed Task 4 selected_node.change_size(0.01) tree.update_data_sizes() tree.update_rectangles((0, 0, WIDTH, HEIGHT - FONT_HEIGHT)) elif event.key == pygame.K_DOWN: #pass # TODO: Uncomment once you have completed Task 4 selected_node.change_size(-0.01) tree.update_data_sizes() tree.update_rectangles((0, 0, WIDTH, HEIGHT - FONT_HEIGHT)) elif event.key == pygame.K_m: #pass # TODO: Uncomment once you have completed Task 4 selected_node.move(hover_node) tree.update_data_sizes() tree.update_rectangles((0, 0, WIDTH, HEIGHT - FONT_HEIGHT)) elif event.key == pygame.K_e: pass # TODO: Uncomment once you have completed Task 5 # selected_node.expand() elif event.key == pygame.K_a: pass # TODO: Uncomment once you have completed Task 5 # selected_node.expand_all() elif event.key == pygame.K_c: pass # TODO: Uncomment once you have completed Task 5 # selected_node.collapse() elif event.key == pygame.K_x: pass # TODO: Uncomment once you have completed Task 5 # selected_node.collapse_all() # Update display render_display(screen, tree, selected_node, hover_node)
def test_complicate_task2(self): leafI = TMTree("leaf", [], 20) leafJ = TMTree("leaf2", [], 15) folderD = TMTree("folderD", [leafI, leafJ], 50) leafE = TMTree("leaf3", [], 35) folderA = TMTree("folderA", [folderD, leafE], 0) leafK = TMTree("leafK", [], 40) leafL = TMTree("leafL", [], 10) folderF = TMTree("folderF", [leafK, leafL], 0) leafG = TMTree("leafG", [], 10) folderB = TMTree("folderB", [folderF, leafG], 0) leafO = TMTree("leafO", [], 20) leafP = TMTree("leafP", [], 20) folderM = TMTree("leafM", [leafO, leafP], 40) leafN = TMTree("leafN", [], 40) folderH = TMTree("folderH", [folderM, leafN], 0) folderC = TMTree("folderC", [folderH], 0) root = TMTree("root", [folderA, folderB, folderC], 0) set_expanded(root) rect = (0, 0, 210, 60) set_expanded(root) root.update_rectangles(rect) exp = [(35, 0, 35, 60), (0, 0, 35, 34), (0, 34, 35, 26), (70, 50, 60, 10), (70, 0, 48, 50), (118, 0, 12, 50), (170, 0, 40, 60), (130, 0, 40, 30), (130, 30, 40, 30)] temp = root.get_rectangles() assert len(temp) == 9 act = [sub[0] for sub in temp] self.assertCountEqual( act, exp, "For task 2 you should return every leaf in the DATA tree")