-
Notifications
You must be signed in to change notification settings - Fork 2
/
model.js
142 lines (130 loc) · 4.86 KB
/
model.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/**
* Model module for Schokofinder
* @model model
*/
/*
* JSON array for chocolate entries
*
* format as follows:
* [
* {
* "name": "Milka Mmmax Toffee Ganznuss", -> String
* "typ": "milch", -> String
* "geschmack": "suß", -> String
* "preis": "billig", -> String
* "ort": "deutschland", -> String
* "hersteller": "milka", -> String
* "inhalt": ["karamel"], -> Array (of strings)
* "url": "https://www.milka.de/produkte/milka-mmmax-toffee-ganznuss" -> String
* },
* ]
*/
let chocolate = require("./src/schokolade.json");
module.exports = {
findChocolate: (typ, geschmack, preis, inhalt) => {
return findChocolate(typ, geschmack, preis, inhalt);
},
/**
* returns all entries in schokolade.json
* @returns {array} an array of chocolate objects
*/
returnAllEntries: () => {
return chocolate;
}
}
/**
* searches through chocolate entries to find a suitable match according to the criteria
* @param {string} typ - the type of chocolate ("hell", "dunkel", "milch")
* @param {string} geschmack - the preferred taste ("bitter", "suß", "neutral")
* @param {string} preis - target price range ("teuer", "billig", "neutral")
* @param {array} inhalt - a list of chocolate fills
* @returns {array} an array of best matching chocolate objects
*/
function findChocolate(typ, geschmack, preis, inhalt) {
//the number of criteria that have to match
let i, requiredMatches = 4;
let matchFound = false;
let matches = [];
//continue until we find a suitable chocolate
while (!matchFound) {
//loop through the entries
for (i = 0; i < chocolate.length; i++) {
let entry = chocolate[i];
//find how well the given chocolate entry matches the criteria
let matchConfidence = compareChocolateBase([typ, geschmack, preis], entry);
if (compareChocolateFilling(inhalt, entry)) {
// console.log(`matched ${ inhalt } with ${ entry.inhalt }`);
matchConfidence++;
} else {
// console.log(`did not match ${ inhalt } with ${ entry.inhalt }`);
//prevent matching chocolate with filling
matchConfidence = 0;
}
//check if the chocolate matches well enough
if (matchConfidence >= requiredMatches) {
//push the given chocolate and stop searching
matches.push(entry);
matchFound = true;
//we don't break here because there could be more possible matches
}
}
//decrement amount of required matches and try again
// > 1 prevents the 0 pass from happening, where every chocolate would get matched
if (requiredMatches <= 0) {
//break out of loop, as no suitable chocolate exists
break;
} else {
requiredMatches = (matchFound) ? requiredMatches : requiredMatches - 1;
}
}
console.log(`Found ${ matches.length } results with an overlap of ${ requiredMatches }`);
return matches;
}
/**
* compares the base critera (type, taste, price) given to the chocolate entry
* @param {array} criteria - contains type, taste, price, and filling
* @param {object} chocolate - the chocolate entry
* @returns {int} the amount of criteria that match
*/
function compareChocolateBase(criteria, chocolate) {
let i, matches = 0;
//iterate through all criteria
for (i = 0; i < criteria.length; i++) {
//if the criteria is neutral then any result matches
if (criteria[i] == "neutral") {
matches++;
} else {
//iterate through each element of the chocolate object
for (let key in chocolate) {
//if the attribute is not the url or name
if (!(["url", "name", "inhalt"].includes(key))) {
//if we find the criterion in the attribute
if (chocolate[key].search(criteria[i]) >= 0) {
//we count this as a match and stop searching
matches++;
break;
}
}
}
}
}
return matches;
}
/**
* compares the filling(s) to the given chocolate entry
* @param {array} filling - a list of valid fillings
* @param {object} chocolate - the chocolate entry
* @returns {bool} true if the filling is in the chocolate, otherwise false
*/
function compareChocolateFilling(filling, chocolate) {
let i, match = false;
//match for filling type
for (i = 0; i < filling.length; i++) {
if (chocolate.inhalt.includes(filling[i])) {
//the chocolate entry has said filling, stop searching
match = true;
break;
}
}
return match;
}