diff --git a/.cspell.json b/.cspell.json index 3037dab87eb..41df3fe6454 100644 --- a/.cspell.json +++ b/.cspell.json @@ -35,6 +35,8 @@ "cccs", "ccep", "ccid", + "ccmodel", + "cctx", "celo", "cids", "clazz", @@ -206,6 +208,7 @@ "undici", "unixfs", "Unmarshal", + "unmodeled", "utxoexample", "uuidv", "vscc", diff --git a/packages/cactus-plugin-ccmodel-hephaestus/.gitignore b/packages/cactus-plugin-ccmodel-hephaestus/.gitignore index e923932be38..fc4c178418c 100644 --- a/packages/cactus-plugin-ccmodel-hephaestus/.gitignore +++ b/packages/cactus-plugin-ccmodel-hephaestus/.gitignore @@ -1,4 +1,3 @@ cactus-openapi-spec-plugin-consortium-manual.json src/main/typescript/generated/openapi/typescript-axios/.npmignore -src/test/csv -src/test/json +src/test/ccLogs \ No newline at end of file diff --git a/packages/cactus-plugin-ccmodel-hephaestus/README.md b/packages/cactus-plugin-ccmodel-hephaestus/README.md index 87fc6bcc7dc..1ca46028288 100644 --- a/packages/cactus-plugin-ccmodel-hephaestus/README.md +++ b/packages/cactus-plugin-ccmodel-hephaestus/README.md @@ -32,6 +32,16 @@ In the root of the project to install the dependencies execute the command: npm run configure ``` +The plugin requires Python and packages for process mining functionality. Install the following prerequisites: +1. Python 3.x and pip: +```sh +sudo apt install python3 python3-pip +``` +2. Required Python packages: +```sh +pip3 install pm4py pandas +``` + Know how to use the following plugins of the project: - [cactus-plugin-ledger-connector-besu](https://github.com/hyperledger/cactus/tree/main/packages/cactus-plugin-ledger-connector-besu) diff --git a/packages/cactus-plugin-ccmodel-hephaestus/src/main/typescript/pm4py-adapter/check_conformance.py b/packages/cactus-plugin-ccmodel-hephaestus/src/main/python/check_conformance.py similarity index 81% rename from packages/cactus-plugin-ccmodel-hephaestus/src/main/typescript/pm4py-adapter/check_conformance.py rename to packages/cactus-plugin-ccmodel-hephaestus/src/main/python/check_conformance.py index e2d80a3701f..61ed7dfac9e 100644 --- a/packages/cactus-plugin-ccmodel-hephaestus/src/main/typescript/pm4py-adapter/check_conformance.py +++ b/packages/cactus-plugin-ccmodel-hephaestus/src/main/python/check_conformance.py @@ -11,13 +11,6 @@ from pm4py.objects.petri_net.obj import PetriNet, Marking from pm4py.objects.petri_net.utils import petri_utils -#chage path if necessary -path = os.getcwd() -parent = os.path.dirname(path) -csv_dir = path + "/packages/cactus-plugin-ccmodel-hephaestus/src/test/csv" -json_dir = path + "/packages/cactus-plugin-ccmodel-hephaestus/src/test/json" -pnml_file = path + "/packages/cactus-plugin-ccmodel-hephaestus/src/main/typescript/pm4py-adapter/process_models/pnml/petri_output.pnml" - ################################################################## def import_csv_original(file_path): @@ -34,17 +27,6 @@ def import_json_original(file_path): ################################################################## -def unserialize_and_check_conformance_file(ccLog): - net, initial_marking, final_marking = pm4py.read_pnml(pnml_file) - # pm4py.view_petri_net(net, initial_marking, final_marking) - - # check conformance: - print("\n----diagnostics:") - diagnostics = pm4py.conformance_diagnostics_alignments(ccLog, net, initial_marking, final_marking) - print(diagnostics) - -################################################################## - def divide_model(model): split_model = model.split(';') return split_model[0], split_model[1], split_model[2], split_model[3], split_model[4] @@ -112,17 +94,15 @@ def unserialize_model(model): (source, target) = get_from_to_arc(arc) # source is a place, target is a transition - if get_place(net.places, source) != None: + if get_place(net.places, source) != None: place = get_place(net.places, source) transition = get_transition(net.transitions, target) petri_utils.add_arc_from_to(place, transition, net) - # target is a place, source is a transition elif get_place(net.places, target) != None: transition = get_transition(net.transitions, source) place = get_place(net.places, target) petri_utils.add_arc_from_to(transition, place, net) - # target and source are both a transition or a place - cannot happen else: print("arcs cannot have the same type in source and target") @@ -171,13 +151,13 @@ def unserialize_and_check_conformance(ccLog): if len(non_conforming_activities) != 0: print("NON-CONFORMANCE:") print(non_conforming_activities) - print(file) + print(os.path.basename(log_file_path)) return if len(all_activities) == len(conforming_activities): print("FULL CONFORMANCE:") print(conforming_activities) - print(file) + print(os.path.basename(log_file_path)) return # If there were no skips in the case, then all the conforming activities @@ -191,36 +171,36 @@ def unserialize_and_check_conformance(ccLog): if ignore_skips == True: print("PARTIAL CONFORMANCE:") print(conforming_activities) - print(file) + print(os.path.basename(log_file_path)) else: print("SKIPPED ACTIVITY:") print(skipped_activities) - print(file) + print(os.path.basename(log_file_path)) ################################################################## def main(): - file_csv = file + ".csv" - file_json = file + ".json" - - file_path_csv = os.path.join(csv_dir, file_csv) - file_path_json = os.path.join(json_dir, file_json) - if (os.path.exists(file_path_csv)): - ccLog = import_csv_original(file_path_csv) + if not os.path.exists(log_file_path): + print(f"File '{log_file_path}' does not exist") + exit(1) + + file_extension = os.path.splitext(log_file_path)[1].lower() + + if file_extension == '.csv': + ccLog = import_csv_original(log_file_path) unserialize_and_check_conformance(ccLog) - elif (os.path.exists(file_path_json)): - ccLog = import_json_original(file_path_json) + elif file_extension == '.json': + ccLog = import_json_original(log_file_path) unserialize_and_check_conformance(ccLog) else: - print(f"File '{file}' does not exist") - print(file_path_json) + print(f"Unsupported file type: {file_extension}") exit(1) if __name__ == "__main__": if len(sys.argv) != 3: - print("Usage: python3 check_conformance.py file_with_new_logs serialized_ccmodel") + print("Usage: python3 check_conformance.py path_to_log_file serialized_ccmodel") exit(1) - file = sys.argv[1] + log_file_path = sys.argv[1] serialized_ccmodel = sys.argv[2] main() \ No newline at end of file diff --git a/packages/cactus-plugin-ccmodel-hephaestus/src/main/typescript/pm4py-adapter/convert_model.py b/packages/cactus-plugin-ccmodel-hephaestus/src/main/python/convert_model.py similarity index 100% rename from packages/cactus-plugin-ccmodel-hephaestus/src/main/typescript/pm4py-adapter/convert_model.py rename to packages/cactus-plugin-ccmodel-hephaestus/src/main/python/convert_model.py diff --git a/packages/cactus-plugin-ccmodel-hephaestus/src/main/python/create_model.py b/packages/cactus-plugin-ccmodel-hephaestus/src/main/python/create_model.py new file mode 100644 index 00000000000..7f06e68842f --- /dev/null +++ b/packages/cactus-plugin-ccmodel-hephaestus/src/main/python/create_model.py @@ -0,0 +1,59 @@ +import sys +import os +# uncomment if problems with dependencies +#%pip install pm4py +#%pip install pandas +import pm4py +import time +import pandas +import pickle +import json + +def import_csv_original(file_path): + event_log = pandas.read_csv(file_path, sep=';') + event_log = pm4py.format_dataframe(event_log, case_id='caseID', activity_key='methodName', timestamp_key='timestamp') + return event_log + +def import_json_original(file_path): + with open(file_path, 'r') as file: + data = json.load(file) + event_log = pandas.DataFrame(data) + event_log = pm4py.format_dataframe(event_log, case_id='caseID', activity_key='methodName', timestamp_key='timestamp') + return event_log + +################################################################## + +def create_and_serialize_model(ccLog): + pn, im, fm = pm4py.discover_petri_net_inductive(ccLog) + # pm4py.view_petri_net(pn, im, fm) + return str(pn.places) + ";" + str(pn.transitions) + ";" + str(pn.arcs) + ";" + str(im) + ";" + str(fm) + +################################################################## + +def main(): + file_path = sys.argv[1] + + if not os.path.exists(file_path): + print(f"File '{file_path}' does not exist") + exit(1) + + file_extension = os.path.splitext(file_path)[1].lower() + + if file_extension == '.csv': + ccLog = import_csv_original(file_path) + serialized_model = create_and_serialize_model(ccLog) + print(serialized_model) + elif file_extension == '.json': + ccLog = import_json_original(file_path) + serialized_model = create_and_serialize_model(ccLog) + print(serialized_model) + else: + print(f"Unsupported file type: {file_extension}") + exit(1) + +if __name__ == "__main__": + if len(sys.argv) != 2: + print("Usage: python3 create_model.py path_to_log_file") + exit(1) + + main() \ No newline at end of file diff --git a/packages/cactus-plugin-ccmodel-hephaestus/src/main/typescript/pm4py-adapter/ccmodel-adapter.ts b/packages/cactus-plugin-ccmodel-hephaestus/src/main/typescript/ccmodel-adapter.ts similarity index 64% rename from packages/cactus-plugin-ccmodel-hephaestus/src/main/typescript/pm4py-adapter/ccmodel-adapter.ts rename to packages/cactus-plugin-ccmodel-hephaestus/src/main/typescript/ccmodel-adapter.ts index c9837952703..d3e7f25eb22 100644 --- a/packages/cactus-plugin-ccmodel-hephaestus/src/main/typescript/pm4py-adapter/ccmodel-adapter.ts +++ b/packages/cactus-plugin-ccmodel-hephaestus/src/main/typescript/ccmodel-adapter.ts @@ -2,9 +2,9 @@ import { execSync } from "child_process"; import path from "path"; -export function createModelPM4PY(file_name: string): string { - const createModelScript = path.join(__dirname, "create_model.py"); - const command = `python3 ${createModelScript} ${file_name}`; +export function createModelPM4PY(logPath: string): string { + const createModelScript = path.join(__dirname, "../python/create_model.py"); + const command = `python3 ${createModelScript} ${logPath}`; try { const startTime = new Date(); @@ -21,11 +21,14 @@ export function createModelPM4PY(file_name: string): string { } export function checkConformancePM4PY( - file_name: string, + logPath: string, serializedCCModel: string, ): string { - const checkConformanceScript = path.join(__dirname, "check_conformance.py"); - const command = `python3 ${checkConformanceScript} ${file_name} \'${serializedCCModel}\'`; + const checkConformanceScript = path.join( + __dirname, + "../python/check_conformance.py", + ); + const command = `python3 ${checkConformanceScript} ${logPath} \'${serializedCCModel}\'`; // console.log(command); try { diff --git a/packages/cactus-plugin-ccmodel-hephaestus/src/main/typescript/plugin-ccmodel-hephaestus.ts b/packages/cactus-plugin-ccmodel-hephaestus/src/main/typescript/plugin-ccmodel-hephaestus.ts index fa26b486fec..d9430b41929 100644 --- a/packages/cactus-plugin-ccmodel-hephaestus/src/main/typescript/plugin-ccmodel-hephaestus.ts +++ b/packages/cactus-plugin-ccmodel-hephaestus/src/main/typescript/plugin-ccmodel-hephaestus.ts @@ -1,7 +1,3 @@ -import { Server } from "http"; -import { Server as SecureServer } from "https"; -import { Optional } from "typescript-optional"; -import { promisify } from "util"; import { IPluginWebService, IWebServiceEndpoint, @@ -32,10 +28,7 @@ import { CrossChainEvent, CrossChainEventLog, } from "./models/cross-chain-event"; -import { - createModelPM4PY, - checkConformancePM4PY, -} from "./pm4py-adapter/ccmodel-adapter"; +import { createModelPM4PY, checkConformancePM4PY } from "./ccmodel-adapter"; export interface IWebAppOptions { port: number; @@ -70,27 +63,28 @@ export interface IPluginCcModelHephaestusOptions extends ICactusPluginOptions { fabricTxObservable?: Observable; sourceLedger: LedgerType; targetLedger: LedgerType; + ccLogsDir?: string; } export class CcModelHephaestus implements ICactusPlugin, IPluginWebService { private readonly log: Logger; private readonly instanceId: string; private endpoints: IWebServiceEndpoint[] | undefined; - private httpServer: Server | SecureServer | null = null; private crossChainLog: CrossChainEventLog; private unmodeledEventLog: CrossChainEventLog; private nonConformedCrossChainLog: CrossChainEventLog; - private nonConformedCCTxs: string[]; + private readonly nonConformedCCTxs: string[]; private crossChainModel: CrossChainModel; public readonly className = "plugin-ccmodel-hephaestus"; private caseID: string; - private ethTxObservable?: Observable; - private besuTxObservable?: Observable; - private fabricTxObservable?: Observable; - private sourceLedger: LedgerType; - private targetLedger: LedgerType; + private readonly besuTxObservable?: Observable; + private readonly ethTxObservable?: Observable; + private readonly fabricTxObservable?: Observable; + private readonly sourceLedger: LedgerType; + private readonly targetLedger: LedgerType; private startMonitoring: number | null = null; private isModeling: boolean; + private readonly ccLogsDir: string; constructor(public readonly options: IPluginCcModelHephaestusOptions) { const startTime = new Date(); @@ -132,6 +126,14 @@ export class CcModelHephaestus implements ICactusPlugin, IPluginWebService { this.nonConformedCCTxs = []; + this.ccLogsDir = + options.ccLogsDir || path.join(__dirname, "..", "..", "test", "ccLogs"); + // Create directories if they don't exist + if (!fs.existsSync(this.ccLogsDir)) { + fs.mkdirSync(path.join(this.ccLogsDir, "csv"), { recursive: true }); + fs.mkdirSync(path.join(this.ccLogsDir, "json"), { recursive: true }); + } + const finalTime = new Date(); this.log.debug( `EVAL-${this.className}-SETUP-CONSTRUCTOR:${finalTime.getTime() - startTime.getTime()}`, @@ -189,15 +191,6 @@ export class CcModelHephaestus implements ICactusPlugin, IPluginWebService { public async shutdown(): Promise { this.log.info(`Shutting down...`); - const serverMaybe = this.getHttpServer(); - if (serverMaybe.isPresent()) { - this.log.info(`Awaiting server.close() ...`); - const server = serverMaybe.get(); - await promisify(server.close.bind(server))(); - this.log.info(`server.close() OK`); - } else { - this.log.info(`No HTTP server found, skipping...`); - } } async registerWebServices(app: Express): Promise { @@ -225,20 +218,15 @@ export class CcModelHephaestus implements ICactusPlugin, IPluginWebService { return endpoints; } - public getHttpServer(): Optional { - return Optional.ofNullable(this.httpServer); - } - public getPackageName(): string { return `@hyperledger/cactus-plugin-ccmodel-hephaestus`; } private createReceiptFromRunTransactionV1ExchangeBesu( data: RunTransactionV1ExchangeBesu, - caseId: string, ): BesuV2TxReceipt { return { - caseID: caseId, + caseID: this.caseID, blockchainID: LedgerType.Besu2X, timestamp: data.timestamp, transactionID: data.response.transactionReceipt.transactionHash, @@ -251,25 +239,11 @@ export class CcModelHephaestus implements ICactusPlugin, IPluginWebService { }; } - private pollTxReceiptsBesu( - data: RunTransactionV1ExchangeBesu, - ): BesuV2TxReceipt { - const fnTag = `${this.className}#pollTxReceiptsBesu()`; - this.log.debug(fnTag); - - const besuReceipt = this.createReceiptFromRunTransactionV1ExchangeBesu( - data, - this.caseID, - ); - return besuReceipt; - } - private createReceiptFromRunTransactionV1ExchangeEth( data: RunTransactionV1ExchangeEth, - caseId: string, ): EthereumTxReceipt { return { - caseID: caseId, + caseID: this.caseID, blockchainID: LedgerType.Ethereum, timestamp: data.timestamp, transactionID: data.response.transactionReceipt.transactionHash, @@ -282,25 +256,11 @@ export class CcModelHephaestus implements ICactusPlugin, IPluginWebService { }; } - private pollTxReceiptsEth( - data: RunTransactionV1ExchangeEth, - ): EthereumTxReceipt { - const fnTag = `${this.className}#pollTxReceiptsEth()`; - this.log.debug(fnTag); - - const ethReceipt = this.createReceiptFromRunTransactionV1ExchangeEth( - data, - this.caseID, - ); - return ethReceipt; - } - private createReceiptFromRunTxReqWithTxId( data: RunTxReqWithTxId, - caseId: string, ): FabricV2TxReceipt { return { - caseID: caseId, + caseID: this.caseID, blockchainID: LedgerType.Fabric2, timestamp: data.timestamp, channelName: data.request.channelName, @@ -313,17 +273,6 @@ export class CcModelHephaestus implements ICactusPlugin, IPluginWebService { }; } - private pollTxReceiptsFabric(data: RunTxReqWithTxId): FabricV2TxReceipt { - const fnTag = `${this.className}#pollTxReceiptsFabric()`; - this.log.debug(fnTag); - - const fabricReceipt = this.createReceiptFromRunTxReqWithTxId( - data, - this.caseID, - ); - return fabricReceipt; - } - private watchRunTransactionV1ExchangeBesu(duration: number = 0): void { const fnTag = `${this.className}#watchRunTransactionV1ExchangeBesu()`; this.log.debug(fnTag); @@ -351,7 +300,8 @@ export class CcModelHephaestus implements ICactusPlugin, IPluginWebService { // Handle the data whenever a new value is received by the observer: // this includes creating the receipt, then the cross-chain event // and check its conformance to the model, if the model is already defined - const receipt = this.pollTxReceiptsBesu(data); + const receipt = + this.createReceiptFromRunTransactionV1ExchangeBesu(data); const ccEvent = this.createCrossChainEventFromBesuReceipt( receipt, this.isModeling, @@ -401,7 +351,8 @@ export class CcModelHephaestus implements ICactusPlugin, IPluginWebService { // Handle the data whenever a new value is received by the observer // this includes creating the receipt, then the cross-chain event // and check its conformance to the model, if the model is already defined - const receipt = this.pollTxReceiptsEth(data); + const receipt = + this.createReceiptFromRunTransactionV1ExchangeEth(data); const ccEvent = this.createCrossChainEventFromEthReceipt( receipt, this.isModeling, @@ -450,7 +401,7 @@ export class CcModelHephaestus implements ICactusPlugin, IPluginWebService { // Handle the data whenever a new value is received by the observer // this includes creating the receipt, then the cross-chain event // and check its conformance to the model, if the model is already defined - const receipt = this.pollTxReceiptsFabric(data); + const receipt = this.createReceiptFromRunTxReqWithTxId(data); const ccEvent = this.createCrossChainEventFromFabricReceipt( receipt, this.isModeling, @@ -720,7 +671,7 @@ export class CcModelHephaestus implements ICactusPlugin, IPluginWebService { const logName = name ? `${name}.csv` : `hephaestus_log_${startTime.getTime()}.csv`; - const csvFolder = path.join(__dirname, "../", "../", "test", "csv"); + const csvFolder = path.join(this.ccLogsDir, "csv"); const logPath = path.join(csvFolder, logName); const fnTag = `${this.className}#persistCrossChainLogCsv()`; const ccEvents = this.crossChainLog.logEntries; @@ -741,18 +692,13 @@ export class CcModelHephaestus implements ICactusPlugin, IPluginWebService { // Concatenate columns and rows into a single CSV string const data = [columns.join(";"), ...csvRows].join("\n"); this.log.debug(data); - - // Create directory if it doesn't exist - if (!fs.existsSync(csvFolder)) { - fs.mkdirSync(csvFolder); - } fs.writeFileSync(logPath, data); const finalTime = new Date(); this.log.debug( `EVAL-${this.className}-PERSIST-LOG-CVS:${finalTime.getTime() - startTime.getTime()}`, ); - return logName; + return logPath; } catch (error) { const errorMessage = `${fnTag} Failed to export cross-chain event log to CSV file:`; throw new RuntimeError(errorMessage, error); @@ -764,7 +710,7 @@ export class CcModelHephaestus implements ICactusPlugin, IPluginWebService { const logName = name ? `${name}.json` : `hephaestus_log_${startTime.getTime()}.json`; - const jsonFolder = path.join(__dirname, "../", "../", "test", "json"); + const jsonFolder = path.join(this.ccLogsDir, "json"); const logPath = path.join(jsonFolder, logName); const fnTag = `${this.className}#persistCrossChainLogJson()`; @@ -773,19 +719,13 @@ export class CcModelHephaestus implements ICactusPlugin, IPluginWebService { try { const data = JSON.stringify(ccEvents, null, 2); this.log.debug(data); - - // Create directory if it doesn't exist - if (!fs.existsSync(jsonFolder)) { - fs.mkdirSync(jsonFolder); - } fs.writeFileSync(logPath, data); const finalTime = new Date(); this.log.debug( `EVAL-${this.className}-PERSIST-LOG-JSON:${finalTime.getTime() - startTime.getTime()}`, ); - - return logName; + return logPath; } catch (error) { const errorMessage = `${fnTag} Failed to export cross-chain event log to JSON file:`; throw new RuntimeError(errorMessage, error); @@ -795,7 +735,7 @@ export class CcModelHephaestus implements ICactusPlugin, IPluginWebService { private async persistUnmodeledEventLog(): Promise { const startTime = new Date(); const logName = `hephaestus_log_${startTime.getTime()}`; - const jsonFolder = path.join(__dirname, "../", "../", "test", "json"); + const jsonFolder = path.join(this.ccLogsDir, "json"); const logPath = path.join(jsonFolder, logName + ".json"); const fnTag = `${this.className}#persistUnmodeledEventLog()`; @@ -804,19 +744,13 @@ export class CcModelHephaestus implements ICactusPlugin, IPluginWebService { try { const data = JSON.stringify(ccLogEvents, null, 2); this.log.debug(data); - - // Create directory if it doesn't exist - if (!fs.existsSync(jsonFolder)) { - fs.mkdirSync(jsonFolder); - } fs.writeFileSync(logPath, data); const finalTime = new Date(); this.log.debug( `EVAL-${this.className}-PERSIST-LOG-JSON:${finalTime.getTime() - startTime.getTime()}`, ); - - return logName; + return logPath; } catch (error) { const errorMessage = `${fnTag} Failed to export cross-chain event log to JSON file:`; throw new RuntimeError(errorMessage, error); @@ -846,10 +780,9 @@ export class CcModelHephaestus implements ICactusPlugin, IPluginWebService { } public async createModel(): Promise { - let fileName = await this.persistCrossChainLogJson(); - fileName = fileName.split(".")[0]; + const logPath = await this.persistCrossChainLogJson(); await this.aggregateCcTx(); - const petriNet = createModelPM4PY(fileName); + const petriNet = createModelPM4PY(logPath); this.ccModel.setType(CrossChainModelType.PetriNet); this.saveModel(CrossChainModelType.PetriNet, petriNet); this.setLedgerMethods(); @@ -861,9 +794,9 @@ export class CcModelHephaestus implements ICactusPlugin, IPluginWebService { serializedCCModel: string, ledgerHasMethod: boolean, ): Promise { - const fileName = await this.persistUnmodeledEventLog(); + const logPath = await this.persistUnmodeledEventLog(); const conformanceDetails = checkConformancePM4PY( - fileName, + logPath, serializedCCModel, ); return this.filterLogsByConformance(conformanceDetails, ledgerHasMethod); diff --git a/packages/cactus-plugin-ccmodel-hephaestus/src/main/typescript/pm4py-adapter/create_model.py b/packages/cactus-plugin-ccmodel-hephaestus/src/main/typescript/pm4py-adapter/create_model.py deleted file mode 100644 index cb1fd8f96e9..00000000000 --- a/packages/cactus-plugin-ccmodel-hephaestus/src/main/typescript/pm4py-adapter/create_model.py +++ /dev/null @@ -1,84 +0,0 @@ -import sys -import os -# uncomment if problems with dependencies -#%pip install pm4py -#%pip install pandas -import pm4py -import time -import pandas -import pickle -import json - -#chage path if necessary -path = os.getcwd() -parent = os.path.dirname(path) -csv_dir = path + "/packages/cactus-plugin-ccmodel-hephaestus/src/test/csv" -json_dir = path + "/packages/cactus-plugin-ccmodel-hephaestus/src/test/json" -pnml_file = path + "/packages/cactus-plugin-ccmodel-hephaestus/src/main/typescript/pm4py-adapter/process_models/pnml/petri_output.pnml" - -def import_csv_original(file_path): - event_log = pandas.read_csv(file_path, sep=';') - event_log = pm4py.format_dataframe(event_log, case_id='caseID', activity_key='methodName', timestamp_key='timestamp') - return event_log - -def import_json_original(file_path): - with open(file_path, 'r') as file: - data = json.load(file) - event_log = pandas.DataFrame(data) - event_log = pm4py.format_dataframe(event_log, case_id='caseID', activity_key='methodName', timestamp_key='timestamp') - return event_log - -################################################################## -# unused - -def create_and_serialize_model_file(ccLog): - pn, im, fm = pm4py.discover_petri_net_inductive(ccLog) - pm4py.write_pnml(pn, im, fm, pnml_file) - -def create_and_serialize_model_pickle(ccLog): - pn, im, fm = pm4py.discover_petri_net_inductive(ccLog) - - pn_str = pickle.dumps(pn) - print(pn_str) - im_str = pickle.dumps(im) - print(im_str) - fm_str = pickle.dumps(fm) - print(fm_str) - - return pn_str + b"\n" + im_str + b"\n" + fm_str + b"\n" - -################################################################## - -def create_and_serialize_model(ccLog): - pn, im, fm = pm4py.discover_petri_net_inductive(ccLog) - # pm4py.view_petri_net(pn, im, fm) - return str(pn.places) + ";" + str(pn.transitions) + ";" + str(pn.arcs) + ";" + str(im) + ";" + str(fm) - -################################################################## - -def main(): - file_csv = file + ".csv" - file_json = file + ".json" - - file_path_csv = os.path.join(csv_dir, file_csv) - file_path_json = os.path.join(json_dir, file_json) - - if (os.path.exists(file_path_csv)): - ccLog = import_csv_original(file_path_csv) - serialized_model = create_and_serialize_model(ccLog) - print(serialized_model) - elif (os.path.exists(file_path_json)): - ccLog = import_json_original(file_path_json) - serialized_model = create_and_serialize_model(ccLog) - print(serialized_model) - else: - print(f"File '{file}' does not exist") - exit(1) - -if __name__ == "__main__": - if len(sys.argv) != 2: - print("Usage: python3 create_model.py file_with_logs") - exit(1) - - file = sys.argv[1] - main() \ No newline at end of file diff --git a/packages/cactus-plugin-ccmodel-hephaestus/src/test/typescript/integration/cross-chain-model-conformance-checking.test.ts b/packages/cactus-plugin-ccmodel-hephaestus/src/test/typescript/integration/cross-chain-model-conformance-checking.test.ts index e9c5867b580..3aeaf99bd0d 100644 --- a/packages/cactus-plugin-ccmodel-hephaestus/src/test/typescript/integration/cross-chain-model-conformance-checking.test.ts +++ b/packages/cactus-plugin-ccmodel-hephaestus/src/test/typescript/integration/cross-chain-model-conformance-checking.test.ts @@ -271,7 +271,7 @@ describe("Test cross-chain model serialization and conformance checking", () => hephaestus.setIsModeling(false); }); - test("Check confomity of unmodeled transaction when they happen", async () => { + test("Check conformance of unmodeled transaction when they happen", async () => { const createResEth = await apiClient.invokeContractV1({ contract: { contractName: LockAssetContractJson.contractName,