-
-
Notifications
You must be signed in to change notification settings - Fork 23
/
groupUtils.js
executable file
·169 lines (156 loc) · 5.31 KB
/
groupUtils.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/**Credit goes to Florian Hotze for the initial idea previously submitted
* to openhab_rules_tools. However, with the changes to JSScripting and
* ECMAScript 11, a complete rewrite was warranted including some
* simplification and generalization.
*
* The original is still available in the before-npm branch for reference.
*/
/**
* Utility that will return the passed in Group's members mapped with the
* passed in mapping function. An example mapping funciton would be:
*
* i => i.name
*
* which will return an array of the member's names. Supports an optional
* filterFunc to filter the members before generating the mapped list. A
* filter looks something like
*
* i => !i.isUninitialized
* @param {string} groupName
* @param {function(i)} mapFunc function called to map the Item
* @param {function(i)} filterFunc optional filtering function
* @returns {Array} the filtered Items with the mapping function applies
*/
const membersToMappedList = (groupName, mapFunc, filterFunc) => {
if(!filterFunc) filterFunc = i => i;
return items.getItem(groupName).members.filter(filterFunc).map(mapFunc);
}
/**
* Same as membersToMappingList except it works on descendents of the Group.
* @param {string} groupName
* @param {function(i)} mapFunc
* @param {function(i)} filterFunc
* @returns {Array}
*/
const descendentsToMappedList = (groupName, mapFunc, filterFunc) => {
if(!filterFunc) filterFunc = i => i;
return items.getItem(groupName).descendents.filter(filterFunc).map(mapFunc);
}
/**
* Calls membersToMappedList and joins the result into a separator
* separated string.
* @param {string} groupName
* @param {string} separator string to separate the list in the resultant string
* @param {function(i)} mapFunc
* @param {function(i)} filterFunc
* @returns {string} the mapped values concetanted to a single string
*/
const membersToString = (groupName, separator, mapFunc, filterFunc) => {
return membersToMappedList(groupName, mapFunc, filterFunc).join(separator);
}
/**
* Same as membersToString except it operates on the Group's descendents.
* @param {string} groupName
* @param {string} separator
* @param {function(i)} mapFunc
* @param {function(i)} filterFunc
* @returns {string}
*/
const descendentsToString = (groupName, separator, mapFunc, filterFunc) => {
return descendentsToMappedList(groupName, mapFunc, filterFunc).join(separator);
}
/**
* Optionally, filters the members of the group, maps the Items to rawState,
* and applies the reduce function. The function should take two values,
* a total and a value. It would look something like this for a sum.
*
* (total, value) => total += value
*
* @param {string} groupName
* @param {function(i)} reduceFunc
* @param {function(i)} filterFunc
* @returns A single reduced value calculated from all members of the group
*/
const reduceMemberStates = (groupName, reduceFunc, filterFunc) => {
return membersToMappedList(groupName, (m) => m.rawState, filterFunc)
.reduce(reduceFunc, null);
}
/**
* Same as reduceMemberStates except it does it for all descendents.
* @param {string} groupName
* @param {function(i)} reduceFunc
* @param {function(i)} filterFunc
* @returns A single reduced value calculated from all members of the group
*/
const reduceDecendentStates = (groupName, reduceFunc, filterFunc) => {
return descendentsToMappedList(groupName, (m) => m.rawState, filterFunc)
.reduce(reduceFunc, null);
}
/**
* Tests to see if i is an Item with a numeric state.
* @param {*} i
* @returns {boolean} true if i's rawState has a floatValue function
*/
const isNumber = (i) => {
return i.rawState.floatValue;
}
/**
* Sums the states of the passed in list of Items. Items with a non-numeric
* state are ignored.
* @param {Array<item>} list
* @returns {float} sum of the Items with numeric states.
*/
const sumList = (list) => {
return list.filter(isNumber)
.map(i => i.rawState.floatValue())
.reduce((total, value) => total += value);
}
/**
* Averages the states of the passed in list of Items. Items with a non-numeric
* state are completely ignored and not considered part of the calculation.
* @param {Array<item>} list
* @returns {float} average of the Item's with numberic states.
*/
const avgList = (list) => {
const filtered = list.filter(isNumber);
const sum = sumList(list);
return sum / filtered.length;
}
/**
* @param {Array<item>} list
* @returns {num} Minimum value of the Items with numeric states.
*/
const minList = (list) => {
return list.filter(isNumber)
.map(i => i.rawState.floatValue())
.reduce((total, value) => (total < value) ? total : value);
}
/**
* @param {Array<item>} list
* @returns {num} Maxiumum value of the Items with numeric states.
*/
const maxList = (list) => {
return list.filter(isNumber)
.map(i => i.rawState.floatValue())
.reduce((total, value) => (total > value) ? total : value);
}
/**
* @param {Array<item>} list
* @returns {num} the count of the Items that match the filterFunc
*/
const countList = (list, filterFunc) => {
return list.filter(filterFunc).length;
}
module.exports = {
membersToMappedList,
descendentsToMappedList,
membersToString,
descendentsToString,
reduceMemberStates,
reduceDecendentStates,
sumList,
avgList,
minList,
maxList,
countList
}