From 91ae7608a3ad03f397d63dc9374a494dcdad3e1a Mon Sep 17 00:00:00 2001 From: "WQY\\qiong" Date: Fri, 4 Nov 2022 16:30:09 +0800 Subject: [PATCH] Add vertex api and test --- api/__init__.py | 2 + api/s25_vertices.py | 65 +++++++++++++++++++++++++++ script/sql/create/25.vertices.sql | 3 +- test_tjnetwork.py | 73 +++++++++++++++++++++++++++++++ tjnetwork.py | 22 +++++++++- 5 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 api/s25_vertices.py diff --git a/api/__init__.py b/api/__init__.py index 1080f1b..9a3d849 100644 --- a/api/__init__.py +++ b/api/__init__.py @@ -71,6 +71,8 @@ from .s23_options import get_option_schema, get_option, set_option from .s24_coordinates import get_node_coord +from .s25_vertices import get_vertex_schema, get_vertex, set_vertex, add_vertex, delete_vertex + from .s26_labels import get_label_schema, get_label, set_label, add_label, delete_label from .s27_backdrop import get_backdrop_schema, get_backdrop, set_backdrop diff --git a/api/s25_vertices.py b/api/s25_vertices.py new file mode 100644 index 0000000..c668af0 --- /dev/null +++ b/api/s25_vertices.py @@ -0,0 +1,65 @@ +from .operation import * + + +def get_vertex_schema(name: str) -> dict[str, dict[str, Any]]: + return { 'link' : {'type': 'str' , 'optional': False , 'readonly': True }, + 'coords' : {'type': 'list' , 'optional': False , 'readonly': False, + 'element': { 'x' : {'type': 'float' , 'optional': False , 'readonly': False }, + 'y' : {'type': 'float' , 'optional': False , 'readonly': False } }}} + + +def get_vertex(name: str, link: str) -> dict[str, Any]: + cus = read_all(name, f"select * from vertices where link = '{link}' order by _order") + cs = [] + for r in cus: + cs.append({ 'x': float(r['x']), 'y': float(r['y']) }) + return { 'link': link, 'coords': cs } + + +def set_vertex_cache(name: str, cs: ChangeSet) -> SqlChangeSet: + link = cs.operations[0]['link'] + + old = get_vertex(name, link) + new = { 'link': link, 'coords': [] } + + f_link = f"'{link}'" + + # TODO: transaction ? + redo_sql = f"delete from vertices where link = {f_link};" + for xy in cs.operations[0]['coords']: + x, y = float(xy['x']), float(xy['y']) + f_x, f_y = x, y + redo_sql += f"\ninsert into vertices (link, x, y) values ({f_link}, {f_x}, {f_y});" + new['coords'].append({ 'x': x, 'y': y }) + + undo_sql = f"delete from vertices where link = {f_link};" + for xy in old['coords']: + f_x, f_y = xy['x'], xy['y'] + undo_sql += f"\ninsert into vertices (link, x, y) values ({f_link}, {f_x}, {f_y});" + + redo_cs = { 'type': 'vertex' } | new + undo_cs = { 'type': 'vertex' } | old + + return SqlChangeSet(redo_sql, undo_sql, redo_cs, undo_cs) + + +def set_vertex(name: str, cs: ChangeSet) -> ChangeSet: + result = set_vertex_cache(name, cs) + result.redo_cs |= g_update_prefix + result.undo_cs |= g_update_prefix + return execute_command(name, result) + + +def add_vertex(name: str, cs: ChangeSet) -> ChangeSet: + result = set_vertex_cache(name, cs) + result.redo_cs |= g_add_prefix + result.undo_cs |= g_delete_prefix + return execute_command(name, result) + + +def delete_vertex(name: str, cs: ChangeSet) -> ChangeSet: + cs.operations[0]['coords'] = [] + result = set_vertex_cache(name, cs) + result.redo_cs |= g_delete_prefix + result.undo_cs |= g_add_prefix + return execute_command(name, result) diff --git a/script/sql/create/25.vertices.sql b/script/sql/create/25.vertices.sql index c4e2ec0..4e924f3 100644 --- a/script/sql/create/25.vertices.sql +++ b/script/sql/create/25.vertices.sql @@ -2,7 +2,8 @@ create table vertices ( - link varchar(32) references _link(id) not null + _order serial primary key +, link varchar(32) references _link(id) not null , x numeric not null , y numeric not null ); diff --git a/test_tjnetwork.py b/test_tjnetwork.py index 70f0b1b..bc84873 100644 --- a/test_tjnetwork.py +++ b/test_tjnetwork.py @@ -2488,6 +2488,79 @@ class TestApi: self.leave(p) + # 25 vertex + + + def test_vertex(self): + p = 'test_vertex' + self.enter(p) + + add_junction(p, ChangeSet({'id': 'j1', 'x': 0.0, 'y': 10.0, 'elevation': 20.0})) + add_junction(p, ChangeSet({'id': 'j2', 'x': 0.0, 'y': 10.0, 'elevation': 20.0})) + add_pipe(p, ChangeSet({'id': 'p0', 'node1': 'j1', 'node2': 'j2', 'length': 100.0, 'diameter': 10.0, 'roughness': 0.1, 'minor_loss': 0.5, 'status': PIPE_STATUS_OPEN })) + + v = get_vertex(p, 'p0') + assert v['link'] == 'p0' + assert v['coords'] == [] + + set_vertex(p, ChangeSet({'link' : 'p0', 'coords': [{'x': 1.0, 'y': 2.0}, {'x': 2.0, 'y': 1.0}]})) + + v = get_vertex(p, 'p0') + xys = v['coords'] + assert len(xys) == 2 + assert xys[0]['x'] == 1.0 + assert xys[0]['y'] == 2.0 + assert xys[1]['x'] == 2.0 + assert xys[1]['y'] == 1.0 + + set_vertex(p, ChangeSet({'link' : 'p0', 'coords': []})) + + v = get_vertex(p, 'p0') + assert v['link'] == 'p0' + assert v['coords'] == [] + + self.leave(p) + + + def test_vertex_op(self): + p = 'test_vertex_op' + self.enter(p) + + add_junction(p, ChangeSet({'id': 'j1', 'x': 0.0, 'y': 10.0, 'elevation': 20.0})) + add_junction(p, ChangeSet({'id': 'j2', 'x': 0.0, 'y': 10.0, 'elevation': 20.0})) + add_pipe(p, ChangeSet({'id': 'p0', 'node1': 'j1', 'node2': 'j2', 'length': 100.0, 'diameter': 10.0, 'roughness': 0.1, 'minor_loss': 0.5, 'status': PIPE_STATUS_OPEN })) + + cs = set_vertex(p, ChangeSet({'link' : 'p0', 'coords': [{'x': 1.0, 'y': 2.0}, {'x': 2.0, 'y': 1.0}]})).operations[0] + assert cs['operation'] == API_UPDATE + assert cs['type'] == 'vertex' + assert cs['link'] == 'p0' + xys = cs['coords'] + assert len(xys) == 2 + assert xys[0]['x'] == 1.0 + assert xys[0]['y'] == 2.0 + assert xys[1]['x'] == 2.0 + assert xys[1]['y'] == 1.0 + + cs = execute_undo(p).operations[0] + assert cs['operation'] == API_UPDATE + assert cs['type'] == 'vertex' + assert cs['link'] == 'p0' + assert cs['coords'] == [] + + cs = execute_redo(p).operations[0] + assert cs['operation'] == API_UPDATE + assert cs['type'] == 'vertex' + assert cs['link'] == 'p0' + xys = cs['coords'] + assert len(xys) == 2 + assert xys[0]['x'] == 1.0 + assert xys[0]['y'] == 2.0 + assert xys[1]['x'] == 2.0 + assert xys[1]['y'] == 1.0 + + self.leave(p) + + # 26 label diff --git a/tjnetwork.py b/tjnetwork.py index a63e61c..0d9a391 100644 --- a/tjnetwork.py +++ b/tjnetwork.py @@ -533,7 +533,27 @@ def get_node_coord(name: str, node_id: str) -> dict[str, float] | None: ############################################################ -# backdrop 27.[BACKDROP] +# vertex 25.[VERTICES] +############################################################ + +def get_vertex_schema(name: str) -> dict[str, dict[str, Any]]: + return api.get_vertex_schema(name) + +def get_vertex(name: str, link: str) -> dict[str, Any]: + return api.get_vertex(name, link) + +def set_vertex(name: str, cs: ChangeSet) -> ChangeSet: + return api.set_vertex(name, cs) + +def add_vertex(name: str, cs: ChangeSet) -> ChangeSet: + return api.add_vertex(name, cs) + +def delete_vertex(name: str, cs: ChangeSet) -> ChangeSet: + return api.delete_vertex(name, cs) + + +############################################################ +# label 26.[LABELS] ############################################################ def get_label_schema(name: str) -> dict[str, dict[str, Any]]: