Harry Potter is celebrating yet another trip around the sun and I built a Sorting Hat of sorts to distract myself from just how many birthdays that is for The Boy Who Lived (and me).
Due to the proprietary nature of magic and magical items, the experience of a magical hat guiding me at the beginning of my educational career was not in the cards (to say nothing of the need for time travel). However, this has not deterred me. I’ve often come across these kinds of challenges and, when I want to create something magical, I turn to open source.
Using the open standards Decision Model and Notation (DMN) and Business Model and Notation (BPMN), as well as our very own open source Camunda Platform, I built something that can match people with their proper Hogwarts house.
Interested in finding out which house you belong to? You can check out the final project and installation instructions here.
Building the DRD
I wanted to be thorough, so I started with a Decision Requirements Diagram (DRD) to play around with different high-level designs and add relationships between the various decision tables. This helps scope out how many rule sets are needed and also what inputs are valuable. I would have been very unhappy if my lack of attention to detail would lead to the great house of Slytherin being infested with unworthy students.
At the top of this DRD is the main table Decide on House. For it to decide, it needs to get the results from four other tables (one for each house), as well as take into account the Preferred House of the student.
Building DMN tables for each house
I decided to use DMN tables to create a scoring system. The result of each table would be a score that represents the affinity a person would have for each house. The bigger the number, the stronger that affinity.
When a user/victim answers a list of questions, their answers will earn them positive or negative points towards each house.
In the Are you Gryffindor table for example, doing a bunch of useless tasks would give you positive points while doing anything interesting or cunning would get you negative points.
The Hit Policy is set to Collect (Sum), meaning that multiple rules on this table can match a set of input values. A value called Gryffindor Score exists for each rule. All rules that match would have their Gryffindor Score added together to give you a single result. For example for the input:
- Play Quidditch? – True
- Your Potion – Beautification Potion
- Horcrux – 11
- Your Wand – phoenix feathers
- Help a Friend – Jump in the Way
It would trigger the following rules:
You can see that for help a Friend if you chose to oddly Jump in the Way of danger, you would get 100 points added to your Gryffindor Score. But if you select something useful and clever like having nine or more horcruxes, you’d get -100 points.
In the end, all of these inputs mentioned above add up to a total Gryffindor Score of 60, which is ok. But if you’re going to be making a bunch of horcruxes then Gryffindor isn’t for you.
I used the same scoring method for each of the tables but with obviously very different rules. There is an emphasis on specific inputs that I felt aligned better with the principles of each house. Ultimately, I had four separate DMN tables that each gave me a score for a given house.
The final decision
For the final part of the decision making process, I needed to take all of those values and put them through the Decide on House table, while also taking into account the house that person originally picked.
This table didn’t give a score, but rather returned the name of the house that you’re best suited for. Unlike the other tables, this one has the Hit Policy set to First, meaning that it would go through each rule individually until a single rule matches all the input criteria. As soon as a rule matches, it returns the result. This means that the order in which the rules are placed really matters.
It would be pretty boring to simply return to the house that you got the highest score in, so I decided to make things a little more complex. Knowing that Gryffindor and Slytherin don’t usually get along, I added a rule that enforces if your Gryffindor score is higher than any other house and is at least 20 points higher than your Slytherin score, then you’re relegated to serving your time in Gryffindor.
Another rule I added was to make it clear that Huffelfpuff was the most inclusive and accepting of the houses. With the other houses you need to have at least a score of 100 to qualify, but Hufflepuff only requires 25. By adding the Hufflepuff check to near the bottom, it meant that if you don’t have a strong affinity with any other house you’ll likely end up in Hufflepuff.
The very last rule is a catch-all. If for some reason you don’t have a clear affinity for any of the houses, that’s when we take your own choice into account.
Deploying and Evaluating
At this point, the DMN tables and DRD are complete and ready for execution.
To run it, you’d just need three things:
- Open the SortingHat.dmn file with the modeler and deploy it to the Camunda Platform from the modeler
- Test the table by clicking here
- Scroll down to
Decision Definition
and select theEvaluate by Key
call
- Once there, you just need to add the key of the DMN model – which is
DecideOnHouse
and then the body containing the input values:
{
"variables": {
"friend": {
"value": "Jump in the Way",
"type": "String"
},
"houseChoice": {
"value": "Slytherin",
"type": "String"
},
"wand": {
"value": "phoenix feathers",
"type": "String"
},
"quidditch": {
"value": true,
"type": "Boolean"
},
"horkrux": {
"value": 11,
"type": "Long"
},
"potion": {
"value": "Beautification Potion",
"type": "String"
},
"rules": {
"value": true,
"type": "Boolean"
},
"robes": {
"value": true,
"type": "Boolean"
},
"prime": {
"value": 280,
"type": "Long"
},
"milk": {
"value": 0.75,
"type": "Double"
}
}
}
Click on Execute, and if you’re really lucky you should see the following return value:
What’s next?
Well, making a REST call from the swaggerUI is nice, but it’s not ideal. The ideal scenario would be to have a BPMN model which displays a set of questions for the user to answer and subsequently takes those answers and executes the DMN table in the background displaying the results. Thankfully, this is already done.
Checkout the full report for details.