2023-02-22 10:23:05 +08:00
import sqlite3 , collections
import DecoratorData , DecoratorConst
2023-02-23 15:50:18 +08:00
class BuildBBEnvironment ( object ) :
def __init__ ( self ,
cursor : sqlite3 . Cursor , tree : DecoratorData . TreeLayout [ DecoratorData . BBTreeNodeWrapper ] ,
depth : int , query_bb : int ) :
self . m_Cursor : sqlite3 . Cursor = cursor
self . m_Tree : DecoratorData . TreeLayout [ DecoratorData . BBTreeNodeWrapper ] = tree
self . m_Depth : int = depth
self . m_QueryBB : int = query_bb
class BuildOperEnvironment ( object ) :
def __init__ ( self ,
cursor : sqlite3 . Cursor , tree : DecoratorData . TreeLayout [ DecoratorData . OperTreeNodeWrapper ] ,
depth : int , query_oper : int ) :
self . m_Cursor : sqlite3 . Cursor = cursor
self . m_Tree : DecoratorData . TreeLayout [ DecoratorData . OperTreeNodeWrapper ] = tree
self . m_Depth : int = depth
self . m_QueryOper : int = query_oper
class FindOperRootEnvironment ( object ) :
def __init__ ( self ,
cursor : sqlite3 . Cursor , walked_oper : set [ int ] ,
depth : int , query_oper : int ) :
self . m_Cursor : sqlite3 . Cursor = cursor
self . m_WalkedOper : set [ int ] = walked_oper
self . m_Depth : int = depth
self . m_QueryOper : int = query_oper
2023-02-22 21:49:31 +08:00
2023-02-21 22:27:38 +08:00
class BlocksFactory ( object ) :
2023-02-22 21:49:31 +08:00
def __init__ ( self , db : sqlite3 . Connection , graph : DecoratorData . GraphResult ) :
2023-02-21 22:27:38 +08:00
# assign members
2023-02-22 21:49:31 +08:00
self . m_Graph : DecoratorData . GraphResult = graph
2023-02-21 22:27:38 +08:00
self . m_Db : sqlite3 . Connection = db
self . __AllBB : set [ int ] = set ( )
self . __AllOper : set [ int ] = set ( )
# fill data first
self . __FillDataFromDb ( )
2023-02-22 10:23:05 +08:00
# proc each data
self . __ProcActiveBB ( )
self . __ProcPassiveBB ( )
self . __ProcPassiveOper ( )
2023-02-21 22:27:38 +08:00
def __GetOneFromSet ( self , vals : set [ int ] ) - > int :
return next ( iter ( vals ) )
def __FillDataFromDb ( self ) :
2023-02-22 21:49:31 +08:00
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 ( ) :
2023-02-21 22:27:38 +08:00
payload : DecoratorData . BBDataPayload = DecoratorData . BBDataPayload ( sqldata )
2023-02-22 21:49:31 +08:00
self . m_Graph . m_BlockDict [ payload . m_CKID ] = DecoratorData . BBTreeNode ( payload )
2023-02-21 22:27:38 +08:00
self . __AllBB . add ( payload . m_CKID )
2023-02-22 21:49:31 +08:00
cursor . execute ( ' SELECT * FROM [script_pOper] WHERE parent == ? ' , ( self . m_Graph . m_GraphCKID , ) )
for sqldata in cursor . fetchall ( ) :
2023-02-21 22:27:38 +08:00
payload : DecoratorData . OperDataPayload = DecoratorData . OperDataPayload ( sqldata )
2023-02-22 21:49:31 +08:00
self . m_Graph . m_BlockDict [ payload . m_CKID ] = DecoratorData . OperTreeNode ( payload )
2023-02-21 22:27:38 +08:00
self . __AllOper . add ( payload . m_CKID )
2023-02-22 21:49:31 +08:00
cursor . close ( )
2023-02-22 10:23:05 +08:00
2023-02-23 15:50:18 +08:00
def __RecursiveFindOperRoot ( self , envir : FindOperRootEnvironment ) - > tuple [ int ] :
envir . m_Cursor . execute ( ' SELECT [output_obj], [output_type], [output_is_bb] FROM [script_pLink] WHERE ([input_obj] == ? AND [input_is_bb] == ? AND NOT (([output_type] == ? OR [output_type] == ?) AND [output_is_bb] == ?) AND [parent] == ?); ' ,
( envir . m_QueryOper , ( DecoratorConst . Export_Boolean . TRUE if envir . m_Depth == 0 else DecoratorConst . Export_Boolean . FALSE ) ,
DecoratorConst . Export_pLink_InputOutputType . PIN , DecoratorConst . Export_pLink_InputOutputType . PTARGET , DecoratorConst . Export_Boolean . TRUE , # filter all BB's pIn
self . m_Graph . m_GraphCKID )
)
2023-02-22 21:49:31 +08:00
2023-02-23 15:50:18 +08:00
opers : set [ int ] = set ( )
results : set [ int ] = set ( )
2023-02-22 21:49:31 +08:00
2023-02-23 15:50:18 +08:00
# read datas
for ( output_obj , output_type , output_is_bb , ) in envir . m_Cursor . fetchall ( ) :
# check dup
if output_obj in envir . m_WalkedOper :
continue
envir . m_WalkedOper . add ( output_obj )
2023-02-22 21:49:31 +08:00
2023-02-23 15:50:18 +08:00
if output_type == DecoratorConst . Export_pLink_InputOutputType . PIN :
# this is a oper. find its pOut and add into stack
opers . add ( output_obj )
else :
# this oper point to non-pIn, should be add into result
results . add ( output_obj )
# recursive calling opers to get root
for oper in opers :
results . update ( self . __RecursiveFindOperRoot ( FindOperRootEnvironment (
envir . m_Cursor , envir . m_WalkedOper , envir . m_Depth + 1 , oper
) ) )
return tuple ( i for i in results )
def __RecursiveBuildOper ( self , envir : BuildOperEnvironment ) :
envir . m_Cursor . execute ( " SELECT [input_obj] FROM [script_pLink] WHERE ([output_obj] == ? AND [output_type] == ? AND [input_type] == ? AND [input_is_bb] == ? AND [parent] = ?); " ,
( envir . m_QueryOper , DecoratorConst . Export_pLink_InputOutputType . PIN , # order pOper's pIn
2023-02-22 21:49:31 +08:00
DecoratorConst . Export_pLink_InputOutputType . POUT , DecoratorConst . Export_Boolean . FALSE , # order pOper's pOut
self . m_Graph . m_GraphCKID , )
)
2023-02-23 15:50:18 +08:00
gottenOper : list [ int ] = [ ]
for ( input_obj , ) in envir . m_Cursor . fetchall ( ) :
if input_obj in self . __AllOper :
self . __AllOper . remove ( input_obj )
gottenOper . append ( input_obj )
2023-02-22 21:49:31 +08:00
2023-02-23 15:50:18 +08:00
if len ( gottenOper ) == 0 :
2023-02-22 10:23:05 +08:00
return
2023-02-23 15:50:18 +08:00
if envir . m_Depth == 0 :
# if depth == 0, all item should start from a new layer
for item in gottenOper :
envir . m_Tree . NewLayer ( DecoratorData . TreeLayout . NO_REFERENCE_LAYER , DecoratorData . TreeLayout . NO_START_POS_OF_REF_LAYER )
envir . m_Tree . NewItem ( self . m_Graph . m_BlockDict [ item ] )
self . __RecursiveBuildOper ( BuildOperEnvironment (
envir . m_Cursor , envir . m_Tree , envir . m_Depth + 1 , item
) )
else :
# otherwise, only non-first node need new layer
# proc first node
first : int = gottenOper [ 0 ]
envir . m_Tree . NewItem ( self . m_Graph . m_BlockDict [ first ] )
self . __RecursiveBuildOper ( BuildOperEnvironment (
envir . m_Cursor , envir . m_Tree , envir . m_Depth + 1 , first
) )
# get layer and pos
cur_layer = envir . m_Tree . GetCurrentLayerIndex ( )
cur_idx = envir . m_Tree . GetCurrentItemIndex ( )
# proc other node
for other in gottenOper [ 1 : ] :
envir . m_Tree . NewLayer ( cur_layer , cur_idx )
envir . m_Tree . NewItem ( self . m_Graph . m_BlockDict [ other ] )
self . __RecursiveBuildOper ( BuildOperEnvironment (
envir . m_Cursor , envir . m_Tree , envir . m_Depth + 1 , other
) )
def __RecursiveBuildBB ( self , envir : BuildBBEnvironment ) :
# query all link for next bb
envir . m_Cursor . execute ( ' SELECT [output_obj] FROM [script_bLink] WHERE ([input_obj] == ? AND [input_type] == ? AND [parent] = ?) ORDER BY [input_index] ASC; ' ,
( envir . m_QueryBB ,
( DecoratorConst . Export_bLink_InputOutputType . INPUT if envir . m_Depth == 0 else DecoratorConst . Export_bLink_InputOutputType . OUTPUT ) ,
self . m_Graph . m_GraphCKID )
2023-02-22 10:23:05 +08:00
)
2023-02-23 15:50:18 +08:00
# filter useless bb
gottenBB : list [ int ] = [ ]
for ( output_obj , ) in envir . m_Cursor . fetchall ( ) :
if output_obj in self . __AllBB :
self . __AllBB . remove ( output_obj )
gottenBB . append ( output_obj )
2023-02-22 10:23:05 +08:00
2023-02-23 15:50:18 +08:00
if len ( gottenBB ) == 0 :
return
2023-02-22 10:23:05 +08:00
2023-02-23 15:50:18 +08:00
# we need process this BB related opers now
# for every item
for bbid in gottenBB :
bb : DecoratorData . BBTreeNodeWrapper = self . m_Graph . m_BlockDict [ bbid ]
# upper opers
self . __RecursiveBuildOper ( BuildOperEnvironment (
envir . m_Cursor , bb . m_UpperOper , 0 , bbid
) )
# lower opers
lower_root : tuple [ int ] = self . __RecursiveFindOperRoot ( FindOperRootEnvironment (
envir . m_Cursor , set ( ) , 0 , bbid
) )
for operid in lower_root :
# we need add it manually
self . __AllOper . remove ( operid )
bb . m_LowerOper . NewLayer ( DecoratorData . TreeLayout . NO_REFERENCE_LAYER , DecoratorData . TreeLayout . NO_START_POS_OF_REF_LAYER )
bb . m_LowerOper . NewItem ( self . m_Graph . m_BlockDict [ operid ] )
# gotten "root" is oper's CKID, so use depth 1 to cheat this function
self . __RecursiveBuildOper ( BuildOperEnvironment (
envir . m_Cursor , bb . m_LowerOper , 1 , operid
) )
# now we place BB in tree layout
if envir . m_Depth == 0 :
# if depth == 0, all item should start from a new layer
for item in gottenBB :
envir . m_Tree . NewLayer ( DecoratorData . TreeLayout . NO_REFERENCE_LAYER , DecoratorData . TreeLayout . NO_START_POS_OF_REF_LAYER )
envir . m_Tree . NewItem ( self . m_Graph . m_BlockDict [ item ] )
self . __RecursiveBuildBB ( BuildBBEnvironment (
envir . m_Cursor , envir . m_Tree , envir . m_Depth + 1 , item
) )
else :
# otherwise, only non-first node need new layer
# proc first node
first : int = gottenBB [ 0 ]
envir . m_Tree . NewItem ( self . m_Graph . m_BlockDict [ first ] )
self . __RecursiveBuildBB ( BuildBBEnvironment (
envir . m_Cursor , envir . m_Tree , envir . m_Depth + 1 , first
) )
# get layer and pos
cur_layer = envir . m_Tree . GetCurrentLayerIndex ( )
cur_idx = envir . m_Tree . GetCurrentItemIndex ( )
# proc other node
for other in gottenBB [ 1 : ] :
envir . m_Tree . NewLayer ( cur_layer , cur_idx )
envir . m_Tree . NewItem ( self . m_Graph . m_BlockDict [ other ] )
self . __RecursiveBuildBB ( BuildBBEnvironment (
envir . m_Cursor , envir . m_Tree , envir . m_Depth + 1 , other
) )
2023-02-22 21:49:31 +08:00
2023-02-23 15:50:18 +08:00
2023-02-22 10:23:05 +08:00
def __ProcActiveBB ( self ) :
2023-02-22 21:49:31 +08:00
cursor : sqlite3 . Cursor = self . m_Db . cursor ( )
2023-02-23 15:50:18 +08:00
self . __RecursiveBuildBB ( BuildBBEnvironment (
cursor , self . m_Graph . m_ActivePassiveBB , 0 , self . m_Graph . m_GraphCKID
) )
2023-02-22 21:49:31 +08:00
cursor . close ( )
2023-02-22 10:23:05 +08:00
def __ProcPassiveBB ( self ) :
2023-02-22 21:49:31 +08:00
cursor : sqlite3 . Cursor = self . m_Db . cursor ( )
2023-02-22 10:23:05 +08:00
while len ( self . __AllBB ) != 0 :
2023-02-23 15:50:18 +08:00
# we manually add first
bbid = self . __GetOneFromSet ( self . __AllBB )
self . __AllBB . remove ( bbid )
self . m_Graph . m_ActivePassiveBB . NewLayer ( DecoratorData . TreeLayout . NO_REFERENCE_LAYER , DecoratorData . TreeLayout . NO_START_POS_OF_REF_LAYER )
self . m_Graph . m_ActivePassiveBB . NewItem ( self . m_Graph . m_BlockDict [ bbid ] )
# use depth = 1 to cheat this function for avoiding error bIO type
self . __RecursiveBuildBB ( BuildBBEnvironment (
cursor , self . m_Graph . m_ActivePassiveBB , 1 , bbid
) )
2023-02-22 21:49:31 +08:00
cursor . close ( )
2023-02-22 10:23:05 +08:00
def __ProcPassiveOper ( self ) :
2023-02-23 15:50:18 +08:00
cursor : sqlite3 . Cursor = self . m_Db . cursor ( )
while len ( self . __AllOper ) != 0 :
# peek one randomly and try finding root
peek : int = self . __GetOneFromSet ( self . __AllOper )
roots : tuple [ int ] = self . __RecursiveFindOperRoot ( FindOperRootEnvironment (
cursor , set ( ) , 1 , peek # use 1 to cheat this function
) )
# if no root found, add self
roots = ( peek , )
# generate tree
for operid in roots :
# we need add it manually
self . __AllOper . remove ( operid )
self . m_Graph . m_PassiveOper . NewLayer ( DecoratorData . TreeLayout . NO_REFERENCE_LAYER , DecoratorData . TreeLayout . NO_START_POS_OF_REF_LAYER )
self . m_Graph . m_PassiveOper . NewItem ( self . m_Graph . m_BlockDict [ operid ] )
# gotten "roots" is oper's CKID, so use depth 1 to cheat this function
self . __RecursiveBuildOper ( BuildOperEnvironment (
cursor , self . m_Graph . m_PassiveOper , 1 , operid
) )
cursor . close ( )