Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

193 events hints #216

Merged
merged 17 commits into from
Jan 31, 2020
Merged
16 changes: 11 additions & 5 deletions back-end/resources/manuals/message_manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ are specifically defined depending on the sender and receiver.
- `contents`:
- If type is `instruction`, then the message contents have
- `instruction`: one of following instructions:
`send setup`, `send status`, `reset all`, `test all`, `test device`, `finish rule`, `hint`
- `send setup`, `reset all`, `test all`: no additional parameters
- `test device`, has additional parameter `device` to specify which device to test
- `finish rule`, has additional parameter `rule` to specify which rule to finish
- `hint`: has extra parameters `value` and `topic` to specify the hint to send and on which topic

##### Example
{
Expand All @@ -85,6 +88,7 @@ are specifically defined depending on the sender and receiver.
"rule": "playlist puzzel 1",
}]
}

### Back-end to Front-end
- `type`: the type of the message, this can be:
- `confirmation`
Expand All @@ -105,7 +109,6 @@ are specifically defined depending on the sender and receiver.
- `connection` boolean
- If type is `event status`, then the message contents has objects with
- `id` of rule
- `description` of rule
- `status` of rule describes whether the rule is finished or not
- If type is `front-end status`, then the message contents has a list of objects with:
- `id` of button
Expand All @@ -117,9 +120,12 @@ are specifically defined depending on the sender and receiver.
- If type is `setup`, the contents:
- a `name` parameter carrying the name of the escape room
- a `hints` parameter carrying a map with the name of the puzzle as key and a list of hints as value
- an `events` parameter carrying a map with the name of the rule as key and the description as value
- a `cameras` parameter carrying a list with camera objects with a `name` and `link` tag
- a `buttons` parameter carrying a list of button names that should be added to the front-end
- an `events` parameter carrying a list of maps with the parameters `id`, `description`, `status`,
`puzzle` (whether it belongs to puzzle or not), and `eventName` (name of general event or puzzle it belongs to)
- a `cameras` parameter carrying a list of camera objects with a `name` and `link` tag
- a `buttons` parameter carrying a list of button maps with `id` and `disabled` parameters
for buttons that should be added to the front-end
- a `devices` parameter carrying a list of device maps with `id`, `description` and `labels`

##### example
{
Expand Down
96 changes: 96 additions & 0 deletions back-end/resources/testing/test_doubleGeneralEventNames.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
{
"general": {
"name": "Escape X",
"duration": "30m",
"host": "localhost",
"port": 1883
},
"general_events": [
{
"name": "event",
"hints": [],
"rules": [
{
"id": "mainSwitch flipped",
"description": "Als de mainSwitch true is, moet greenLight1 aangaan",
"limit": 1,
"conditions": {
"operator": "OR",
"list": [
{
"type": "device",
"type_id": "controlBoard",
"constraints": {
"operator": "AND",
"list": [
{
"component_id": "mainSwitch",
"comparison": "eq",
"value": true
}
]
}
}
]
},
"actions": [
{
"type": "device",
"type_id": "controlBoard",
"message": [
{
"component_id": "greenLight1",
"instruction": "turnOnOff",
"value": true
}
]
}
]
}
]
},
{
"name": "event",
"hints": [],
"rules": [
{
"id": "mainSwitch2 flipped",
"description": "Als de mainSwitch true is, moet greenLight1 aangaan",
"limit": 1,
"conditions": {
"operator": "OR",
"list": [
{
"type": "device",
"type_id": "controlBoard",
"constraints": {
"operator": "AND",
"list": [
{
"component_id": "mainSwitch",
"comparison": "eq",
"value": true
}
]
}
}
]
},
"actions": [
{
"type": "device",
"type_id": "controlBoard",
"message": [
{
"component_id": "greenLight1",
"instruction": "turnOnOff",
"value": true
}
]
}
]
}
]
}
]
}
96 changes: 96 additions & 0 deletions back-end/resources/testing/test_doublePuzzleNames.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
{
"general": {
"name": "Escape X",
"duration": "30m",
"host": "localhost",
"port": 1883
},
"puzzles": [
{
"name": "event",
"hints": [],
"rules": [
{
"id": "mainSwitch flipped",
"description": "Als de mainSwitch true is, moet greenLight1 aangaan",
"limit": 1,
"conditions": {
"operator": "OR",
"list": [
{
"type": "device",
"type_id": "controlBoard",
"constraints": {
"operator": "AND",
"list": [
{
"component_id": "mainSwitch",
"comparison": "eq",
"value": true
}
]
}
}
]
},
"actions": [
{
"type": "device",
"type_id": "controlBoard",
"message": [
{
"component_id": "greenLight1",
"instruction": "turnOnOff",
"value": true
}
]
}
]
}
]
},
{
"name": "event",
"hints": [],
"rules": [
{
"id": "mainSwitch2 flipped",
"description": "Als de mainSwitch true is, moet greenLight1 aangaan",
"limit": 1,
"conditions": {
"operator": "OR",
"list": [
{
"type": "device",
"type_id": "controlBoard",
"constraints": {
"operator": "AND",
"list": [
{
"component_id": "mainSwitch",
"comparison": "eq",
"value": true
}
]
}
}
]
},
"actions": [
{
"type": "device",
"type_id": "controlBoard",
"message": [
{
"component_id": "greenLight1",
"instruction": "turnOnOff",
"value": true
}
]
}
]
}
]
}
]
}
3 changes: 2 additions & 1 deletion back-end/resources/testing/test_setup.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"type": "string",
"instructions": {
"play": "string"
}
},
"label": ["sound"]
},
"ringTone": {
"type": "string",
Expand Down
50 changes: 45 additions & 5 deletions back-end/src/sciler/config/configHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ func generateDataStructures(readConfig ReadConfig) (WorkingConfig, []string) {
uniqueErrors := checkUniqueIDs(&config)
config.StatusMap = generateStatusMap(&config)
config.EventRuleMap = generateEventRuleMap(&config)
config.PuzzleRuleMap = generatePuzzleRuleMap(&config)
config.LabelMap = generateLabelMap(&config)
errorList = append(errorList, append(ruleErrors, append(uniqueErrors, checkConfig(config)...)...)...)
}
Expand Down Expand Up @@ -211,15 +212,31 @@ func generateRuleMap(config *WorkingConfig) (map[string]*Rule, []string) {
return ruleMap, errorList
}

// generatePuzzle RuleMap creates rule map with rule id
// pointing to rule object pointers for rules of all puzzles and general events
// generateEventRuleMap creates rule map with rule id
// pointing to rule object pointers for rules of all general events
func generateEventRuleMap(config *WorkingConfig) map[string]*Rule {
ruleMap := make(map[string]*Rule)
rules := getAllRules(config)

for _, rule := range rules {
ruleMap[rule.ID] = rule
for _, event := range config.GeneralEvents {
for _, rule := range event.GetRules() {
ruleMap[rule.ID] = rule
}
}

return ruleMap
}

// generatePuzzleRuleMap creates rule map with rule id
// pointing to rule object pointers for rules of all puzzles
func generatePuzzleRuleMap(config *WorkingConfig) map[string]*Rule {
ruleMap := make(map[string]*Rule)

for _, event := range config.Puzzles {
IssaHanou marked this conversation as resolved.
Show resolved Hide resolved
for _, rule := range event.GetRules() {
ruleMap[rule.ID] = rule
}
}

return ruleMap
}

Expand Down Expand Up @@ -279,35 +296,58 @@ func appendWhenUniqueComp(comps []*Component, comp *Component) []*Component {
// generatePuzzles transforms readPuzzles to puzzles
// it generates events and copies the rest
// if the config does not abide by the manual, a non-empty list of mistakes is returned
// the puzzles must have unique names between them
func generatePuzzles(readPuzzles []ReadPuzzle, config *WorkingConfig) ([]*Puzzle, []string) {
var result []*Puzzle
errorList := make([]string, 0)
nameList := make([]string, 0)
for _, readPuzzle := range readPuzzles {
event, newErrors := generateGeneralEvent(readPuzzle, config)
puzzle := Puzzle{
Event: event,
Hints: readPuzzle.Hints,
}
result = append(result, &puzzle)
nameList = append(nameList, event.Name)
errorList = append(errorList, newErrors...)
}
errorList = append(errorList, checkEventNamesUnique(nameList, "puzzle")...)
return result, errorList
}

// generateGeneralEvents transforms readGeneralEvents to generalEvents
// it loops through all readGeneralEvents and generates generalEvents for them
// if the config does not abide by the manual, a non-empty list of mistakes is returned
// the general events must have unique names between them
func generateGeneralEvents(readGeneralEvents []ReadGeneralEvent, config *WorkingConfig) ([]*GeneralEvent, []string) {
var result []*GeneralEvent
errorList := make([]string, 0)
nameList := make([]string, 0)
for _, readGeneralEvent := range readGeneralEvents {
newResult, newErrors := generateGeneralEvent(readGeneralEvent, config)
result = append(result, newResult)
nameList = append(nameList, newResult.Name)
errorList = append(errorList, newErrors...)
}
errorList = append(errorList, checkEventNamesUnique(nameList, "general event")...)
return result, errorList
}

// checkEventNames checks whether all puzzles or general events have unique names between their own types.
// typeOfEvent carries the name of the type to put in the error message.
func checkEventNamesUnique(nameList []string, typeOfEvent string) []string {
errorList := make([]string, 0)
seen := make(map[string]string, 0)
for _, name := range nameList {
if _, ok := seen[name]; ok {
errorList = append(errorList, fmt.Sprintf("level II - format error: a %s already exists with name %s", typeOfEvent, name))
} else {
seen[name] = name
}
}
return errorList
}

// generateGeneralEvent transforms readGeneralEvent to generalEvent
// it generates rules and copies the rest
// if the config does not abide by the manual, a non-empty list of mistakes is returned
Expand Down
14 changes: 14 additions & 0 deletions back-end/src/sciler/config/configHandler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,3 +311,17 @@ func Test_DoubleIDs(t *testing.T) {
func() { ReadFile(filename) },
"two timers with the same id is not allowed")
}

func Test_DoublePuzzleNames(t *testing.T) {
filename := "../../../resources/testing/test_doublePuzzleNames.json"
assert.Panics(t,
func() { ReadFile(filename) },
"two puzzles with the same name is not allowed")
}

func Test_DoubleGeneralEventNames(t *testing.T) {
filename := "../../../resources/testing/test_doubleGeneralEventNames.json"
assert.Panics(t,
func() { ReadFile(filename) },
"two general events with the same name is not allowed")
}
1 change: 1 addition & 0 deletions back-end/src/sciler/config/workingConfigTypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type WorkingConfig struct {
StatusMap map[string][]*Rule
RuleMap map[string]*Rule
EventRuleMap map[string]*Rule
PuzzleRuleMap map[string]*Rule
LabelMap map[string][]*Component
}

Expand Down
Loading