Skip to content

Commit 4d51d0f

Browse files
committed
docs and README update
1 parent 257cf80 commit 4d51d0f

File tree

3 files changed

+159
-0
lines changed

3 files changed

+159
-0
lines changed

Diff for: README.md

+158
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# Sorting hat
2+
3+
This repository hosts a questionnaire/survey/quiz-like application, which consist of a backend that is agnostic of the type of survey the user is taking, and a frontend that is specific to the topic of the survey.
4+
5+
It is using **Angular** as it's frontend, including **apollo** and **graphql** both on the front and the back. **NestJS** for the backend and **prisma** as a Node.js/TypeScript ORM, with an **sqlite** database.
6+
7+
In this README I use questionnaire/survey/quiz interchangeably, but I really mean of an application that gives you possible questions and answers, and with each answer on a question you score points towards a final result.
8+
9+
![decision tree](docs/assets/decision-tree.png)
10+
_view in bigger resolution [here](https://raw.githubusercontent.com/lubeskih/sorting-hat/main/docs/assets/decision-tree.png?token=ALSATGCRDIGJHBLZOVEBIX3BTIVPM)_
11+
12+
**Table of Contents**
13+
14+
- [How to build and run](#How-to-build-and-run)
15+
- [How it works](#How-it-works)
16+
- [Matrix](#Matrix)
17+
- [Survey](#Survey)
18+
- [User](#User)
19+
- [Scoring and decisions](#Decision)
20+
- [Database models and relations diagram](#Database-models-and-relations-diagram)
21+
22+
23+
## How to build and run
24+
25+
```bash
26+
$ git clone https://github.com/lubeskih/sorting-hat.git
27+
$ cd sorting-hat
28+
$ docker-compose up # -d (optionally)
29+
```
30+
31+
Docker will try to start the applications on ports `4200` and `3000`, so make sure those are open and not used on your machine. Otherwise you'll have to change the Docker configuration to your desired ports.
32+
33+
After the images are built and containers are running, visit `localhost:4200`. The `POTTERMORE` survey is following this JSON structure: [hp_survey.json](api/src/parser/service/hp_survey.json) and is seeded automatically by the `ParserService`, which parses and validates the file, and seeds the database if it is not already seeded.
34+
35+
## How it works
36+
37+
The full application is divided in two parts: a `backend` and a `frontend`. The `backend` survey engine is independent of the topic of the survey on the frontend. For example, this frontend hosted here is a survey for Harry Potter fans. But it can really be any kind of survey as long as it involves scoring points per given answer.
38+
39+
The backend understands three concepts:
40+
41+
* **Matrix**
42+
* **Survey**
43+
* **User**
44+
45+
### Matrix
46+
47+
I use the word **matrix** to describe an array of objects, where each object keeps a unique answer and an array of numbers which represent the score that the answer brings towards the final outcomes.
48+
49+
The "source of truth" comes from a JSON file (find the application's JSON [here](api/src/parser/service/hp_survey.json)), which holds a structure that the backend parses/validates and then seeds the database. In a real-world situation you would have a nice frontend that would let the user make their own survey structure in a more user-friendly way, instead of writing JSON in a file. For example, the JSON structure for a matrix looks like this:
50+
51+
```JSON
52+
{
53+
"matrix": [
54+
{
55+
"surveyTitle": "pottermore",
56+
"bias": [3, 2, 1, 0],
57+
"surveyMatrix": [
58+
{
59+
"answerId": 1,
60+
"matrixId": 1,
61+
"score": [100, 100, 0, 0]
62+
},
63+
{
64+
"answerId": 2,
65+
"matrixId": 1,
66+
"score": [0, 0, 100, 100]
67+
}
68+
]
69+
}
70+
]
71+
}
72+
73+
```
74+
75+
### Survey
76+
77+
A **Survey** is a structure that consists of:
78+
* A name of the survey
79+
* An ID of the matrix it's answers are being weighted
80+
* Array of questions
81+
82+
A **Question** is an object that consists of:
83+
* A **value**, or the question itself
84+
* **answerChoice**, which is later send to the frontend to decide how the user should answer it's answers (text input, radio button, normal button).
85+
* **parentSurveyId** the survey id that the question is a child of.
86+
* **lastQuestion** which is a boolean that specifies if that question is the last question of the survey.
87+
* Array of answers
88+
89+
An **Answer** is an object that has:
90+
* A value, or the answer itself
91+
* **parentQuestionId** which is the ID of it's parent
92+
* **nextQuestionId** which is the ID of the next question that should be asked if that answer is chosen. This property gives the survey a tree-structure navigation.
93+
94+
A JSON structure for a survey looks like this:
95+
96+
```JSON
97+
{
98+
"survey": [
99+
{
100+
"surveyTitle": "pottermore",
101+
"scoreMatrixId": 1,
102+
"questions": [
103+
{
104+
"value": "Dawn or dusk?",
105+
"answerChoice": "radio_button",
106+
"parentSurveyId": 1,
107+
"lastQuestion": false,
108+
"answers": [
109+
{
110+
"value": "Dawn",
111+
"parentQuestionId": 1,
112+
"nextQuestionId": 2
113+
},
114+
{
115+
"value": "Dusk",
116+
"parentQuestionId": 1,
117+
"nextQuestionId": 2
118+
}
119+
]
120+
},
121+
]
122+
}
123+
]
124+
}
125+
```
126+
127+
### User
128+
A user is just an entity in database that has an unique session token as soon as they start a survey. The session token is kept is session storage, and is being sent upon each answer, so it can be recorded, and later linked against the score matrix to calculate the score. Each user can have a `user answer`, which is just a record of which user selected which answer on which question.
129+
130+
131+
## Scoring and decisions
132+
133+
When a user chooses and answers and continues to the next question, the `DecisionsService` is recalculating it's score towards the possible final outcomes.
134+
135+
This diagram shows how the `DecisionsService` is doing the calculations:
136+
137+
![scoring diagram](docs/assets/scoring.png)
138+
_view in bigger resolution [here]()_
139+
140+
What we see here is, each column of the answer matrix represents points given to each house. For each column, the values are added, which represent the total score of one house. After we find the total score of each house, those scores are added to find the total score of all houses together.
141+
142+
The **bias** is a preference towards a final outcome, it is used in case two houses have the same score. (you'd say it's unfair, and I'd agree, but then it's a _bias_).
143+
144+
Then, we find percentage with:
145+
146+
```
147+
score = 100 * (score_house / score_total)
148+
```
149+
150+
## Database models and relations diagram
151+
<br>
152+
153+
![db relations](docs/assets/relations.png)
154+
_view in bigger resolution [here](https://raw.githubusercontent.com/lubeskih/sorting-hat/main/docs/assets/relations.png?token=ALSATGCI3CL5GJTPYJIMWH3BTIVVU)_
155+
156+
## License
157+
158+
This software is licensed under [MIT](LICENSE.md).

Diff for: docs/assets/scoring.png

72.5 KB
Loading

Diff for: docs/assets/xml/scoring.drawio

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<mxfile host="app.diagrams.net" modified="2021-11-21T12:24:29.185Z" agent="5.0 (X11)" etag="xc9Zl2-2rm1J7lhV68Cj" version="15.7.0" type="device"><diagram id="7DQUapl_bQZywB9Was5H" name="Page-1">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</diagram></mxfile>

0 commit comments

Comments
 (0)