finsish BuildOper

This commit is contained in:
yyc12345 2023-02-22 21:49:31 +08:00
parent 979183e9fc
commit 54d31ed6bd
3 changed files with 199 additions and 52 deletions

View File

@ -8,22 +8,19 @@ class IntermediateTreeNode(object):
self.m_LocatedPos: int = DecoratorData.TreeLayout.NO_START_POS_OF_REF_LAYER
self.m_Collection: collections.deque[int] = collections.deque()
class BlocksFactory(object):
def __init__(self, db: sqlite3.Connection, graph: int):
# assign members
self.m_GraphCKID: int = graph
self.m_Db: sqlite3.Connection = db
self.__Cursor: sqlite3.Cursor = db.cursor()
class IntermediateOperDownwardSearch(object):
def __init__(self):
self.m_Collection: collections.deque[int] = collections.deque()
class BlocksFactory(object):
def __init__(self, db: sqlite3.Connection, graph: DecoratorData.GraphResult):
# assign members
self.m_Graph: DecoratorData.GraphResult = graph
self.m_Db: sqlite3.Connection = db
self.m_BBDict: dict[int, DecoratorData.BBTreeNode] = {}
self.m_OperDict: dict[int, DecoratorData.OperTreeNode] = {}
self.__AllBB: set[int] = set()
self.__AllOper: set[int] = set()
self.m_PassiveOperLayer: DecoratorData.TreeLayout = DecoratorData.TreeLayout()
self.m_ActiveBBLayer: DecoratorData.TreeLayout = DecoratorData.TreeLayout()
self.m_PassiveBBLayer: DecoratorData.TreeLayout = DecoratorData.TreeLayout()
# fill data first
self.__FillDataFromDb()
@ -37,25 +34,146 @@ class BlocksFactory(object):
return next(iter(vals))
def __FillDataFromDb(self):
self.__Cursor.execute('SELECT * FROM [script_behavior] WHERE parent == ?', (self.m_GraphCKID, ))
for sqldata in self.__Cursor.fetchall():
cursor: sqlite3.Cursor = self.m_Db.cursor()
cursor.execute('SELECT * FROM [script_behavior] WHERE parent == ?', (self.m_Graph.m_GraphCKID, ))
for sqldata in cursor.fetchall():
payload: DecoratorData.BBDataPayload = DecoratorData.BBDataPayload(sqldata)
self.m_BBDict[payload.m_CKID] = DecoratorData.BBTreeNode(payload)
self.m_Graph.m_BlockDict[payload.m_CKID] = DecoratorData.BBTreeNode(payload)
self.__AllBB.add(payload.m_CKID)
self.__Cursor.execute('SELECT * FROM [script_pOper] WHERE parent == ?', (self.m_GraphCKID, ))
for sqldata in self.__Cursor.fetchall():
cursor.execute('SELECT * FROM [script_pOper] WHERE parent == ?', (self.m_Graph.m_GraphCKID, ))
for sqldata in cursor.fetchall():
payload: DecoratorData.OperDataPayload = DecoratorData.OperDataPayload(sqldata)
self.m_OperDict[payload.m_CKID] = DecoratorData.OperTreeNode(payload)
self.m_Graph.m_BlockDict[payload.m_CKID] = DecoratorData.OperTreeNode(payload)
self.__AllOper.add(payload.m_CKID)
def __FindBBBottomOperRoot(self, start_pOut: int) -> tuple[int]:
pass
cursor.close()
def __BuildOper(self, tree: DecoratorData.TreeLayout, start_oper: int):
pass
def __FindBBBottomOperRoot(self, start_pOut: tuple[int]) -> tuple[int]:
cursor: sqlite3.Cursor = self.m_Db.cursor()
cursor_outget: sqlite3.Cursor = self.m_Db.cursor()
def __BuildBB(self, tree: DecoratorData.TreeLayout, start_bb: int):
# prepare something
stack: collections.deque[int] = collections.deque()
procedOut: set[int] = set()
result: set[int] = set()
# prepare start symbol
stack.extend(start_pOut)
# analyze
while len(stack) != 0:
# peek again
pout: int = stack.pop()
# search this pOut in pLink
cursor.execute('SELECT [output], [output_obj], [output_type], [output_is_bb] FROM [script_pLink] WHERE ([input] == ? AND NOT (([output_type] == ? OR [output_type] == ?) AND [output_is_bb] == ?) AND [parent] == ?);',
(pout,
DecoratorConst.Export_pLink_InputOutputType.PIN, DecoratorConst.Export_pLink_InputOutputType.PTARGET, DecoratorConst.Export_Boolean.TRUE, # filter all BB's pIn
self.m_Graph.m_GraphCKID)
)
# read datas
for (output, output_obj, output_type, output_is_bb, ) in cursor.fetchall():
# check dup
if output in procedOut:
continue
procedOut.add(output)
if output_type == DecoratorConst.Export_pLink_InputOutputType.PIN and output_is_bb == DecoratorConst.Export_Boolean.FALSE:
# this is a oper. find its pOut and add into stack
cursor_outget.execute('SELECT [thisobj] FROM [script_pOut] WHERE [parent] == ?;',
(output_obj, )
)
for (thisobj, ) in cursor_outget.fetchall():
stack.append(thisobj)
else:
# this oper point to non-pIn, should be add into result
result.add(output_obj)
# free cursor and return
cursor.close()
cursor_outget.close()
return tuple(i for i in result)
def __BuildOper(self, tree: DecoratorData.TreeLayout[DecoratorData.OperTreeNode], start_oper: int):
# prepare stack and start condition
stack: collections.deque[IntermediateTreeNode] = collections.deque()
# check whether this BB has been processed
if start_oper not in self.__AllOper:
return
self.__AllOper.remove(start_oper)
# create cursor
cursor: sqlite3.Cursor = self.m_Db.cursor()
# create new layer and insert it
tree.NewLayer(DecoratorData.TreeLayout.NO_REFERENCE_LAYER, DecoratorData.TreeLayout.NO_START_POS_OF_REF_LAYER)
tree.NewItem(self.m_Graph.m_BlockDict[start_oper])
# prepare stack data
start_oper_data: IntermediateTreeNode = IntermediateTreeNode()
start_oper_data.m_LoactedLayer = tree.GetCurrentLayerIndex()
start_oper_data.m_LocatedPos = tree.GetCurrentItemIndex()
cursor.execute("SELECT [input_obj] FROM [script_pLink] WHERE ([output_obj] == ? AND [output_type] == ? AND [input_type] == ? AND [input_is_bb] == ? AND [parent] = ?);",
(start_oper, DecoratorConst.Export_pLink_InputOutputType.PIN, # order pOper's pIn
DecoratorConst.Export_pLink_InputOutputType.POUT, DecoratorConst.Export_Boolean.FALSE, # order pOper's pOut
self.m_Graph.m_GraphCKID, )
)
for (input_obj, ) in cursor.fetchall():
start_oper_data.m_Collection.append(input_obj)
stack.append(start_oper_data)
# start analyze
while len(stack) != 0:
# pick stack and decide whether pop this
stack_entry: IntermediateTreeNode = stack[-1]
if len(stack_entry.m_Collection) == 0:
stack.pop()
continue
# pick a new Oper from collection.
# check whether it need process
oper_id: int = stack_entry.m_Collection[-1]
if oper_id not in self.__AllOper:
stack_entry.m_Collection.pop()
continue
self.__AllOper.remove(oper_id)
# get corresponding tree node
tree_node: DecoratorData.BBTreeNode = self.m_Graph.m_BlockDict[oper_id]
# start proc Oper
# create new stack entry
oper_data: IntermediateTreeNode = IntermediateTreeNode()
# push tree node into tree layout and get corresponding index.
# create new layer according to whether first visit
if stack_entry.m_FirstVisit:
tree.NewItem(tree_node)
oper_data.m_LoactedLayer = stack_entry.m_LoactedLayer
oper_data.m_LocatedPos = stack_entry.m_LocatedPos + 1
# reset first visit
stack_entry.m_FirstVisit = False
else:
tree.NewLayer(stack_entry.m_LoactedLayer, stack_entry.m_LocatedPos)
tree.NewItem(tree_node)
oper_data.m_LoactedLayer = tree.GetCurrentLayerIndex()
oper_data.m_LocatedPos = tree.GetCurrentItemIndex()
# query and fill stack entry data
cursor.execute("SELECT [input_obj] FROM [script_pLink] WHERE ([output_obj] == ? AND [output_type] == ? AND [input_type] == ? AND [input_is_bb] == ? AND [parent] = ?);",
(oper_id, DecoratorConst.Export_pLink_InputOutputType.PIN, # order pOper's pIn
DecoratorConst.Export_pLink_InputOutputType.POUT, DecoratorConst.Export_Boolean.FALSE, # order pOper's pOut
self.m_Graph.m_GraphCKID, )
)
for (output_obj, ) in cursor.fetchall():
oper_data.m_Collection.append(output_obj)
stack.append(oper_data)
cursor.close()
def __BuildBB(self, tree: DecoratorData.TreeLayout[DecoratorData.BBTreeNode], start_bb: int):
# prepare stack and start condition
stack: collections.deque[IntermediateTreeNode] = collections.deque()
@ -64,18 +182,21 @@ class BlocksFactory(object):
return
self.__AllBB.remove(start_bb)
# create cursor
cursor: sqlite3.Cursor = self.m_Db.cursor()
# create new layer and insert it
tree.NewLayer(DecoratorData.TreeLayout.NO_REFERENCE_LAYER, DecoratorData.TreeLayout.NO_START_POS_OF_REF_LAYER)
tree.NewItem(self.m_BBDict[start_bb])
tree.NewItem(self.m_Graph.m_BlockDict[start_bb])
# prepare stack data
start_bb_data: IntermediateTreeNode = IntermediateTreeNode()
start_bb_data.m_LoactedLayer = tree.GetCurrentLayerIndex()
start_bb_data.m_LocatedPos = tree.GetCurrentItemIndex()
self.__Cursor.execute("SELECT [output_obj] FROM [script_bLink] WHERE ([input_obj] == ? AND [input_type] == ? AND [belong_to] = ?) ORDER BY [input_index] ASC;",
(start_bb, DecoratorConst.Database_bLink_InputOutputType.OUTPUT, self.m_GraphCKID, )
cursor.execute("SELECT [output_obj] FROM [script_bLink] WHERE ([input_obj] == ? AND [input_type] == ? AND [parent] = ?) ORDER BY [input_index] ASC;",
(start_bb, DecoratorConst.Export_bLink_InputOutputType.OUTPUT, self.m_Graph.m_GraphCKID, )
)
for (output_obj, ) in self.__Cursor.fetchall():
for (output_obj, ) in cursor.fetchall():
start_bb_data.m_Collection.append(output_obj)
stack.append(start_bb_data)
@ -96,7 +217,7 @@ class BlocksFactory(object):
self.__AllBB.remove(bb_id)
# get corresponding tree node
tree_node = self.m_BBDict[bb_id]
tree_node: DecoratorData.BBTreeNode = self.m_Graph.m_BlockDict[bb_id]
# start proc BB
# create new stack entry
@ -117,25 +238,33 @@ class BlocksFactory(object):
bb_data.m_LoactedLayer = tree.GetCurrentLayerIndex()
bb_data.m_LocatedPos = tree.GetCurrentItemIndex()
# query and fill stack entry data
self.__Cursor.execute("SELECT [output_obj] FROM [script_bLink] WHERE ([input_obj] == ? AND [input_type] == ? AND [belong_to] = ?) ORDER BY [input_index] ASC;",
(bb_id, DecoratorConst.Database_bLink_InputOutputType.OUTPUT, self.m_GraphCKID, )
cursor.execute("SELECT [output_obj] FROM [script_bLink] WHERE ([input_obj] == ? AND [input_type] == ? AND [belong_to] = ?) ORDER BY [input_index] ASC;",
(bb_id, DecoratorConst.Export_bLink_InputOutputType.OUTPUT, self.m_Graph.m_GraphCKID, )
)
for (output_obj, ) in self.__Cursor.fetchall():
for (output_obj, ) in cursor.fetchall():
bb_data.m_Collection.append(output_obj)
stack.append(bb_data)
# todo: executing oper finder for current bb
cursor.close()
def __ProcActiveBB(self):
self.__Cursor.execute("SELECT [output_obj] FROM [script_bLink] WHERE ([input_obj] == ? AND [input_type] == ? AND [belong_to] = ?) ORDER BY [input_index] ASC;",
(self.m_GraphCKID, DecoratorConst.Database_bLink_InputOutputType.INPUT, self.m_GraphCKID, )
cursor: sqlite3.Cursor = self.m_Db.cursor()
cursor.execute("SELECT [output_obj] FROM [script_bLink] WHERE ([input_obj] == ? AND [input_type] == ? AND [belong_to] = ?) ORDER BY [input_index] ASC;",
(self.m_Graph.m_GraphCKID, DecoratorConst.Export_bLink_InputOutputType.INPUT, self.m_Graph.m_GraphCKID, )
)
for (output_obj, ) in self.__Cursor.fetchall():
self.__BuildBB(self.m_ActiveBBLayer, output_obj)
for (output_obj, ) in cursor.fetchall():
self.__BuildBB(self.m_Graph.m_ActiveBB, output_obj)
cursor.close()
def __ProcPassiveBB(self):
cursor: sqlite3.Cursor = self.m_Db.cursor()
while len(self.__AllBB) != 0:
self.__BuildBB(self.m_PassiveBBLayer, self.__GetOneFromSet(self.__AllBB))
cursor.close()
def __ProcPassiveOper(self):
pass

View File

@ -1,9 +1,13 @@
class Database_bLink_InputOutputType(object):
class Export_Boolean(object):
TRUE = 1
FALSE = 0
class Export_bLink_InputOutputType(object):
INPUT = 0
OUTPUT = 1
class Database_pLink_InputOutputType(object):
class Export_pLink_InputOutputType(object):
PIN = 0
POUT = 1
PLOCAL = 2

View File

@ -1,3 +1,14 @@
'''
NOTE:
There are 3 different styles shape in generated graph.
"Block" is stands for the large block, including BB and pOper.
"Cell" is stands for the medium block, including pLocal, pAttr, Shortcut.
"Particle" is stands for the small block, including bIO, pIO, pTarget.
Besides these shapes, the generated graph also include various links.
There are 2 types link. bLink and pLink.
'''
import typing, collections, sqlite3
class Vector(object):
@ -59,7 +70,7 @@ class Margin(object):
self.m_BodySize: Vector = Vector()
self.m_BottomSize: Vector = Vector()
class ICanComputeSize(object):
class ICanManipulate(object):
'''
This class is served for TreeLayout class.
@ -70,23 +81,15 @@ class ICanComputeSize(object):
The reason is that the vertical and horizonal direction between BB and Oper is opposited.
So we use Leaves and Root to give theme an uniformed concept.
'''
def GetPos() -> Vector:
'''
Get current node's start position.
'''
raise NotImplementedError()
def GetSize() -> Vector:
'''
Get current node's size.
'''
raise NotImplementedError()
def SetOrigin():
pass
def ComputeSize() -> Vector:
'''
Get current node's start position
'''
raise NotImplementedError()
TNode = typing.TypeVar('TNode', bound=ICanComputeSize)
TNode = typing.TypeVar('TNode', bound=ICanManipulate)
class TreeLayoutLayer(typing.Generic[TNode]):
def __init__(self, ref_layer: int, start_pos_of_ref_layer: int):
@ -154,11 +157,11 @@ class OperDataPayload(object):
self.m_OpGuid: str = v.op_guid
self.m_Parent: int = v.parent
class OperTreeNode(ICanComputeSize):
class OperTreeNode(ICanManipulate):
def __init__(self, payload: OperDataPayload):
self.m_Payload: OperDataPayload = payload
class BBTreeNode(ICanComputeSize):
class BBTreeNode(ICanManipulate):
def __init__(self, payload: BBDataPayload):
self.m_UpperOper: TreeLayout[OperTreeNode] = TreeLayout()
self.m_LowerOper: TreeLayout[OperTreeNode] = TreeLayout()
@ -167,8 +170,19 @@ class BBTreeNode(ICanComputeSize):
self.m_Payload: BBDataPayload = payload
class GraphWork(ICanComputeSize):
class GraphResult(ICanManipulate):
def __init__(self):
self.m_GraphCKID: int = 0
self.m_BlockDict: dict[int, ICanManipulate] = {}
self.m_CellDict: dict[int, ICanManipulate] = {}
self.m_ParticleDict: dict[int, ICanManipulate] = {}
self.m_bIn: collections.deque = collections.deque()
self.m_bOut: collections.deque = collections.deque()
self.m_pIn: collections.deque = collections.deque()
self.m_pOut: collections.deque = collections.deque()
self.m_PassiveVal: collections.deque = collections.deque()
self.m_PassiveOper: TreeLayout[OperTreeNode] = TreeLayout()
self.m_ActiveBB: TreeLayout[BBTreeNode] = TreeLayout()