Giter Club home page Giter Club logo

decisioncentral's Introduction

DecisionCentral

DecisionCentral is a central repository for all DMN based decision services.

DecisionCentral

  • Creates a web site that lets you upload DMN compliant Excel workbooks or DMN conformant XML files
  • For each uploaded DMN compliant Excel workbook or DMN compliant XML file, DecisionCentral will
    • create a decision service from that DMN compliant Excel workbook or DMN conformant XML file
    • create a user interface where users can enter values and check specific use cases for this decision service
    • creates an API for this decision service which accepts JSON data (the input values) and returns a JSON structure (representing the decision)
  • For each decision service, DecisionCentral will create web pages detailing all the parts of your decision service
    • The glossary of data items, both inputs and outputs, associated with this decision service
    • The decision sequence (the sequence in which you decision tables will be run)
    • The decision tables that form this decision service
    • An OpenAPI specification for the the API associated with this decision service which will be displayed as a web page, but it can also be downloaded and imported to Postman/Swagger etc.
  • For each decision table, within each decision service, DecisionCentral will
    • create a DMN compliant representation of the rules built when the decision service was created
    • create a user interface where users can enter values and check specific use cases for this decision table within this decision service
    • create an API for this decision table within this decision service which accepts JSON data (the input values) and returns a JSON structure (representing the decision)
    • createe an OpenAPI specification for the the API associated with this decision table with this decision service which will be displayed as a web page, but it can also be downloaded and imported to Postman/Swagger etc.

DecisionCentral also has an API for uploading a DMN compliant Excel workbook or DMN conformant XML file, plus and API for deleting a decision service.

DecisionCentral listens for http requests on port 7777 by default. The -p portNo option lets you assign a different port. However, DecisionCental can also be run in a container (it uses no disk storage - see the dockerfile) and you can use containter port mapping to map your desired port to 7777.

DecisionCentral can be run locally (see -h option for details).
However can also be run in a container - dockerfile can be used to build a Docker image
$ docker build -t decisioncentral:0.0.1 .
And run under Docker Desktop
$ docker run --name decisioncentral -p 7777:7777 -d decisioncentral:0.0.1

There is a flask version of DecisionCentral which is the reference version. It can also be run in a docker container and the basis for [DecisionCentralAzure] (https://github.com/russellmcdonell/DecisionCentralAzure) - a version which creates an Azure Program as a Platform instance of DecisionCentral. NOTE: The flask versions listens for http requests on port 5000, and it too can be run in a container.

JSON and DMN data types JSON doesn't support all the data types that are supported by DMN (and the FEEL expression language). Decision Central borrows a solution suggested by FEEL - @strings. If a string starts with the two characters @" and ends with the character " then what is in between has to be de-serialized by some other non-JSON interpreter. In this case, the FEEL interpreter (pySFeel). The following code can be used to serialize and de-serialize @strings.

import datetime
import pySFeel

parser = pySFeel.SFeelParser()


def convertAtString(thisString):
    # Convert an @string
    (status, newValue) = parser.sFeelParse(thisString[2:-1])
    if 'errors' in status:
        return thisString
    else:
        return newValue


def convertIn(newValue):
    if isinstance(newValue, dict):
        for key in newValue:
            if isinstance(newValue[key], int):
                newValue[key] = float(newValue[key])
            elif isinstance(newValue[key], str) and (newValue[key][0:2] == '@"') and (newValue[key][-1] == '"'):
                newValue[key] = convertAtString(newValue[key])
            elif isinstance(newValue[key], dict) or isinstance(newValue[key], list):
                newValue[key] = convertIn(newValue[key])
    elif isinstance(newValue, list):
        for i in range(len(newValue)):
            if isinstance(newValue[i], int):
                newValue[i] = float(newValue[i])
            elif isinstance(newValue[i], str) and (newValue[i][0:2] == '@"') and (newValue[i][-1] == '"'):
                newValue[i] = convertAtString(newValue[i])
            elif isinstance(newValue[i], dict) or isinstance(newValue[i], list):
                newValue[i] = convertIn(newValue[i])
    elif isinstance(newValue, str) and (newValue[0:2] == '@"') and (newValue[-1] == '"'):
        newValue = convertAtString(newValue)
    return newValue


  def convertOut(thisValue):
      if isinstance(thisValue, datetime.date):
          return '@"' + thisValue.isoformat() + '"'
      elif isinstance(thisValue, datetime.datetime):
          return '@"' + thisValue.isoformat(sep='T') + '"'
      elif isinstance(thisValue, datetime.time):
          return '@"' + thisValue.isoformat() + '"'
      elif isinstance(thisValue, datetime.timedelta):
          sign = ''
          duration = thisValue.total_seconds()
          if duration < 0:
              duration = -duration
              sign = '-'
          secs = duration % 60
          duration = int(duration / 60)
          mins = duration % 60
          duration = int(duration / 60)
          hours = duration % 24
          days = int(duration / 24)
          return '@"%sP%dDT%dH%dM%fS"' % (sign, days, hours, mins, secs)
      elif isinstance(thisValue, bool):
          return thisValue:
      elif thisValue is None:
          return thisValue:
      elif isinstance(thisValue, int):
          sign = ''
          if thisValue < 0:
              thisValue = -thisValue
              sign = '-'
          years = int(thisValue / 12)
          months = (thisValue % 12)
          return '@"%sP%dY%dM"' % (sign, years, months)
      elif isinstance(thisValue, tuple) and (len(thisValue) == 4):
          (lowEnd, lowVal, highVal, highEnd) = thisValue
          return '@"' + lowEnd + str(lowVal) + ' .. ' + str(highVal) + highEnd
      elif thisValue is None:
          return 'null'
      elif isinstance(thisValue, dict):
          for item in thisValue:
              thisValue[item] = convertOut(thisValue[item])
          return thisValue
      elif isinstance(thisValue, list):
          for i in range(len(thisValue)):
              thisValue[i] = convertOut(thisValue[i])
          return thisValue
      else:
          return thisValue

questioner.py is a client that calls a specified Decision Central API, passing data from questions.xlsx and storing the decisions in answers.xlsx

DecisionCentral is not, of itself, a production product. You use pyDMNrules to build those.
It is intended for use at Hackathons and Connectathons; anywhere you need a complex decision service created quickly and easily.

decisioncentral's People

Contributors

russellmcdonell avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

decisioncentral's Issues

Facing Error while 'Make a Decision'

Hi,

I am new to pyDMNrules.
Facing the error , after I click on the 'Make a Decision' button.

method()
File "C:\Users\ux303ln\Desktop\dec\dec\decisioncentral.py", line 1348, in do_POST
(status, self.data.newData) = dmnRules.decideTables(self.data.data, [part])
File "C:\Users\ux303ln\fastapi-mongo\venv\lib\site-packages\pyDMNrules\DMNrules.py", line 5332, in decideTables
self.errors.append('Invalid Decision Table - ' + table)
TypeError: can only concatenate str (not "NoneType") to str

Localhost install. The same xlsx works smoothly in pyDMNrules.

Kindly advise on a relevant fix, if any.

image
image

Did a bit of troubleshooting. changed 'part' in line 1348 to parts and restarted the server.
The server restart issue disappeared. But this is displayed.

image

Console log:
decisioncentral Thread-5 (process_request_thread) [21/09/22 10:59:50 AM]: POST - bad status from decide()
decisioncentral Thread-5 (process_request_thread) [21/09/22 10:59:50 AM]: {'errors': ['Invalid Decision Table - rule004']}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.