def setUp(self): class FakeGui: def mega_refresh(self, recalibrate=False, auto_resize_canvas=True): pass self.g = Graph() self.overlap_remover = OverlapRemoval(self.g, margin=5, gui=FakeGui())
def test_7_generalisation_multiple_inhertitance(self): # START AGAIN - more tests, check multiple inheritance trees # See 'python-in/testmodule08_multiple_inheritance.py' # for another related unit test # F --|> M # F --|> S g = Graph() f = GraphNode("F", 0, 0, 200, 200) m = GraphNode("M", 0, 0, 200, 200) s = GraphNode("S", 0, 0, 200, 200) g.AddEdge(f, m)["uml_edge_type"] = "generalisation" g.AddEdge(f, s)["uml_edge_type"] = "generalisation" nodelist_normal = [node.id for node in g.nodes] # print "nodelist_normal", nodelist_normal nodelist_sorted = [ node.id for node, annotation in g.nodes_sorted_by_generalisation ] nodelist_sorted_expected = ["M", "F", "S"] assert nodelist_sorted_expected == nodelist_sorted, nodelist_sorted # print "nodelist_sorted_expected", nodelist_sorted_expected # print "nodelist_sorted", nodelist_sorted nodelist_sorted_annotated = [ (node.id, annotation) for node, annotation in g.nodes_sorted_by_generalisation ] nodelist_sorted_expected_annotated = [("M", "root"), ("F", "root"), ("S", "root")] assert (nodelist_sorted_expected_annotated == nodelist_sorted_annotated ), nodelist_sorted_annotated
class OverlapTests(unittest.TestCase): def setUp(self): class FakeGui: def mega_refresh(self, recalibrate=False, auto_resize_canvas=True): pass self.g = Graph() self.overlap_remover = OverlapRemoval(self.g, margin=5, gui=FakeGui()) def tearDown(self): pass def testStress1(self): for i in range(10): self.g.LoadGraphFromStrings(TEST_GRAPH5_STRESS) print(i, end=" ") were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.g.Clear() def testStress2_InitialBoot(self): """ This is the slowest stress test because it runs the spring layout several times. """ from layout.layout_spring import GraphLayoutSpring from layout.coordinate_mapper import CoordinateMapper self.g.LoadGraphFromStrings( GRAPH_INITIALBOOT) # load the scenario ourselves layouter = GraphLayoutSpring(self.g) coordmapper = CoordinateMapper(self.g, (800, 800)) def AllToLayoutCoords(): coordmapper.AllToLayoutCoords() def AllToWorldCoords(): coordmapper.AllToWorldCoords() for i in range(8): print(i, end=" ") AllToLayoutCoords() layouter.layout(keep_current_positions=False) AllToWorldCoords() were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed)
def test_3(self): """ Upgrade 1.0 to 1.1 """ g = Graph() filedata = """ # PynSource Version 1.0 {'type':'node', 'id':'UmlShapeCanvas', 'x':237, 'y':65, 'width':226, 'height':781, 'attrs':'scrollStepX|scrollStepY|evenfreddycansee|log|frame|save_gdi|working|font1|font2|umlworkspace|layout|coordmapper|layouter|overlap_remover', 'meths':'__init__|AllToLayoutCoords|AllToWorldCoords|onKeyPress|CmdInsertNewNode|CmdZapShape|Clear|ConvertParseModelToUmlModel|BuildEdgeModel|Go|CreateUmlShape|newRegion|CreateUmlEdge|OnWheelZoom|ChangeScale|stage1|stage2|stateofthenation|stateofthespring|RedrawEverything|ReLayout|LayoutAndPositionShapes|setSize|DecorateShape|createNodeShape|AdjustShapePosition|Redraw222|get_umlboxshapes|OnDestroy|OnLeftClick|DeselectAllShapes'} {'type':'node', 'id':'Log', 'x':1089, 'y':222, 'width':82, 'height':67, 'attrs':'', 'meths':'WriteText'} {'type':'node', 'id':'MainApp', 'x':788, 'y':217, 'width':234, 'height':717, 'attrs':'log|andyapptitle|frame|notebook|umlcanvas|yuml|asciiart|multiText|popupmenu|next_menu_id|printData|box|canvas|preview', 'meths':'OnInit|OnResizeFrame|OnRightButtonMenu|OnBuildGraphFromUmlWorkspace|OnSaveGraphToConsole|OnSaveGraph|OnLoadGraphFromText|OnLoadGraph|LoadGraph|OnTabPageChanged|InitMenus|Add|FileImport|FileImport2|FileImport3|FileNew|FilePrint|OnAbout|OnVisitWebsite|OnCheckForUpdates|OnHelp|OnDeleteNode|OnLayout|OnRefreshUmlWindow|MessageBox|OnButton|OnCloseFrame'} {'type':'node', 'id':'MyEvtHandler', 'x':10, 'y':173, 'width':170, 'height':285, 'attrs':'log|frame|shapecanvas|popupmenu', 'meths':'__init__|UpdateStatusBar|OnLeftClick|_SelectNodeNow|OnEndDragLeft|OnSizingEndDragLeft|OnMovePost|OnPopupItemSelected|OnRightClick|RightClickDeleteNode'} {'type':'edge', 'id':'UmlShapeCanvas_to_MainApp', 'source':'UmlShapeCanvas', 'target':'MainApp', 'uml_edge_type':'composition'} {'type':'edge', 'id':'ImageViewer_to_MainApp', 'source':'ImageViewer', 'target':'MainApp', 'uml_edge_type':'composition'} {'type':'edge', 'id':'UmlShapeCanvas_to_MainApp', 'source':'UmlShapeCanvas', 'target':'MainApp', 'uml_edge_type':'composition'} """ view.graph_persistence.PERSISTENCE_CURRENT_VERSION = 1.1 self.assertTrue( g.persistence.UpgradeToLatestFileFormatVersion(filedata)) # print g.persistence.filedata_list assert (g.persistence.filedata_list[0] == "# PynSource Version 1.1" ), g.persistence.filedata_list[0] assert "meta" in g.persistence.filedata_list[ 1], g.persistence.filedata_list[1] assert g.persistence.ori_file_version == 1.0 # now check type node has been converted to type umlshape data = eval(g.persistence.filedata_list[2]) self.assertEqual("umlshape", data.get("type"))
def test_4(self): """ Upgrade 1.1 to 1.1 """ g = Graph() filedata = """ # PynSource Version 1.1 {'type':'meta', 'info1':'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'} {'type':'umlshape', 'id':'UmlShapeCanvas', 'x':237, 'y':65, 'width':226, 'height':781, 'attrs':'scrollStepX|scrollStepY|evenfreddycansee|log|frame|save_gdi|working|font1|font2|umlworkspace|layout|coordmapper|layouter|overlap_remover', 'meths':'__init__|AllToLayoutCoords|AllToWorldCoords|onKeyPress|CmdInsertNewumlshape|CmdZapShape|Clear|ConvertParseModelToUmlModel|BuildEdgeModel|Go|CreateUmlShape|newRegion|CreateUmlEdge|OnWheelZoom|ChangeScale|stage1|stage2|stateofthenation|stateofthespring|RedrawEverything|ReLayout|LayoutAndPositionShapes|setSize|DecorateShape|createumlshapeShape|AdjustShapePosition|Redraw222|get_umlboxshapes|OnDestroy|OnLeftClick|DeselectAllShapes'} {'type':'umlshape', 'id':'Log', 'x':1089, 'y':222, 'width':82, 'height':67, 'attrs':'', 'meths':'WriteText'} {'type':'edge', 'id':'UmlShapeCanvas_to_MainApp', 'source':'UmlShapeCanvas', 'target':'MainApp', 'uml_edge_type':'composition'} """ view.graph_persistence.PERSISTENCE_CURRENT_VERSION = 1.1 self.assertTrue( g.persistence.UpgradeToLatestFileFormatVersion(filedata)) # print g.persistence.filedata_list assert (g.persistence.filedata_list[0] == "# PynSource Version 1.1" ), g.persistence.filedata_list[0] assert "meta" in g.persistence.filedata_list[ 1], g.persistence.filedata_list[1] assert g.persistence.ori_file_version == 1.1 # now check type node has been converted to type umlshape data = eval(g.persistence.filedata_list[2]) self.assertEqual("umlshape", data.get("type"))
class NoViewStrategy(ViewStrategy): def __init__(self, x_dim: float, y_dim: float): super().__init__(x_dim, y_dim) self.graph = Graph(x_dim, y_dim) self.people = None def update(self, people: List[Person]): self.people = people super().update(people) def finish(self): self.graph.update_distribution() self.graph.update_share( self.healthy_accumulation, self.infected_accumulation, self.ill_accumulation, self.convalescent_accumulation, self.dead_accumulation ) plt.show()
def test_6(self): """ Empty file """ g = Graph() filedata = """ """ view.graph_persistence.PERSISTENCE_CURRENT_VERSION = 1.1 self.assertFalse(g.persistence.can_I_read(filedata)[0]) self.assertFalse( g.persistence.UpgradeToLatestFileFormatVersion(filedata))
def test_5(self): """ Upgrade 1.1 to 1.0 - simulate loading a newer file format into an older version of the app Cannot read. (a bit strict, I know - but gui allows for forcing the read - see filemgmt.py) """ g = Graph() filedata = """ # PynSource Version 1.1 {'type':'meta', 'info1':'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'} {'type':'umlshape', 'id':'UmlShapeCanvas', 'x':237, 'y':65, 'width':226, 'height':781, 'attrs':'scrollStepX|scrollStepY|evenfreddycansee|log|frame|save_gdi|working|font1|font2|umlworkspace|layout|coordmapper|layouter|overlap_remover', 'meths':'__init__|AllToLayoutCoords|AllToWorldCoords|onKeyPress|CmdInsertNewumlshape|CmdZapShape|Clear|ConvertParseModelToUmlModel|BuildEdgeModel|Go|CreateUmlShape|newRegion|CreateUmlEdge|OnWheelZoom|ChangeScale|stage1|stage2|stateofthenation|stateofthespring|RedrawEverything|ReLayout|LayoutAndPositionShapes|setSize|DecorateShape|createumlshapeShape|AdjustShapePosition|Redraw222|get_umlboxshapes|OnDestroy|OnLeftClick|DeselectAllShapes'} {'type':'umlshape', 'id':'Log', 'x':1089, 'y':222, 'width':82, 'height':67, 'attrs':'', 'meths':'WriteText'} {'type':'edge', 'id':'UmlShapeCanvas_to_MainApp', 'source':'UmlShapeCanvas', 'target':'MainApp', 'uml_edge_type':'composition'} """ view.graph_persistence.PERSISTENCE_CURRENT_VERSION = 1.0 self.assertFalse( g.persistence.UpgradeToLatestFileFormatVersion(filedata)) self.assertFalse(g.persistence.can_I_read(filedata)[0])
def layout(self, keep_current_positions=False, optimise=True): if len(self.graph.nodes) == 0: print("Layout aborted - nothing to lay out.") return if not keep_current_positions: self.layoutPrepare() if self.gui: self.gui.kill_layout = False # initialise memento1 = self.graph.GetMementoOfLayoutPoints() break_pending = 0 for i in range(0, self.iterations): self.layoutIteration() if i % 100 == 0: # i%50==0: if self.gui: self.layoutCalcBounds( ) # this is the only time you need to call this explicitly since are in the MIDDLE of a layout and about to visualise self.gui.mega_refresh( recalibrate=True, auto_resize_canvas=False) # refresh gui if self.gui.kill_layout: print("Layout aborted early, due to user interrupt") break if i % 20 == 0: if optimise: memento2 = self.graph.GetMementoOfLayoutPoints() if Graph.MementosEqual(memento1, memento2, 0.01): break_pending += 1 # print "!", if break_pending > 5: # print "break" break else: break_pending = 0 # print ".", memento1 = memento2 # print self.layoutCalcBounds()
def test_2(self): """ Upgrade 0.9 (no version number) to 1.1 """ g = Graph() filedata = """ {'type':'node', 'id':'c', 'x':230, 'y':174, 'width':60, 'height':120} {'type':'node', 'id':'c1', 'x':130, 'y':174, 'width':60, 'height':120} {'type':'edge', 'id':'c_to_c1', 'source':'c', 'target':'c1'} """ view.graph_persistence.PERSISTENCE_CURRENT_VERSION = 1.1 self.assertTrue( g.persistence.UpgradeToLatestFileFormatVersion(filedata)) # print g.persistence.filedata_list assert (g.persistence.filedata_list[0] == "# PynSource Version 1.1" ), g.persistence.filedata_list[0] assert "meta" in g.persistence.filedata_list[ 1], g.persistence.filedata_list[1] assert g.persistence.ori_file_version == 0.9 # now check type node has been converted to type umlshape data = eval(g.persistence.filedata_list[2]) self.assertEqual("umlshape", data.get("type"))
def test_1(self): """ Upgrade 0.9 (no version number) to 1.0 """ g = Graph() filedata = """ {'type':'node', 'id':'c', 'x':230, 'y':174, 'width':60, 'height':120} {'type':'node', 'id':'c1', 'x':130, 'y':174, 'width':60, 'height':120} {'type':'edge', 'id':'c_to_c1', 'source':'c', 'target':'c1'} """ # g.Clear() assert len(g.nodes) == 0 # assert g.GraphToString().strip() == "" view.graph_persistence.PERSISTENCE_CURRENT_VERSION = 1.0 # g.LoadGraphFromStrings(filedata) self.assertTrue( g.persistence.UpgradeToLatestFileFormatVersion(filedata)) # print g.persistence.filedata_list assert (g.persistence.filedata_list[0] == "# PynSource Version 1.0" ), g.persistence.filedata_list[0] assert g.persistence.ori_file_version == 0.9
def test_8_multiple_inhertitance_render(self): # F --|> M # F --|> S g = Graph() f = GraphNode("F", 0, 0, 200, 200) m = GraphNode("M", 0, 0, 200, 200) s = GraphNode("S", 0, 0, 200, 200) g.AddEdge(f, m)["uml_edge_type"] = "generalisation" g.AddEdge(f, s)["uml_edge_type"] = "generalisation" nodelist_normal = [node.id for node in g.nodes] """ Custom ordering allows us to bypass the graph 'nodes_sorted_by_generalisation' algorithm which might either be crashing or have unwanted ordering results. Thus we can experiment with how different experimental orderings will render. """ mycustom_ordering = [(m, "root"), (s, "root"), (f, "root")] from ascii_uml.layout_ascii import model_to_ascii_builder m = model_to_ascii_builder() s = m.main(g, nodes_annotated_and_sorted=mycustom_ordering) expected_s = r""" +---+ | M | +---+ +---+ [ S ][ M ] | S | . +---+ /_\ | | +---+ | F | +---+ """ def remove_blank_lines(str): return os.linesep.join([s for s in str.splitlines() if s.strip()]) # remove blank lines, since different margins and paddings in ascii uml layout # could cause difference expected_s = remove_blank_lines(expected_s) s = remove_blank_lines(s) # print # print "*"*88 # print expected_s # print "*"*88 # print s # print "*"*88 if s.strip() != expected_s.strip(): print(s.strip()) print(expected_s.strip()) # Write to file with open(os.path.abspath("tests/logs/test_8_out_actual_.txt"), "w") as f: f.write(s) with open(os.path.abspath("tests/logs/test_8_out_expected.txt"), "w") as f: f.write(expected_s) import difflib # delta = difflib.ndiff(s.strip(), expected_s.strip()) # this will always emit something, a visual of the original with changes. delta = difflib.unified_diff(s.strip(), expected_s.strip(), n=0, fromfile="actual", tofile="expected") diff_s = "".join(delta) print(diff_s) assert s.strip() == expected_s.strip()
d2 = d * d attractiveForce = (d2 - self.k * self.k) / self.k nodeweight = edge.get("weight", None) # ANDY if (not nodeweight) or (edge["weight"] < 1): edge["weight"] = 1 attractiveForce *= math.log(edge["weight"]) * 0.5 + 1 node2.layoutForceX -= attractiveForce * dx / d node2.layoutForceY -= attractiveForce * dy / d node1.layoutForceX += attractiveForce * dx / d node1.layoutForceY += attractiveForce * dy / d if __name__ == "__main__": from graph import Graph g = Graph() n1 = GraphNode("A", 0, 0, 200, 200) n2 = GraphNode("B", 0, 0, 200, 200) g.AddEdge(n1, n2) layouter = GraphLayoutSpring(g) layouter.layout() for node in g.nodes: print(node, "layout info:", (node.layoutPosX, node.layoutPosY)) print("Done")
# print "rederive check Y % 3.4f % 3.4f \t\t%s" % (rederive_layoutPosY, node.layoutPosY, rederive_Y_ok) # print if node.left > 20000: print("-" * 40, "Something's gone wrong!") print("node.layoutPosX, node.layoutPosY", node.layoutPosX, node.layoutPosY) self.DumpCalibrationInfo(False) raise CustomException("Insane x values being generated") if __name__ == "__main__": from view.graph import Graph, GraphNode g = Graph() n1 = GraphNode("A", 0, 0, 200, 200) n2 = GraphNode("B", 0, 0, 200, 200) g.AddEdge(n1, n2) """ coordinate mapper translation tests """ # Force some values g.layoutMaxX, g.layoutMinX, g.layoutMaxY, g.layoutMinY = ( 5.14284838307, -7.11251323652, 4.97268108065, -5.77186339003, )
class OverlapTests(unittest.TestCase): def setUp(self): class FakeGui: def mega_refresh(self, recalibrate=False, auto_resize_canvas=True): pass self.g = Graph() self.overlap_remover = OverlapRemoval(self.g, margin=5, gui=FakeGui()) def tearDown(self): # pprint.pprint(self.overlap_remover.GetStats()) pass def test0_1OneNode(self): g = self.g g.AddNode(GraphNode("A", 0, 0, 250, 250)) were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertEqual( 0, self.overlap_remover.GetStats()["total_overlaps_found"]) def test0_2TwoNode_notoverlapping(self): g = self.g g.AddNode(GraphNode("A", 0, 0, 250, 250)) g.AddNode(GraphNode("B", 260, 0, 250, 250)) were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertEqual( 0, self.overlap_remover.GetStats()["total_overlaps_found"]) def test0_3TwoNode_overlapping(self): g = self.g g.AddNode(GraphNode("A", 0, 0, 250, 250)) g.AddNode(GraphNode("B", 200, 0, 250, 250)) were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertEqual( 1, self.overlap_remover.GetStats()["total_overlaps_found"]) def test0_4OverlapRemoverCreation(self): g = self.g a = GraphNode("A", 0, 0, 250, 250) a1 = GraphNode("A1", 0, 0) a2 = GraphNode("A2", 0, 0) g.AddEdge(a, a1) g.AddEdge(a, a2) were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) """ Smarter tests. Load scenarios from persistence and use special box comparison utility methods """ def _ensureXorder(self, *args): nodes = [self.g.FindNodeById(id) for id in args] assert len(nodes) >= 2 for i in range(0, len(nodes) - 1): if not nodes[i].right < nodes[i + 1].left: return False return True def _ensureXorderLefts(self, *args): nodes = [self.g.FindNodeById(id) for id in args] assert len(nodes) >= 2 for i in range(0, len(nodes) - 1): if not nodes[i].left < nodes[i + 1].left: return False return True def _ensureYorder(self, *args): nodes = [self.g.FindNodeById(id) for id in args] assert len(nodes) >= 2 for i in range(0, len(nodes) - 1): if not nodes[i].bottom < nodes[i + 1].top: return False return True def _ensureYorderBottoms(self, *args): nodes = [self.g.FindNodeById(id) for id in args] assert len(nodes) >= 2 for i in range(0, len(nodes) - 1): if not nodes[i].bottom < nodes[i + 1].bottom: return False return True def _LoadScenario1(self): self.g.LoadGraphFromStrings(TEST_GRAPH1) def test1_1MoveLeftPushedBackHorizontally01(self): self._LoadScenario1() # move m1 to the left node = self.g.FindNodeById("m1") node.left, node.top = (150, 9) # assert m1 has been pushed back to the right were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertEqual( 1, self.overlap_remover.GetStats()["total_overlaps_found"]) self.assertTrue(node.left > self.g.FindNodeById("D25").right) self.assertTrue(node.top < self.g.FindNodeById("D25").bottom) def test1_2MoveLeftPushedBackDownRight02(self): self._LoadScenario1() # move m1 to the left node = self.g.FindNodeById("m1") node.left, node.top = (106, 79) # assert m1 has been pushed back to the right but also down were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertEqual( 1, self.overlap_remover.GetStats()["total_overlaps_found"]) self.assertTrue(node.left > self.g.FindNodeById("D13").right) self.assertTrue(node.top > self.g.FindNodeById("D25").bottom) def test1_3MoveInsertedVertically1(self): self._LoadScenario1() # move m1 to the left node = self.g.FindNodeById("m1") node.left, node.top = (16, 74) # assert m1 has been squeezed in between the two existing were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertEqual( 2, self.overlap_remover.GetStats()["total_overlaps_found"]) # print self.g.GraphToString() self.assertTrue(node.top > self.g.FindNodeById("D25").bottom) self.assertTrue(node.bottom < self.g.FindNodeById("D13").top) self.assertTrue( self.g.FindNodeById("D13").top > self.g.FindNodeById("D25").bottom) self.assertTrue(node.left < self.g.FindNodeById("D25").right) self.assertTrue(node.left < self.g.FindNodeById("D13").right) def test1_4MovePushedVertically2(self): self._LoadScenario1() # move m1 to the left node = self.g.FindNodeById("m1") node.left, node.top = (6, 154) # assert m1 has been pushed vertically underneath the other two nodes were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertEqual( 1, self.overlap_remover.GetStats()["total_overlaps_found"]) self.assertTrue(self._ensureYorder("D25", "D13", "m1")) self.assertTrue(node.left < self.g.FindNodeById("D25").right) self.assertTrue(node.left < self.g.FindNodeById("D13").right) def _LoadScenario2(self): self.g.LoadGraphFromStrings(TEST_GRAPH2) def test2_1InsertAndPushedRightHorizontally(self): self._LoadScenario2() # move m1 to the left node = self.g.FindNodeById("m1") node.left, node.top = (121, 14) # assert m1 has been inserted and node to the right pushed right were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertEqual( 2, self.overlap_remover.GetStats()["total_overlaps_found"]) self.assertTrue(self._ensureXorder("D25", "m1", "D97")) self.assertTrue(self._ensureYorderBottoms( "m1", "D97")) # m1 bottom above D97 bottom def test2_2PushedRightAndDownNicely(self): self._LoadScenario2() # move m1 to the left node = self.g.FindNodeById("m1") node.left, node.top = (96, 114) # assert m1 has been pushed down and right nicely and snugly were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertEqual( 1, self.overlap_remover.GetStats()["total_overlaps_found"]) self.assertTrue(self._ensureXorder("D13", "m1")) self.assertTrue(self._ensureXorderLefts("D13", "m1", "D97")) self.assertTrue(self._ensureXorderLefts("D25", "m1", "D97")) self.assertTrue(self._ensureYorderBottoms("D25", "D97", "m1")) self.assertTrue(self._ensureYorder("D25", "m1")) self.assertTrue(self._ensureYorderBottoms("D25", "D13", "m1")) self.assertTrue(self._ensureYorderBottoms("D25", "D97", "m1")) def _LoadScenario3(self): self.g.LoadGraphFromStrings(TEST_GRAPH3) def test3_1PushedBetweenLeftAndRight(self): self._LoadScenario3() # move m1 to the left node = self.g.FindNodeById("m1") node.left, node.top = (266, 9) # assert m1 has been pushed between two nodes, horizontally. Both left and right nodes moved left and right respectively. were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertEqual( 2, self.overlap_remover.GetStats()["total_overlaps_found"]) GatherSnugProposals_ON = True # see method ProposeRemovalsAndApply() in overlap_removal.py if GatherSnugProposals_ON: # Newer snug behaviour self.assertTrue(self._ensureXorder("D25", "D97", "D98")) self.assertTrue(self._ensureYorder("D98", "m1")) self.assertTrue(self._ensureYorder("D97", "m1")) self.assertTrue(self._ensureYorder("D25", "m1")) else: # Older squeeze behaviour self.assertTrue(self._ensureXorder("D25", "D97", "m1", "D98")) self.assertTrue(self._ensureYorder("D25", "D13")) self.assertTrue(self._ensureYorderBottoms("D25", "D97", "D13")) def test3_2PushedBetweenLeftAndRightRefused(self): self._LoadScenario3() # move m1 to the left node = self.g.FindNodeById("m1") node.left, node.top = (226, 14) # assert m1 has been not been inserted - refused and snuggled instead were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertEqual( 1, self.overlap_remover.GetStats()["total_overlaps_found"]) self.assertTrue(self._ensureXorder("D25", "D97", "D98")) self.assertTrue(self._ensureXorder("D25", "D97", "m1")) self.assertTrue(self._ensureYorder("D98", "m1")) self.assertTrue(self._ensureYorderBottoms("D98", "D97", "m1")) def test3_2aPushedRefusedButLeftMovedAnyway(self): self._LoadScenario3() # move m1 to the left node = self.g.FindNodeById("m1") node.left, node.top = (281, 64) d97 = self.g.FindNodeById("D97") oldD97pos = (d97.left, d97.top) # assert m1 has been refused insertion, but left (D97) moved leftwards cos there is room. m1 snuggled below and to the right. were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertEqual( 2, self.overlap_remover.GetStats()["total_overlaps_found"]) self.assertTrue(self._ensureXorder("D25", "D97", "D98")) self.assertTrue(self._ensureXorder("D13", "D97", "m1")) self.assertTrue(self._ensureYorder("D25", "D13")) self.assertTrue(self._ensureYorder("D98", "m1")) self.assertTrue(self._ensureYorderBottoms("D98", "D97", "m1")) self.assertNotEqual( oldD97pos, (d97.left, d97.top)) # ensure D97 HAS been pushed left def test3_3InsertedAndTwoPushedRight(self): self._LoadScenario3() # move m1 to the left node = self.g.FindNodeById("m1") node.left, node.top = (146, 9) # assert m1 has been inserted - and two nodes pushed right were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertEqual( 3, self.overlap_remover.GetStats()["total_overlaps_found"]) self.assertTrue(self._ensureXorder("D25", "m1", "D97", "D98")) def test3_4InsertedVerticallyNothingPushedRight(self): self._LoadScenario3() # move m1 to the left node = self.g.FindNodeById("m1") node.left, node.top = (91, 64) d97 = self.g.FindNodeById("D97") oldD97pos = (d97.left, d97.top) # assert m1 has been inserted vertically - one node pushed down, NO nodes pushed right were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertEqual( 5, self.overlap_remover.GetStats()["total_overlaps_found"]) self.assertTrue(self._ensureXorder("D25", "D97", "D98")) self.assertTrue(self._ensureXorder("m1", "D97", "D98")) self.assertTrue(self._ensureYorder("D25", "m1", "D13")) self.assertTrue(self._ensureYorder("D25", "m1", "D13")) self.assertEqual(oldD97pos, (d97.left, d97.top)) # ensure D97 hasn't been pushed def test3_5InsertedVerticallyTwoPushedDown(self): self._LoadScenario3() # move m1 to the left node = self.g.FindNodeById("m1") node.left, node.top = (6, 4) d97 = self.g.FindNodeById("D97") oldD97pos = (d97.left, d97.top) # assert m1 has been inserted vertically - two pushed down were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertEqual( 2, self.overlap_remover.GetStats()["total_overlaps_found"]) self.assertTrue(self._ensureYorder("m1", "D25", "D13")) self.assertTrue(self._ensureXorder("m1", "D97", "D98")) self.assertTrue(self._ensureXorder("D25", "D97", "D98")) self.assertTrue(self._ensureXorder("D13", "D97", "D98")) self.assertEqual(oldD97pos, (d97.left, d97.top)) # ensure D97 hasn't been pushed def _LoadScenario3a(self): self.g.LoadGraphFromStrings(TEST_GRAPH3A) def test3A_1PushedLeft(self): self._LoadScenario3a() node = self.g.FindNodeById("m1") node.left, node.top = (246, 9) # move m1 to the right, should be pushed back to the left were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertEqual( 1, self.overlap_remover.GetStats()["total_overlaps_found"]) self.assertTrue(self._ensureXorder("D25", "m1", "D97")) self.assertTrue(self._ensureXorder("D13", "m1", "D97")) self.assertTrue(self._ensureYorder("D25", "D13")) self.assertTrue(self._ensureYorder("m1", "D13")) self.assertTrue(self._ensureYorder("m1", "D98")) self.assertTrue(self._ensureYorder("D97", "D98")) self.assertFalse(self._ensureYorder("D25", "m1")) # don't want this self.assertFalse(self._ensureYorder("D97", "m1")) # don't want this def test3A_2PushedLeftD97DoesntMove(self): self._LoadScenario3a() d97 = self.g.FindNodeById("D97") oldD97pos = (d97.left, d97.top) node = self.g.FindNodeById("m1") node.left, node.top = (261, 104) # move m1 to the right, should be pushed back to the left. D97 shouldn't move! were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertTrue(self._ensureXorder("D25", "m1", "D97")) self.assertTrue(self._ensureXorder("D25", "m1", "D98")) self.assertTrue(self._ensureXorderLefts("D25", "m1", "D98", "D97")) self.assertEqual(oldD97pos, (d97.left, d97.top)) # ensure D97 hasn't been pushed def test3A_3PushedLeftNotFlyingUpY(self): self._LoadScenario3a() node = self.g.FindNodeById("m1") node.left, node.top = (216, 164) # move m1 to the right, should be pushed back to the left. Not flown up Y. # note that the top of m1 is > top of D98 to trigger this test. were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertEqual( 1, self.overlap_remover.GetStats()["total_overlaps_found"]) self.assertTrue(self._ensureXorder("D25", "m1", "D97")) self.assertTrue(self._ensureXorder("D25", "m1", "D98")) self.assertTrue(self._ensureYorder("D25", "m1")) self.assertFalse(self._ensureYorder("m1", "D98")) # don't want this def _LoadScenario4(self): self.g.LoadGraphFromStrings(TEST_GRAPH4) def test4_1InsertedTwoPushedRightTwoPushedDown(self): self._LoadScenario4() # move m1 to the left node = self.g.FindNodeById("m1") node.left, node.top = (136, 99) d97 = self.g.FindNodeById("D97") d98 = self.g.FindNodeById("D98") d50 = self.g.FindNodeById("D50") d51 = self.g.FindNodeById("D51") oldD97pos = (d97.left, d97.top) oldD98pos = (d98.left, d98.top) oldD50pos = (d50.left, d50.top) oldD51pos = (d51.left, d51.top) # assert m1 has been inserted - two pushed right, two pushed down were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertEqual( 5, self.overlap_remover.GetStats()["total_overlaps_found"]) self.assertTrue(self._ensureXorder("D13", "m1", "D97", "D98")) self.assertTrue(self._ensureXorder("D25", "D97", "D98")) self.assertTrue(self._ensureYorder("D25", "D13", "D50", "D51")) self.assertTrue(self._ensureYorder("D25", "m1", "D50", "D51")) self.assertTrue(self._ensureYorder("D97", "D50", "D51")) self.assertTrue(self._ensureYorder("D98", "D50", "D51")) self.assertTrue(self._ensureXorder("D13", "D50")) self.assertTrue(self._ensureXorder("D13", "D51")) self.assertNotEqual(oldD97pos, (d97.left, d97.top)) # ensure D97 HAS been pushed self.assertNotEqual(oldD98pos, (d98.left, d98.top)) # ensure D98 HAS been pushed self.assertNotEqual(oldD50pos, (d50.left, d50.top)) # ensure D50 HAS been pushed self.assertNotEqual(oldD51pos, (d51.left, d51.top)) # ensure D51 HAS been pushed def test4_2InsertedTwoNotPushedRightThreePushedDown(self): self._LoadScenario4() # move m1 to the left node = self.g.FindNodeById("m1") node.left, node.top = (101, 99) d97 = self.g.FindNodeById("D97") d98 = self.g.FindNodeById("D98") d50 = self.g.FindNodeById("D50") d51 = self.g.FindNodeById("D51") d13 = self.g.FindNodeById("D13") oldD97pos = (d97.left, d97.top) oldD98pos = (d98.left, d98.top) oldD50pos = (d50.left, d50.top) oldD51pos = (d51.left, d51.top) oldD13pos = (d13.left, d13.top) # assert m1 has been inserted - two NOT pushed right, two pushed down, and extra D13 pushed down # because m1 overlaps/attacks D13 (and there is room for D13 to move downwards I guess) # # An earlier version of this test allowed D97 and D98 to be pushed to the right. I changed this. were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertFalse(self._ensureXorder( "D13", "m1", "D97", "D98")) # not true anymore, m1 not pushed to the right so much self.assertFalse(self._ensureYorder("D25", "D13", "D50", "D51")) # not true anymore, self.assertTrue(self._ensureXorder("D25", "D97", "D98")) self.assertTrue(self._ensureXorder("D13", "D97", "D98")) self.assertTrue(self._ensureXorder("D13", "D50")) self.assertTrue(self._ensureXorder("D13", "D51")) self.assertTrue(self._ensureYorder("D25", "m1", "D13", "D51")) self.assertTrue(self._ensureYorder("D25", "m1", "D50", "D51")) self.assertTrue(self._ensureYorder("D97", "D50", "D51")) self.assertTrue(self._ensureYorder("D98", "D50", "D51")) self.assertTrue( self._ensureYorderBottoms("D25", "D97", "m1", "D13", "D50", "D51")) self.assertEqual(oldD97pos, (d97.left, d97.top)) # ensure D97 HAS NOT been pushed self.assertEqual(oldD98pos, (d98.left, d98.top)) # ensure D98 HAS NOT been pushed self.assertNotEqual(oldD50pos, (d50.left, d50.top)) # ensure D50 HAS been pushed self.assertNotEqual(oldD51pos, (d51.left, d51.top)) # ensure D51 HAS been pushed self.assertNotEqual(oldD13pos, (d13.left, d13.top)) # ensure D13 HAS been pushed def _LoadScenario6_linecrossing(self): self.g.LoadGraphFromStrings(TEST_GRAPH6) @unittest.skipIf( not LINE_NODE_OVERLAP_REMOVAL_ENABLED, "line node overlap removal - abandoned this difficult idea", ) def test6_1LineCrossingNotNeeded(self): self._LoadScenario6_linecrossing() # move m1 to the left node = self.g.FindNodeById("m1") node.left, node.top = (49, 48) # assert m1 has been repulsed and snuggeled were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertEqual( 1, self.overlap_remover.GetStats()["total_overlaps_found"]) self.assertTrue(self._ensureXorder("A", "B")) self.assertTrue(self._ensureXorder("A", "m1")) self.assertTrue(self._ensureYorder("A", "C")) self.assertTrue(self._ensureYorder("B", "m1", "C")) self.assertFalse( self._ensureYorder("A", "m1", "C") ) # don't want this otherwise the line from A to C would be crossed @unittest.skipIf( not LINE_NODE_OVERLAP_REMOVAL_ENABLED, "line node overlap removal - abandoned this difficult idea", ) def test6_2LineCrossingAvoided(self): self._LoadScenario6_linecrossing() # move m1 to the left node = self.g.FindNodeById("m1") # node.left, node.top = (9, 103) # A is to the left of A node.left, node.top = ( 24, 98) # m1 is to the left of A - a bit easier to solve # assert m1 has been repulsed and snuggled, and line not crossed - same results as ABOVE were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertEqual( 1, self.overlap_remover.GetStats()["total_overlaps_found"]) self.assertTrue(self._ensureXorder("A", "m1")) # ensure m1 not crossing any lines line_start_point = self.g.FindNodeById("A").centre_point line_end_point = self.g.FindNodeById("C").centre_point crossings = node.CalcLineIntersectionPoints(line_start_point, line_end_point) self.assertEqual(0, len(crossings)) @unittest.skipIf( not LINE_NODE_OVERLAP_REMOVAL_ENABLED, "line node overlap removal - abandoned this difficult idea", ) def test6_3LineCrossingAvoidedGoSnug(self): self._LoadScenario6_linecrossing() # move m1 to down and left, crossing the line node = self.g.FindNodeById("m1") node.left, node.top = (79, 163) # assert m1 has been repulsed up and to the right, snuggled, and line not crossed were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertEqual( 1, self.overlap_remover.GetStats()["total_overlaps_found"]) self.assertTrue(self._ensureXorder("A", "B")) self.assertTrue(self._ensureXorder("A", "m1")) self.assertFalse(self._ensureXorder("C", "m1")) # don't want this self.assertTrue(self._ensureYorder("m1", "C")) self.assertTrue(self._ensureYorder("A", "C")) def _LoadScenario7(self): self.g.LoadGraphFromStrings(TEST_GRAPH7) def test7_1DontJumpTooFarY(self): self._LoadScenario7() # move m1 to the left node = self.g.FindNodeById("m1") node.left, node.top = (240, 15) # assert m1 has been pushed to the right. don't see why edges should make any difference # initially found m1 was being pushed way too far down in the Y direction! were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertEqual( 1, self.overlap_remover.GetStats()["total_overlaps_found"]) self.assertTrue(self._ensureXorder("A", "m1")) self.assertTrue(self._ensureXorder("A", "c")) self.assertTrue(self._ensureYorder("m1", "c")) self.assertFalse(self._ensureYorder( "A", "m1")) # don't want this huge Y jump def test7_2DontJumpTooFarY(self): self._LoadScenario7() # move m1 to the left node = self.g.FindNodeById("m1") node.left, node.top = (235, 120) # assert m1 has been pushed to the right and down snugly # not pushed way too far down in the Y direction! were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertEqual( 1, self.overlap_remover.GetStats()["total_overlaps_found"]) self.assertTrue(self._ensureXorder("A", "m1")) self.assertTrue(self._ensureXorder("A", "c")) self.assertTrue(self._ensureYorder( "c", "m1")) # ensure m1 is snuggled below c self.assertFalse(self._ensureYorder( "A", "m1")) # don't want this huge Y jump def _LoadScenario8(self): self.g.LoadGraphFromStrings(TEST_GRAPH8) def test8_1JumpUpAndSnuggleB1PushedOk(self): self._LoadScenario8() b1 = self.g.FindNodeById("B1") a = self.g.FindNodeById("A") oldB1pos = (b1.left, b1.top) oldApos = (a.left, a.top) # move m1 to the left node = self.g.FindNodeById("m1") node.left, node.top = (64, 75) # assert m1 has been pushed up and to the right. Ok for B1 to be pushed a little left were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertTrue(self._ensureXorder("B1", "m1", "B2")) self.assertTrue(self._ensureYorder("B1", "A")) self.assertTrue(self._ensureYorder("B2", "A")) self.assertEqual(oldApos, (a.left, a.top)) # ensure A HAS NOT been pushed self.assertNotEqual(oldB1pos, (b1.left, b1.top)) # ok if B1 HAS been pushed def test8_2JumpUpAndSnuggle(self): self._LoadScenario8() b1 = self.g.FindNodeById("B1") a = self.g.FindNodeById("A") oldB1pos = (b1.left, b1.top) oldApos = (a.left, a.top) # move m1 to the left node = self.g.FindNodeById("m1") node.left, node.top = (34, 75) # assert m1 has been pushed up and to the right. We used to have it so # moving y up was not an option for m1 so A got pushed down instead. were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertTrue(self._ensureXorder("B1", "m1", "B2")) self.assertTrue(self._ensureYorder("B1", "A")) self.assertTrue(self._ensureYorder("B2", "A")) self.assertEqual(oldApos, (a.left, a.top)) # ensure A HAS NOT been pushed self.assertEqual(oldB1pos, (b1.left, b1.top)) # ensure B1 HAS NOT been pushed def test8_3JumpUpAndSnuggle(self): self._LoadScenario8() b2 = self.g.FindNodeById("B2") a = self.g.FindNodeById("A") oldB2pos = (b2.left, b2.top) oldApos = (a.left, a.top) # move m1 to the left node = self.g.FindNodeById("m1") node.left, node.top = (114, 75) # assert m1 has been pushed up and to the left. We used to have it so # moving y up was not an option for m1 so A got pushed down instead. were_all_overlaps_removed = self.overlap_remover.RemoveOverlaps() self.assertTrue(were_all_overlaps_removed) self.assertTrue(self._ensureXorder("B1", "m1", "B2")) self.assertTrue(self._ensureYorder("B1", "A")) self.assertTrue(self._ensureYorder("B2", "A")) self.assertEqual(oldApos, (a.left, a.top)) # ensure A HAS NOT been pushed self.assertEqual(oldB2pos, (b2.left, b2.top)) # ensure B2 HAS NOT been pushed
def __init__(self, x_dim: float, y_dim: float): super().__init__(x_dim, y_dim) self.graph = Graph(x_dim, y_dim) self.people = None
def test_2_generalisation_sort_order(self): # C --|> B --|> A g = Graph() c = GraphNode("C", 0, 0, 200, 200) b = GraphNode("B", 0, 0, 200, 200) # parent of C a = GraphNode("A", 0, 0, 200, 200) # parent of B # add out of order g.AddNode(b) g.AddNode(c) g.AddNode(a) g.AddEdge(c, b)["uml_edge_type"] = "generalisation" g.AddEdge(b, a)["uml_edge_type"] = "generalisation" nodelist_normal = [node.id for node in g.nodes] nodelist_sorted = [ node.id for node, annotation in g.nodes_sorted_by_generalisation ] nodelist_sorted_expected = ["A", "B", "C"] # print "nodelist_normal", nodelist_normal # print "nodelist_sorted_expected", nodelist_sorted_expected # print "nodelist_sorted", nodelist_sorted assert nodelist_sorted_expected == nodelist_sorted # D --|> C --|> B --|> A d = GraphNode("D", 0, 0, 200, 200) g.AddNode(d) g.AddEdge(d, c)["uml_edge_type"] = "generalisation" nodelist_sorted = [ node.id for node, annotation in g.nodes_sorted_by_generalisation ] nodelist_sorted_expected = ["A", "B", "C", "D"] assert nodelist_sorted_expected == nodelist_sorted # E node not connected to anything e = GraphNode("E", 0, 0, 200, 200) g.AddNode(e) nodelist_sorted = [ node.id for node, annotation in g.nodes_sorted_by_generalisation ] nodelist_sorted_expected = ["A", "B", "C", "D", "E"] assert nodelist_sorted_expected == nodelist_sorted # D --|> C --|> B --|> A # E # C2 --|> B c2 = GraphNode("C2", 0, 0, 200, 200) g.AddNode(c2) g.AddEdge(c2, b)["uml_edge_type"] = "generalisation" nodelist_sorted = [ node.id for node, annotation in g.nodes_sorted_by_generalisation ] nodelist_sorted_expected = ["A", "B", "C", "C2", "D", "E"] assert nodelist_sorted_expected == nodelist_sorted
def test_1_Basics(self): g = Graph() n1 = GraphNode("A", 0, 0, 200, 200) n2 = GraphNode("B", 0, 0, 200, 200) g.AddEdge(n1, n2) # for node in g.nodes: # print node, "layout info:", (node.layoutPosX, node.layoutPosY) # print g.GraphToString().strip() assert len(g.nodes) == 2 assert len(list(g.nodeSet.keys())) == 2 assert len(g.edges) == 1 g.DeleteNodeById("B") assert len(g.nodes) == 1 assert len(list(g.nodeSet.keys())) == 1 assert len(g.edges) == 0 # Old persistence format - very simple, I call this 0.9 format. filedata = """ {'type':'node', 'id':'c', 'x':230, 'y':174, 'width':60, 'height':120} {'type':'node', 'id':'c1', 'x':130, 'y':174, 'width':60, 'height':120} {'type':'edge', 'id':'c_to_c1', 'source':'c', 'target':'c1'} """ g.Clear() assert len(g.nodes) == 0 assert g.GraphToString().strip() == "" g.LoadGraphFromStrings(filedata) # for node in g.nodes: # print node, "layout info:", (node.layoutPosX, node.layoutPosY) # assert g.GraphToString().strip() == filedata.strip(), g.GraphToString().strip() # no longer true since upgrades to persistence format will translate the incoming text # Line intersection tests res = FindLineIntersection((0, 0), (200, 200), (10, 10), (10, 50)) assert res == [10, 10] res = FindLineIntersection((0, 30), (200, 30), (10, 10), (10, 50)) assert res == [10, 30] node = GraphNode("A", 10, 10, 30, 40) assert len(node.lines) == 4 assert (10, 10) in node.lines[0] assert (40, 10) in node.lines[0] assert (40, 10) in node.lines[1] assert (40, 50) in node.lines[1] assert (40, 50) in node.lines[2] assert (10, 50) in node.lines[2] assert (10, 50) in node.lines[3] assert (10, 10) in node.lines[3] res = node.CalcLineIntersectionPoints((0, 0), (200, 200)) assert len(res) == 2 assert (10, 10) in res assert (40, 40) in res res = node.CalcLineIntersectionPoints((20, 0), (20, 1000)) assert len(res) == 2 assert (20, 10) in res assert (20, 50) in res
def test_6_generalisation_sort_order(self): # START AGAIN - more tests, check stranger trees # B,D,F --|> A # G --|> C --|> B # E --|> D g = Graph() a = GraphNode("A", 0, 0, 200, 200) b = GraphNode("B", 0, 0, 200, 200) c = GraphNode("C", 0, 0, 200, 200) d = GraphNode("D", 0, 0, 200, 200) e = GraphNode("E", 0, 0, 200, 200) f = GraphNode("F", 0, 0, 200, 200) h = GraphNode("H", 0, 0, 200, 200) # add out of order g.AddNode(f) g.AddNode(b) g.AddNode(a) g.AddNode(h) g.AddNode(c) g.AddNode(e) g.AddNode(d) g.AddEdge(b, a)["uml_edge_type"] = "generalisation" g.AddEdge(d, a)["uml_edge_type"] = "generalisation" g.AddEdge(f, a)["uml_edge_type"] = "generalisation" g.AddEdge(h, c)["uml_edge_type"] = "generalisation" g.AddEdge(c, b)["uml_edge_type"] = "generalisation" g.AddEdge(e, d)["uml_edge_type"] = "generalisation" nodelist_normal = [node.id for node in g.nodes] nodelist_sorted = [ node.id for node, annotation in g.nodes_sorted_by_generalisation ] nodelist_sorted_expected = ["A", "B", "D", "F", "C", "H", "E"] assert nodelist_sorted_expected == nodelist_sorted nodelist_sorted_annotated = [ (node.id, annotation) for node, annotation in g.nodes_sorted_by_generalisation ] nodelist_sorted_expected_annotated = [ ("A", "root"), ("B", "fc"), ("D", "tab"), ("F", "tab"), ("C", "fc"), ("H", "fc"), ("E", "root"), ] assert nodelist_sorted_expected_annotated == nodelist_sorted_annotated
def test_5_generalisation_sort_order(self): # START AGAIN - more tests, check stranger trees, though the algorithm # is proving pretty smart, prioritising children who have children to the left # B,B1,C,K --|> A # D --|> C g = Graph() a = GraphNode("A", 0, 0, 200, 200) b = GraphNode("B", 0, 0, 200, 200) b1 = GraphNode("B1", 0, 0, 200, 200) c = GraphNode("C", 0, 0, 200, 200) k = GraphNode("K", 0, 0, 200, 200) d = GraphNode("D", 0, 0, 200, 200) # add out of order g.AddNode(b1) g.AddNode(b) g.AddNode(a) g.AddNode(c) g.AddNode(k) g.AddNode(d) g.AddEdge(k, a)["uml_edge_type"] = "generalisation" g.AddEdge(d, c)["uml_edge_type"] = "generalisation" g.AddEdge(c, a)["uml_edge_type"] = "generalisation" g.AddEdge(b1, a)["uml_edge_type"] = "generalisation" g.AddEdge(b, a)["uml_edge_type"] = "generalisation" nodelist_normal = [node.id for node in g.nodes] nodelist_sorted = [ node.id for node, annotation in g.nodes_sorted_by_generalisation ] # print "nodelist_normal", nodelist_normal # print "nodelist_sorted_expected", nodelist_sorted_expected # print "nodelist_sorted", nodelist_sorted assert nodelist_sorted[0] == "A" assert nodelist_sorted[1] == "C" assert nodelist_sorted[-1] == "D" nodelist_sorted_annotated = [ (node.id, annotation) for node, annotation in g.nodes_sorted_by_generalisation ] assert nodelist_sorted_annotated[0] == ("A", "root") assert nodelist_sorted_annotated[1] == ("C", "fc") assert nodelist_sorted_annotated[-1] == ("D", "fc") assert ("K", "tab") in nodelist_sorted_annotated assert ("B", "tab") in nodelist_sorted_annotated assert ("B1", "tab") in nodelist_sorted_annotated
def test_4_generalisation_sort_order(self): # START AGAIN - more tests, ensure children nodes with children themselves, are prioritised # and furthermore, children with the most descendants are prioritised even more. # B,B1 --|> A # C --|> B g = Graph() c = GraphNode("C", 0, 0, 200, 200) b = GraphNode("B", 0, 0, 200, 200) b1 = GraphNode("B1", 0, 0, 200, 200) a = GraphNode("A", 0, 0, 200, 200) c2 = GraphNode("C2", 0, 0, 200, 200) d = GraphNode("D", 0, 0, 200, 200) # add out of order g.AddNode(b1) g.AddNode(b) g.AddNode(a) g.AddNode(c) g.AddNode(c2) g.AddNode(d) g.AddEdge(c2, b1)["uml_edge_type"] = "generalisation" g.AddEdge(d, c)["uml_edge_type"] = "generalisation" g.AddEdge(c, b)["uml_edge_type"] = "generalisation" g.AddEdge(b1, a)["uml_edge_type"] = "generalisation" g.AddEdge(b, a)["uml_edge_type"] = "generalisation" nodelist_normal = [node.id for node in g.nodes] nodelist_sorted = [ node.id for node, annotation in g.nodes_sorted_by_generalisation ] nodelist_sorted_expected = ["A", "B", "B1", "C", "D", "C2"] # print "nodelist_normal", nodelist_normal # print "nodelist_sorted_expected", nodelist_sorted_expected # print "nodelist_sorted", nodelist_sorted assert nodelist_sorted_expected == nodelist_sorted
def test_3_generalisation_sort_order(self): # START AGAIN - more tests, ensure children nodes with children themselves, are prioritised # C2,C --|> B # B,B2 --|> A g = Graph() c = GraphNode("C", 0, 0, 200, 200) c2 = GraphNode("C2", 0, 0, 200, 200) b = GraphNode("B", 0, 0, 200, 200) b2 = GraphNode("B2", 0, 0, 200, 200) a = GraphNode("A", 0, 0, 200, 200) # add out of order g.AddNode(b2) g.AddNode(b) g.AddNode(c) g.AddNode(c2) g.AddNode(a) g.AddEdge(c, b)["uml_edge_type"] = "generalisation" g.AddEdge(c2, b)["uml_edge_type"] = "generalisation" g.AddEdge(b2, a)["uml_edge_type"] = "generalisation" g.AddEdge(b, a)["uml_edge_type"] = "generalisation" nodelist_normal = [node.id for node in g.nodes] nodelist_sorted = [ node.id for node, annotation in g.nodes_sorted_by_generalisation ] nodelist_sorted_expected = ["A", "B", "B2", "C", "C2"] nodelist_sorted_expected2 = ["A", "B", "B2", "C2", "C"] # print "nodelist_normal", nodelist_normal # print "nodelist_sorted_expected", nodelist_sorted_expected # print "nodelist_sorted", nodelist_sorted assert (nodelist_sorted_expected == nodelist_sorted or nodelist_sorted_expected2 == nodelist_sorted)