def removePanel(panelID): del FandS[panelID] response = { "deletedPanelID": panelID, "minifiedFandS": helper.createMinifiedFandS() } return jsonify(response)
def createSimpleCategoricalFilter(): global FandS panelIDOfInputSeq = request.args["panelID"] ForSIDOfInputSeq = request.args["ForSID"] selectedAttrName = request.args["attributeName"] selectedAttrValue = request.args["attributeValue"] # init FandS newForSID = helper.getNewForSID(panelIDOfInputSeq) FandS[panelIDOfInputSeq][newForSID] = { "name": selectedAttrName + "=" + selectedAttrValue, "input": ForSIDOfInputSeq + "-after", # input must be after "output": None, "averageTime": { "after": None }, "averageNumberOfEvents": { "after": None }, "applyToSequences": False, "applyToRecordAttributes": True, "trueStart": { "after": {} }, "trueEnd": { "after": {} } } # update output helper.updateCategoricalFilterOutput(panelIDOfInputSeq, newForSID) # change input of the ForS with the same input as the created ForS ForSIDWithInputChanged = None for currentForSID in FandS[panelIDOfInputSeq]: if currentForSID != newForSID and currentForSID != ForSIDOfInputSeq: # a ForS can have its output as input inputStringOfUpdatedForS = ForSIDOfInputSeq + "-after" inputStringOfCurrentForS = FandS[panelIDOfInputSeq][currentForSID]["input"] if inputStringOfUpdatedForS == inputStringOfCurrentForS: ForSIDWithInputChanged = currentForSID FandS[panelIDOfInputSeq][currentForSID]["input"] = newForSID + "-after" break # update all subsequent ForS (all inputs are correct after the above step) currentForSID = ForSIDWithInputChanged while currentForSID != None: isPatternSplittingPoint = "orderedAVPairsForEachMatcher" in FandS[panelIDOfInputSeq][currentForSID] if isPatternSplittingPoint: helper.updatePatternSPOutput(panelIDOfInputSeq, currentForSID) if not isPatternSplittingPoint: helper.updateSimpleSPOutput(panelIDOfInputSeq, currentForSID) currentForSID = helper.getNextForSID(panelIDOfInputSeq, currentForSID) response = { "updatedPanelID": panelIDOfInputSeq, "minifiedFandS": helper.createMinifiedFandS() } return jsonify(response)
def removeSorF(): global FandS panelID = request.args["panelID"] ForSIDToBeDeleted = request.args["ForSID"] inputStringOfDeletedForS = FandS[panelID][ForSIDToBeDeleted]["input"] ForSIDAfterDeletedForS = helper.getNextForSID(panelID, ForSIDToBeDeleted) if ForSIDAfterDeletedForS != None: # change input of next ForS FandS[panelID][ForSIDAfterDeletedForS][ "input"] = inputStringOfDeletedForS # update all subsequent ForS currentForSID = ForSIDAfterDeletedForS while currentForSID != None: isSplittingPoint = FandS[panelID][currentForSID][ "applyToSequences"] isPatternSplittingPoint = "orderedAVPairsForEachMatcher" in FandS[ panelID][currentForSID] isNumerical = "<=" in FandS[panelID][currentForSID]["name"] if isSplittingPoint and isPatternSplittingPoint: helper.updatePatternSPOutput(panelID, currentForSID) if isSplittingPoint and not isPatternSplittingPoint: helper.updateSimpleSPOutput(panelID, currentForSID) if not isSplittingPoint and not isNumerical: helper.updateCategoricalFilterOutput(panelID, currentForSID) if not isSplittingPoint and isNumerical: helper.updateNumericalFilterOutput(panelID, currentForSID) currentForSID = helper.getNextForSID(panelID, currentForSID) del FandS[panelID][ForSIDToBeDeleted] response = { "updatedPanelID": panelID, "removedForSID": ForSIDToBeDeleted, "minifiedFandS": helper.createMinifiedFandS() } return jsonify(response)
def createMultipleSimpleSplittingPoints( ): # cascading add is not required because multiple splitting points are added to new panel global FandS data = request.get_json() panelIDOfInputSeq = data["panelID"] ForSIDOfInputSeq = data["ForSID"] AVPairs = data["AVPairs"] currentInputForSID = ForSIDOfInputSeq for AVPair in AVPairs: # handle for av pair if AVPair["type"] == "AVPair": attributeName = AVPair["attributeName"] attributeValue = AVPair["attributeValue"] # init FandS newForSID = helper.getNewForSID(panelIDOfInputSeq) FandS[panelIDOfInputSeq][newForSID] = { "name": attributeName + "=" + attributeValue, "input": currentInputForSID + "-after", # input must be after "output": None, "averageTime": { "before": None, "after": None }, # in second "averageNumberOfEvents": { "before": None, "after": None }, "applyToSequences": True, "applyToRecordAttributes": False, "trueStart": { "before": {}, "after": {}, "not": {} }, "trueEnd": { "before": {}, "after": {}, "not": {} } } # update output, averageTime, averageNumberOfEvents, trueStart and trueEnd helper.updateSimpleSPOutput(panelIDOfInputSeq, newForSID) # handle for event with multiple av pair if AVPair["type"] == "Pattern": name = AVPair["name"] eventMatchers = AVPair["eventMatchers"] orderedAVPairsForEachMatcher = AVPair[ "orderedAVPairsForEachMatcher"] logicTableForEachMatcher = AVPair["logicTableForEachMatcher"] # init FandS newForSID = helper.getNewForSID(panelIDOfInputSeq) FandS[panelIDOfInputSeq][newForSID] = { "name": name, "input": ForSIDOfInputSeq + "-after", # input must be after "output": None, "averageTime": { "before": None, "after": None }, # in second "averageNumberOfEvents": { "before": None, "after": None }, "applyToSequences": True, "applyToRecordAttributes": False, "trueStart": { "before": {}, "after": {}, "not": {} }, "trueEnd": { "before": {}, "after": {}, "not": {} }, "eventMatchers": eventMatchers, "orderedAVPairsForEachMatcher": orderedAVPairsForEachMatcher, "logicTableForEachMatcher": logicTableForEachMatcher } # update output, averageTime, averageNumberOfEvents, trueStart and trueEnd helper.updatePatternSPOutput(panelIDOfInputSeq, newForSID) # update for next iteration currentInputForSID = newForSID response = { "updatedPanelID": panelIDOfInputSeq, "minifiedFandS": helper.createMinifiedFandS() } return jsonify(response)
def createPatternSplittingPoint(): global FandS data = request.get_json() panelIDOfInputSeq = data["panelID"] ForSIDOfInputSeq = data["ForSID"] name = data["name"] eventMatchers = data["eventMatchers"] orderedAVPairsForEachMatcher = data["orderedAVPairsForEachMatcher"] logicTableForEachMatcher = data["logicTableForEachMatcher"] # init FandS newForSID = helper.getNewForSID(panelIDOfInputSeq) FandS[panelIDOfInputSeq][newForSID] = { "name": name, "input": ForSIDOfInputSeq + "-after", # input must be after "output": None, "averageTime": { "before": None, "after": None }, # in second "averageNumberOfEvents": { "before": None, "after": None }, "applyToSequences": True, "applyToRecordAttributes": False, "trueStart": { "before": {}, "after": {}, "not": {} }, "trueEnd": { "before": {}, "after": {}, "not": {} }, "eventMatchers": eventMatchers, "orderedAVPairsForEachMatcher": orderedAVPairsForEachMatcher, "logicTableForEachMatcher": logicTableForEachMatcher } # update output, averageTime, averageNumberOfEvents, trueStart and trueEnd helper.updatePatternSPOutput(panelIDOfInputSeq, newForSID) # change input of the ForS with the same input as the created ForS ForSIDWithInputChanged = None for currentForSID in FandS[panelIDOfInputSeq]: if currentForSID != newForSID and currentForSID != ForSIDOfInputSeq: # a ForS can have its output as input inputStringOfUpdatedForS = ForSIDOfInputSeq + "-after" inputStringOfCurrentForS = FandS[panelIDOfInputSeq][currentForSID][ "input"] if inputStringOfUpdatedForS == inputStringOfCurrentForS: ForSIDWithInputChanged = currentForSID FandS[panelIDOfInputSeq][currentForSID][ "input"] = newForSID + "-after" break # update all subsequent ForS currentForSID = ForSIDWithInputChanged while currentForSID != None: isPatternSplittingPoint = "orderedAVPairsForEachMatcher" in FandS[ panelIDOfInputSeq][currentForSID] if isPatternSplittingPoint: helper.updatePatternSPOutput(panelIDOfInputSeq, currentForSID) if not isPatternSplittingPoint: helper.updateSimpleSPOutput(panelIDOfInputSeq, currentForSID) currentForSID = helper.getNextForSID(panelIDOfInputSeq, currentForSID) response = { "updatedPanelID": panelIDOfInputSeq, "minifiedFandS": helper.createMinifiedFandS() } return jsonify(response)
def initFandSForNewPanel(): global FandS panelIDOfStartingSeq = request.args["panelID"] ForSIDOfStartingSeq = request.args["ForSID"] outputTypeOfStartingSeq = request.args["outputType"] clearPrevious = request.args["clearPrevious"] isPanelShowingAllSeq = panelIDOfStartingSeq == "0" and ForSIDOfStartingSeq == "0" and outputTypeOfStartingSeq == "0" currentPanelHasFilters = not isPanelShowingAllSeq and helper.hasFilters( panelIDOfStartingSeq) timeAndEventCountFilterList = [] # return to client startingEventSequencesByID = eventSequencesByID startingFilterName = "Start" trueStartByID = {} trueEndByID = {} if clearPrevious == "true": FandS.clear() if isPanelShowingAllSeq: for ID in startingEventSequencesByID: numberOfEventsForCurrentSequence = len( startingEventSequencesByID[ID]) firstEvent = startingEventSequencesByID[ID][0] lastEvent = startingEventSequencesByID[ID][ numberOfEventsForCurrentSequence - 1] trueStartTime = datetime.strptime(firstEvent[0], "%Y-%m-%dT%H:%M:%SZ") trueEndTime = datetime.strptime(lastEvent[0], "%Y-%m-%dT%H:%M:%SZ") trueStartByID[ID] = trueStartTime trueEndByID[ID] = trueEndTime if not isPanelShowingAllSeq and not currentPanelHasFilters: startingEventSequencesByID = FandS[panelIDOfStartingSeq][ ForSIDOfStartingSeq]["output"][outputTypeOfStartingSeq] startingFilterName = FandS[panelIDOfStartingSeq][ForSIDOfStartingSeq][ "name"] trueStartByID = FandS[panelIDOfStartingSeq][ForSIDOfStartingSeq][ "trueStart"][outputTypeOfStartingSeq] trueEndByID = FandS[panelIDOfStartingSeq][ForSIDOfStartingSeq][ "trueEnd"][outputTypeOfStartingSeq] if not isPanelShowingAllSeq and currentPanelHasFilters: results = helper.getIDListSatisfiedEventCountAndTime( panelIDOfStartingSeq) IDListSatisfiedEventCountAndTime = results[ "IDListSatisfiedEventCountAndTime"] timeAndEventCountFilterList = results["timeAndEventCountFilterList"] resultsWithoutFilters = helper.getStartingSeqWithoutFilters( panelIDOfStartingSeq, ForSIDOfStartingSeq, outputTypeOfStartingSeq, IDListSatisfiedEventCountAndTime) startingFilterName = FandS[panelIDOfStartingSeq][ForSIDOfStartingSeq][ "name"] startingEventSequencesByID = resultsWithoutFilters[ "startingEventSequencesByID"] trueStartByID = resultsWithoutFilters["trueStartByID"] trueEndByID = resultsWithoutFilters["trueEndByID"] # create new panel newPanelID = helper.getNewPanelID() FandS[newPanelID] = {} FandS[newPanelID]["0"] = { "name": startingFilterName, "input": "0-after", # input and output are the same "output": { "after": startingEventSequencesByID }, "averageTime": { "after": None }, "averageNumberOfEvents": { "after": None }, "applyToSequences": False, "applyToRecordAttributes": True, "trueStart": { "after": trueStartByID }, "trueEnd": { "after": trueEndByID } } # prevent division by zero if len(startingEventSequencesByID) == 0: FandS[newPanelID]["0"]["averageTime"]["after"] = 0 FandS[newPanelID]["0"]["averageNumberOfEvents"]["after"] = 0 # compute averageTime and averageNumberOfEvents else: sumOfTime = 0 sumOfNumberOfEvents = 0 for ID in startingEventSequencesByID: # add to sumOfNumberOfEvents numberOfEventsForCurrentSequence = len( startingEventSequencesByID[ID]) sumOfNumberOfEvents += numberOfEventsForCurrentSequence # add to sumOfTime startTimeObject = FandS[newPanelID]["0"]["trueStart"]["after"][ID] endTimeObject = FandS[newPanelID]["0"]["trueEnd"]["after"][ID] deltaT = endTimeObject - startTimeObject deltaTInSecond = deltaT.total_seconds() sumOfTime += deltaTInSecond averageTime = sumOfTime / len(startingEventSequencesByID) averageNumberOfEvents = sumOfNumberOfEvents / len( startingEventSequencesByID) FandS[newPanelID]["0"]["averageTime"]["after"] = averageTime FandS[newPanelID]["0"]["averageNumberOfEvents"][ "after"] = averageNumberOfEvents # add back the filters on the clicked panel if not isPanelShowingAllSeq and currentPanelHasFilters: # get all filters in the clicked panel except eventCount or time currentForSID = "0" allFiltersOnPanel = [] while currentForSID != None: isFilter = FandS[panelIDOfStartingSeq][currentForSID][ "applyToRecordAttributes"] isNumerical = "<=" in FandS[panelIDOfStartingSeq][currentForSID][ "name"] isEventCountOrTime = False if isNumerical: splittedName = FandS[panelIDOfStartingSeq][currentForSID][ "name"].split("<=") recordAttributeName = splittedName[1] isEventCountOrTime = (recordAttributeName == "eventCount") or (recordAttributeName == "time") # push filter only if it is not eventCount or time if isFilter and not isEventCountOrTime and currentForSID != "0": allFiltersOnPanel.append( FandS[panelIDOfStartingSeq][currentForSID]) currentForSID = helper.getNextForSID(panelIDOfStartingSeq, currentForSID) # create FandS for each filter previousForSID = "0" for filter in allFiltersOnPanel: newForSID = helper.getNewForSID(newPanelID) filterName = filter["name"] FandS[newPanelID][newForSID] = { "name": filterName, "input": previousForSID + "-after", "output": None, "averageTime": { "after": None }, "averageNumberOfEvents": { "after": None }, "applyToSequences": False, "applyToRecordAttributes": True, "trueStart": { "after": {} }, "trueEnd": { "after": {} } } previousForSID = newForSID # update output of all FandS currentFilterID = helper.getNextForSID(newPanelID, "0") while currentFilterID != None: isNumerical = "<=" in FandS[newPanelID][currentFilterID]["name"] if not isNumerical: helper.updateCategoricalFilterOutput(newPanelID, currentFilterID) if isNumerical: helper.updateNumericalFilterOutput(newPanelID, currentFilterID) currentFilterID = helper.getNextForSID(newPanelID, currentFilterID) response = { "newPanelID": newPanelID, "minifiedFandS": helper.createMinifiedFandS(), "timeAndEventCountFilterList": timeAndEventCountFilterList } return jsonify(response)