UNPKG

pm4js

Version:

Process Mining for Javascript

231 lines (219 loc) 9.96 kB
class CelonisNDWrapper { constructor(celonisMapper) { this.celonisMapper = celonisMapper; this.celonis1Dwrapper = new Celonis1DWrapper(this.celonisMapper); } getMVPmodel(analysisId) { if (analysisId == null) { analysisId = this.celonisMapper.getFirstAnalysis(); } let dataModel = this.celonisMapper.dataModels[this.celonisMapper.analysisDataModel[analysisId]]; let dataModelTables = this.celonisMapper.dataModelsTables[dataModel["id"]]; let mvp = {}; for (let configuration of dataModel.processConfigurations) { let activityTable = dataModelTables[configuration["activityTableId"]]; mvp[activityTable] = this.celonis1Dwrapper.downloadFrequencyDfg(analysisId, configuration.id); } return mvp; } static uuidv4() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } static nodeUuid() { let uuid = CelonisNDWrapper.uuidv4(); return "n"+uuid.replace(/-/g, ""); } static stringToColour(str) { var hash = 0; for (var i = 0; i < str.length; i++) { hash = str.charCodeAt(i) + ((hash << 5) - hash); } var colour = '#'; for (var i = 0; i < 3; i++) { var value = (hash >> (i * 8)) & 0xFF; colour += ('00' + value.toString(16)).substr(-2); } return colour; } static visualizationMVP(mvp) { let ret = []; let activities = {}; let startNodes = {}; let endNodes = {}; ret.push("digraph G {"); for (let persp in mvp) { let perspCol = CelonisNDWrapper.stringToColour(persp); for (let act in mvp[persp].activities) { if (!(act in activities)) { let nodeUuid = CelonisNDWrapper.nodeUuid(); activities[act] = nodeUuid; ret.push(nodeUuid+" [shape=box, label=\""+act+"\"]"); } } let startNodeUuid = CelonisNDWrapper.nodeUuid(); startNodes[persp] = startNodeUuid; ret.push(startNodeUuid+" [shape=ellipse, label=\""+persp+"\", color=\""+perspCol+"\", style=filled, fillcolor=\""+perspCol+"\"]"); let endNodeUuid = CelonisNDWrapper.nodeUuid(); endNodes[persp] = endNodeUuid; ret.push(endNodeUuid+" [shape=ellipse, label=\""+persp+"\", color=\""+perspCol+"\", style=filled, fillcolor=\""+perspCol+"\"]"); } for (let persp in mvp) { let perspCol = CelonisNDWrapper.stringToColour(persp); for (let edge0 in mvp[persp].pathsFrequency) { let edge = edge0.split(","); ret.push(activities[edge[0]]+" -> "+activities[edge[1]]+" [color=\""+perspCol+"\", label=\"TO="+mvp[persp].pathsFrequency[edge0]+"\"]") } for (let act in mvp[persp].startActivities) { ret.push(startNodes[persp]+" -> "+activities[act]+" [color=\""+perspCol+"\", label=\"TO="+mvp[persp].startActivities[act]+"\"]"); } for (let act in mvp[persp].endActivities) { ret.push(activities[act]+" -> "+endNodes[persp]+" [color=\""+perspCol+"\", label=\"TO="+mvp[persp].endActivities[act]+"\"]"); } } ret.push("}"); return ret.join("\n"); } downloadBaseEventLog(analysisId, processConfiguration) { let dataModel = this.celonisMapper.dataModels[this.celonisMapper.analysisDataModel[analysisId]]; let dataModelTables = this.celonisMapper.dataModelsTables[dataModel["id"]]; let activityTable = dataModelTables[processConfiguration["activityTableId"]]; let query = []; query.push("TABLE("); query.push("\""+activityTable+"\".\""+processConfiguration.caseIdColumn+"\" AS \"ocel:omap\", "); query.push("\""+activityTable+"\".\""+processConfiguration.activityColumn+"\" AS \"ocel:activity\", "); query.push("\""+activityTable+"\".\""+processConfiguration.timestampColumn+"\" AS \"ocel:timestamp\") NOLIMIT;"); query = query.join(""); let res = CsvImporter.parseCSV(this.celonisMapper.performQueryAnalysis(analysisId, query)); return [activityTable, res]; } downloadRelations(analysisId, processConfiguration1, processConfiguration2) { let dataModel = this.celonisMapper.dataModels[this.celonisMapper.analysisDataModel[analysisId]]; let dataModelTables = this.celonisMapper.dataModelsTables[dataModel["id"]]; let activityTable1 = dataModelTables[processConfiguration1["activityTableId"]]; let activityTable2 = dataModelTables[processConfiguration2["activityTableId"]]; let activityColumn1 = processConfiguration1["activityColumn"]; let activityColumn2 = processConfiguration2["activityColumn"]; let timestampColumn1 = processConfiguration1["timestampColumn"]; let timestampColumn2 = processConfiguration2["timestampColumn"]; let caseColumn2 = processConfiguration2["caseIdColumn"]; let query = []; query.push("TABLE ("); query.push("TRANSIT_COLUMN ( TIMESTAMP_INTERLEAVED_MINER ("); query.push("\""+activityTable2+"\".\""+activityColumn2+"\", "); query.push("\""+activityTable1+"\".\""+activityColumn1+"\"), "); query.push("\""+activityTable2+"\".\""+caseColumn2+"\"), "); query.push("\""+activityTable1+"\".\""+activityColumn1+"\", "); query.push("\""+activityTable1+"\".\""+timestampColumn1+"\""); query.push(") NOLIMIT;"); query = query.join(""); try { let res0 = this.celonisMapper.performQueryAnalysis(analysisId, query); return CsvImporter.parseCSV(res0); } catch (err) { console.log(err); return []; } } downloadDataModelFromCelonis(analysisId) { let dataModelId = this.celonisMapper.analysisDataModel[analysisId]; let dataModel = this.celonisMapper.dataModels[dataModelId]; let ocel = {"ocel:global-log": {"ocel:attribute-names": [], "ocel:object-types": []}, "ocel:events": {}, "ocel:objects": {}}; for (let conf of dataModel.processConfigurations) { let arr = this.downloadBaseEventLog(analysisId, conf); let ot = arr[0]; let log = arr[1]; ocel["ocel:global-log"]["ocel:object-types"].push(ot); let i = 1; while (i < log.length) { let evid = log[i][1] + log[i][2]; let objId = log[i][0]; let eve = {"ocel:activity": log[i][1], "ocel:timestamp": new Date(log[i][2])}; ocel["ocel:events"][evid] = {"ocel:activity": log[i][1], "ocel:timestamp": new Date(log[i][2]), "ocel:omap": {objId: 0}}; if (!(objId in ocel["ocel:objects"])) { ocel["ocel:objects"][objId] = {"ocel:type": ot}; } i++; } } let i = 0; while (i < dataModel.processConfigurations.length) { let j = 0; while (j < dataModel.processConfigurations.length) { if (i != j) { let ret = this.downloadRelations(analysisId, dataModel.processConfigurations[i], dataModel.processConfigurations[j]); let z = 1; while (z < ret.length) { let evid = ret[z][1] + ret[z][2]; let objId = ret[z][0]; ocel["ocel:events"][evid]["ocel:omap"][objId] = 0; z = z + 1; } } j++; } i++; } for (let evId in ocel["ocel:events"]) { if ("objId" in ocel["ocel:events"][evId]["ocel:omap"]) { delete ocel["ocel:events"][evId]["ocel:omap"]["objId"]; } ocel["ocel:events"][evId]["ocel:omap"] = Object.keys(ocel["ocel:events"][evId]["ocel:omap"]); } return ocel; } uploadOcelToCelonis(ocel, baseName, dummy=false, sep=",", quotechar="\"", newline="\r\n") { let dataPoolId = null; let dataModelId = null; let workspaceId = null; let analysisId = null; let res = OcelToCelonis.apply(ocel, sep, quotechar, newline); if (!(dummy)) { dataPoolId = this.celonisMapper.createDataPool(baseName+"_POOL", false); dataModelId = this.celonisMapper.createDataModel(dataPoolId, baseName+"_DMODEL"); this.celonisMapper.getDataPools(); this.celonisMapper.getDataModels(); for (let tab in res["coll"]) { console.log("pushing table: "+tab+" "+res["timestampColumns"][tab]); this.celonisMapper.pushCSV(dataPoolId, res["coll"][tab], tab, false, res["timestampColumns"][tab], sep, quotechar, newline); this.celonisMapper.getDataPools(); console.log("adding table to data model: "+tab); this.celonisMapper.addTableFromPool(dataModelId, tab, false); } this.celonisMapper.getDataModels(); for (let ot of res["objectTypes"]) { console.log("setting up foreign key for type: "+ot); this.celonisMapper.addForeignKey(dataModelId, ot+"_EVENTS", "CASE_"+ot, ot+"_CASES", "CASE_"+ot, false); console.log("adding process configuration:"); this.celonisMapper.addProcessConfiguration(dataModelId, ot+"_EVENTS", ot+"_CASES", "CASE_"+ot, "ACT_"+ot, "TIME_"+ot, null, false); } for (let trans of res["transitions"]) { console.log("adding foreign keys for transition: "+trans); this.celonisMapper.addForeignKey(dataModelId, "CONNECT_"+trans[0]+"_CASES_"+trans[1]+"_CASES", "CASE_"+trans[0], trans[0]+"_CASES", "CASE_"+trans[0], false); this.celonisMapper.addForeignKey(dataModelId, "CONNECT_"+trans[0]+"_CASES_"+trans[1]+"_CASES", "CASE_"+trans[1], trans[1]+"_CASES", "CASE_"+trans[1], false); } this.celonisMapper.reloadDataModel(dataModelId); console.log("creating workspace"); workspaceId = this.celonisMapper.createWorkspace(dataModelId, baseName+"_WORKSPACE"); console.log("creating analysis"); analysisId = this.celonisMapper.createAnalysis(workspaceId, baseName+"_ANALYSIS", false); console.log("reloading data pools"); this.celonisMapper.getDataPools(); console.log("reloading data models"); this.celonisMapper.getDataModels(); console.log("reloading analyses"); this.celonisMapper.getAnalyses(); } return {"dataPoolId": dataPoolId, "dataModelId": dataModelId, "workspaceId": workspaceId, "analysisId": analysisId, "objectTypes": res["objectTypes"], "transitions": res["transitions"], "knowledgeYaml": res["knowledgeYaml"], "modelYaml": res["modelYaml"]}; } } try { global.CelonisNDWrapper = CelonisNDWrapper; module.exports = {CelonisNDWrapper: CelonisNDWrapper}; } catch (err) { // not in Node }