forked from bunkat/schedule
-
Notifications
You must be signed in to change notification settings - Fork 0
/
coverage.html
342 lines (295 loc) · 145 KB
/
coverage.html
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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
make[1]: Entering directory `/home/bill/dev/schedule'
<!DOCTYPE html><html><head><title>Coverage</title><script>
headings = [];
onload = function(){
headings = document.querySelectorAll('h2');
};
onscroll = function(e){
var heading = find(window.scrollY);
if (!heading) return;
var links = document.querySelectorAll('#menu a')
, link;
for (var i = 0, len = links.length; i < len; ++i) {
link = links[i];
link.className = link.getAttribute('href') == '#' + heading.id
? 'active'
: '';
}
};
function find(y) {
var i = headings.length
, heading;
while (i--) {
heading = headings[i];
if (y >= heading.offsetTop) {
return heading;
}
}
}
</script>
<style>
body {
font: 14px/1.6 "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: 0;
color: #2C2C2C;
border-top: 2px solid #ddd;
}
#coverage {
padding: 60px;
}
h1 a {
color: inherit;
font-weight: inherit;
}
h1 a:hover {
text-decoration: none;
}
.onload h1 {
opacity: 1;
}
h2 {
width: 80%;
margin-top: 80px;
margin-bottom: 0;
font-weight: 100;
letter-spacing: 1px;
border-bottom: 1px solid #eee;
}
a {
color: #8A6343;
font-weight: bold;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
ul {
margin-top: 20px;
padding: 0 15px;
width: 100%;
}
ul li {
float: left;
width: 40%;
margin-top: 5px;
margin-right: 60px;
list-style: none;
border-bottom: 1px solid #eee;
padding: 5px 0;
font-size: 12px;
}
ul::after {
content: '.';
height: 0;
display: block;
visibility: hidden;
clear: both;
}
code {
font: 12px monaco, monospace;
}
pre {
margin: 30px;
padding: 30px;
border: 1px solid #eee;
border-bottom-color: #ddd;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
-webkit-box-shadow: inset 0 0 10px #eee;
-moz-box-shadow: inset 0 0 10px #eee;
overflow-x: auto;
}
img {
margin: 30px;
padding: 1px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
-webkit-box-shadow: 0 3px 10px #dedede, 0 1px 5px #888;
-moz-box-shadow: 0 3px 10px #dedede, 0 1px 5px #888;
max-width: 100%;
}
footer {
background: #eee;
width: 100%;
padding: 50px 0;
text-align: right;
border-top: 1px solid #ddd;
}
footer span {
display: block;
margin-right: 30px;
color: #888;
font-size: 12px;
}
#menu {
position: fixed;
font-size: 12px;
overflow-y: auto;
top: 0;
right: 0;
margin: 0;
height: 100%;
padding: 15px 0;
text-align: right;
border-left: 1px solid #eee;
-moz-box-shadow: 0 0 2px #888
, inset 5px 0 20px rgba(0,0,0,.5)
, inset 5px 0 3px rgba(0,0,0,.3);
-webkit-box-shadow: 0 0 2px #888
, inset 5px 0 20px rgba(0,0,0,.5)
, inset 5px 0 3px rgba(0,0,0,.3);
-webkit-font-smoothing: antialiased;
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGYAAABmCAMAAAAOARRQAAABelBMVEUjJSU6OzshIyM5OjoqKy02NjgsLS01NTYjJCUzNTUgISMlJSc0NTUvMDA6PDwlJyg1NjYoKis2NjYrLS02ODkpKyw0NDYrLC04ODovLzA4Ojo0NDUtLy86OjwjIyU4OTosLS82ODgtLS8hIyQvMTEnKCooKSsrKy0qLCwkJSUnKCkrLCwpKiwwMjIxMzMqLC0tLS0pKissLC00NTYwMDIwMTQpKysoKSovMDEtLzA2OTkxMzUrKywvLy8qKyszNTY5OzsqKiw6OjswMDExNDUoKiozNDUvMDIyNDY1Njg2Njk5OTozMzU0NjY4ODkiIyUiIyQ4OTkuMDEmKCowMjQwMTErLS4qKywwMTMhIiMpKiopKy0tLjAkJScxNDQvLzExNDYyNDQmKCk5OTslJig5OjskJSYxMzQrLS8gISIwMTIoKCk1NTUlJSUnJygwMDA4ODgiIiMhISI8PDw6Ojo5OTkpKSojIyQ7OzsyMjIpKSssLCw6Ozw1NjlrfLakAAAg2UlEQVR42jR6i3ea6rYvPgANIAhVXh8WvkQlioUiFlFcBtAmoiRNdzxqu9p0J7vrdK29zuPeex77nnvO/35n1r1ndHRktI0jTOacv/l7lCBK5UqVpOha/YxmWK7BC4TQFKVXrbYsnimqxuuMVlOQ0XltWjUdCwRJ1M+tC1KudOs9q6+da2adUewG0SC0SwELfHtgDds93VEuydEbl3QMWeNoYkR7b/0x1ZRobGI3mLwzAhePqTAwhg6aogjNsGy7/jwQ4rkdqe7CWLxF8k9LfMVFyRS7VJqtkrW8Vt/bkR8FZJao16ipknbC3Yw2lM7laO6HBEOadEZ2tpf65c4v8e3u7FyU6qbiNNyCuzXZ6pawgnwgmrpTT/Q7w2EZmiIJ0dzWDI7mhQ80IfRnMu2kzA5r5r1pIFoia+/d93HRYp1GV8TbrkWoU/+jdI0Ff6yGwTjT1Hn8J+8m1rKpGiYPuNiHnMtNMIv+zpsk84MYTNW1/+DpwXLvckdOCMYowVNPREe0QlM8xRHXXFhcNDzupwsSmb5pH+0t0RP2Qk+QtI7F1Qm6JRC6ZPBtPq/dq/kH+jxtCljn9TIpW6rQIgmSVyj6lPICIw4N/taka41PFUInth0je9+jO6Kt1G4/a7V2LEgG02B0pHVuCZrgltSKMuIl5SyufUv9mYuQi+mFgzbBEtFo2g+Dh4sSTrLNu8JPh00sQydpb00tqXBvqRN7Q7kqzcnIxCGnvZt/WmJacoOEO6Dcn8Qre03pOCSQxbMOXUuDNx9SxuLz4W1I18gvjViQ67zV0rxdWL8Te/TQkuo8STS41DR48W7L6YP2uWIqiUV8rd6Gbf/rnegKZeG8TpAM6afhGze9JAOxbLjsnUXEbrZ9vLYd7MT32cPF5mKKxmjy7huaoD9n62GOxni3iIJwv0IzZAZjdZkUtolCNLVfYZNaquFjGszVVf+J0vrz4CawoKdHnOzb0NMH7CDBOybfYNJ4rfeMyFNjkFYVTzMFs87rnPGXLUOeNKRVc0LnU7/UIgelzsy3CMuth0YfvnY0wsD3vODUL3eJcKqHQpm8yM3XZQWJxO6Un9iYloyyLpOwN2obHy6W6gbpcb44XmyC+mg+itAcaprGcrwZCqMj/GmtKn0zPvpTz/Cv1dw21XwP3cRupg3H3MF/S71eTKj1YrdwKdc2Mw0fRmb2sFf8lW3aU6JbIZSEPqvXvjM7G/aApyXlXeqKfMq0g/Su3rUGJPSPrtGElgknrZM3xUXqsAP6zMCNVn5u8aJnSNpJv2uru7t2jfRziW2+GuhqfldUNbPk71olwo+46ePUo1U3WKk/e5YK07F/wGRgcpODmQnIlVeHCWBE4puBi2jq28UKpqiN1/4UOrGz59TNYrrQHtd+11sG40BGD+pXdelNqGOg4NXe8W4eacJV/NS9/2Umtym6WQqveqR9xdCMElpxnbkalM4Vf9uaEcWZaKdyibEIjWKxJZPN95niCL3GiaXyssIrHxoLkqkzLCXULN46/f2h3tQJgyip+Tk9EAjJ9aJshq7t8X45aowSKspMSvPf7r9R8yxNptIaHS5ozuEm6luPDApugyNP8OaqiQ4BjaequXA54SLC83eHIY2r+CZp4409Xqw8Aa2oI7XkCrQi+in0w5AqF/kLNrcUz+qkl/lAobY1jSnx5OJNhyXIz3qfNFlXc0TKaglNwdWkWYt9QQ1Kr6W8zue21iNrdJk+N5oCr2O9nEtWKC7IS5J/zdDEYrmnAYfg6agCy+qcgz7ZofeDc4PbUWSvkshWuAc7OjiUyLkj+RAtdlwXJcjxdpkTTHDhK8lBCi8+JtvDVL1W6elmOM++YS0LuSlaP1oUvAeiW3cFnvTr8EbTz1tsSMYdGeZe40sRWu5uAfj7q+ZoKv2FNQ0p5XY1lmlcigHZqTPpabufEVrNuNPi165w3uCVQJHyJqmSJ7ZHnguqwtCmwViIJijj04ba2JNYtB+yORf5gg1/9t9iw4vUpeqiunSAbf+IBdj/b+iG2qrHvuNP0Vd/+ThVZT/lrvHYjjgDbbyxaqgHNM2uhxa1GW3UedZYhMMwM4mQhltouK+IV4NdbIQNM+8Yv311RZk9kT4tiYR4LkyFcuPpdcjuhUuFqBAWRZa11lcZ3gEBlXywsNhrt+plISZP5DlsV9l4EgY6J3yZPTUcMrgaWAT3oI79eSbGEbcJpr6BD8kyDiVt+G0/hXosQN4NFXKlfWIfsIs0BHODVok1/IGnKFHJYIquh8Xo+2+bkQNTGgWmN/fZ0Y33LSj6lr1GyV7mWIKg7ZTRZPGuhF/zjRNcQ1UPtSYgnWQxSs0yrVhwNDcdGMNSNe2JT3WuzbAM3HykyAajS3Uphf6STKEqxLas9EnmnhA/lyj9Uj+JoY7SVgVmGLl46Rm2u98sbkap2lzAdKBG4r6LgulQOSSjQv1GWdQ0jtDUK/mAaqM1Uqjpu4k3Rvfvxv7YTxLSK+wN3E5jVIzmF23uZ7hiH/sVP49D7tvoKp4S8b1LuvRlivVB/algbhcFITYVXvDpLzpDfplR2uD5V4XJFxpjmIpLc9Y5sB2TpBRix7Bme6GZIq+06v3XzNeTcA4obQIKxrnT4C2JpOqD92dbmSX8MGazly5EsZVMvSU1f4RZwyu8iQXbVdeLlZrjuTT1jrY1uk5c7iZ7RsvhhluqAkq4JpVQAg7RJFtSu+xgJ8Pv6O1j5DkLxT8mkbfyRW5DrQmG7hiDIjCgBsADbjuof6YHLGeV6a5Q1Smx9joUXPpdaaDx97A/Wq00oJkdR7ZYuQRfS533JtxO1erduqWOYIt3wh0wpbLuCNIYkwxbswbikCUu2CDCS+Q+7rgVtfRcm+SOcdKPRlZ/rE7wNVUEE39KTS5uvUKN1PUnkloPkyzhyGQ8qkouEjJ3H/VXdqG6asSRiw3ecMlBvDDt8dDhBHXMwZ2Cajzjr7/76T+IavqPYvz6r7//E/3X3+N//h/0QozbjPgPiir69P/8X3/9F/yv8b/827/++98WItPu5/Hvwd8YPf5bp/2/lX/T/+Of/0MJ/lYTa+L/Ef+d9vN/3/2T6P/+jyTzu/evf6U7vxN7B6pJkRtAF6jUr8I+P8RsP/ptGhfqFk+pQ/DgAy6NJtRYJdXmp4gK7WLqLKJ+MaKhGjOojvL+SnIWrkpy0SLHDe4QuyNzaEA15mLMCcmE8Em+4HdOihW4/ZWuppJEmzeAwcDtv7MuLc9y2V5atvxXNe3S4DUMt5/Qy2LM9kSYKiVWBuKlfp4nxTntpuW03JbIlkiRvBXmT23g1I2OYe6IizUHPIq6zm6mbfsbteKmi/sg9J+ocQBMctGFO7iljo8TPN+z3jxw4do+ZwfqoR9dkNTKHyM305GpTkfhcHexVkPVGEbUOjuo9f0UMPHBFlGEx0SLvJvVRKTwW7PSew5oPme+E42+frJa9cGt2njS3dK5kIif2eYbhuSEQXEqMVfUjhGIuin0G0/W5ezJyJQy3SpMLai4M0JUWb5u1k9tny5bd1pPwYBpQuDCXZl62xg4CdVEAtflXHs6JKmP/pH6mOl796Lgopj0o8d5kKh00hxG3OSdEE/QBo9Hgr8JJqAeLDwJohG5j/DGh61Rc/+tf22/8kEnxHNCEjo0ElvvGfESZkqmz2BDcKV1H1buSkhkdg7p1IMGs2s17nYjpblrWuE2K9WEO/hcRp5e9oOF/QBmOaDtgil+oaU6szPrdwW65fOB0KUTsVUn7LFU7J8e6cxJIl9+FHw5MQMzuQJ+4oxMH3iW/5GK+hWuG0T+gTLs+fAjdtUd58TmIUq04EeyRCYCjkldow234aIgR5bqwrtZosZ+6YEqAmDqatJ9lWasz4IquKALPtd92hGI3Z2BdzzZue+REl1Om4DIWD+RrtUTOJLI+S0jHowXXdAxsGLSd40zYNuEUlOGhrwL6c7tcOtUOvpJCP7QBQS19H+GvZn05ewjlVLz+IGKoC9TyfQjLMBNmXCuqqtTdOSukZW48B0HqgSTCBrBnlFvF4CG2Su7yFzqmJFURK3UmTT3ru050r0ptUpMilYnBJWfl2Bv6kPlUuE1kxxpdzui9AubsR2N2boVSu81OulAwBqoSr1LZ0LLYOomyZHmjqnXlP72s8LnDouEJjtodBvdHaG1jMySYO7crWd90MpCRyCG14vb5IE7Arupw/y/RcCm/Tm3zK6zYj8PYNaGldiUfkB/LHWcmf2lVM+mwyU27a0qq2tscrQ/vzBjN26DnntIrOyGizzXK35yKQdYnUABkyN4saz3WD/viF+eCcsXnIajdWYJWaYHRstIis9CS+tqnFGmz2j5uzfr3Z4prqgK4XOT/PyftvjZqIm8lhkfxJ7Ol3CJF1piYBGAG8wtAk56Drw1YwmOpcz+NdfkSpSLplRXLXHL0Rquj6YW/gabqgK7Dgr6NwtH0B/AN7XrN+MVJ6AmXmUuqmQulrNNYPmH0RoDogydOKLo/QbfYNARSQQKISRCzRXU+q9WWJFL3LZW6u34CkeG97xC0NNGaJ0bvK6SnZS3zPskr5EtuCgjMWR5o2x5BqhKmDWJPRe7JMEOyRb5uUKlHaGVtq5ivSOaSliSXp9SQm2qk8MRJh10MAp9QQ2H5t59J8rjiwSZtoIfMGjlLPVNdYl/LBR0AO6WLGDmkLkIPRE45Y9MftdAK/yNu1Hn6tzOQTesgQ+8fSzB19wO91vCnO23vOWQdwJ63SJrYjdfKFW6W281PKs2k8iT9ai1cgJ4sa3xqdvmtxR8/+D1B8AKc2u+6JftryRhMWSQtoSBgIyyQGyxcnELuAasXN12oSriU4RMz1DD6RL0TSV+om7i1Yt+jEE/jnawM8cX/UhN4nkiv/w9eALrzNhXuQfOzFL0Fi6SjF7/4Qn8rLYBoa85cvgAnkCEBP+HPbEnquVXCZsMS/yzYw2Vru60P/+nJPYKkzZFjmbykzUoEqV836T5q3fP/L383dF82tx18/AZgZczMAgyeWYKmSZIqtHL+e+O4ZRcq9VI3g/qPeCoiK4pcgEqdbS0S/Be54sbVQOuJVPNBblIghzeasNu7h/g+Sz1IdhI5lCwq1nUb3Ji4OCIcqQZqtqJ5w7rXrg/DA9IgVmEGhDgGecEwnCTHffXcXs0V3OCEVzYDKS1vp/oX+ng+6XVU86UjA6FMO2RXOOOrqY1GgPvrAk9HV/BXtCu5RuwF8qgdGDLsBcui4E33ymdBip1X8uKyhIWT8qNRDsXz+gvO9UiEC0d8RG4Tf2x8H4slljgHtCBcxHLTWOYJm5H/fCPCzOgf9qgOUxTRZ0Pc6ha5yLuLVT9ntvIa6gacE99mCovdUumTQdRP4RPsS9129eEe2uSvvGh0bV4Y3QPPhPZMqhZWSMa5R0Hc1SGO4IVOQc0FrirlibTVfKRrYkD8kz3b+X65/QkUNaZdrdl3mCap0Hf3YcCw/LiouJYNbqz88UqeDYv93yO7vvXtgl4XCyAO4ODkY6W+83+LZU//p3/zXNGGrUKClCiOnL27iJZbNWDF02XXAOeFlB7IaADoMH1Yqr+UP9biyZDEa/iJt4MDeIz6GKTdLVBfWGVtRN4fdT2rgReX8UXwF2zOrradm4J0nyTgdPnai3RvzpZvCKDUqjOwD/QA6EDaMCLewX6QWYVnHY1sx1bd8ovYnPm1ZvPH+rE20lWjOCnZ66/xDt0QAl15FjfBcZp+i9OU0RNPQ0t3x2pSNWo8eiYudwsnuP1Hq6iH1LJCJynkYsfgJ0p3pF6SoQk2l+jqE8CPk+ziGJRSKjs+W5AO185umPdkYzlK4wl7TC9NxyyDP7ZoyYVoXiuS6SjnInlLWrwz1i8bGTKXX0AVQWkSfIlglW3zRJRJ8bg5VgE6ZEnqNu9B++0GNQvDQJvFize4ESNKBJP+8vA3LM4AX5SIBq08Mob+7QMTCZx4nwP/64+4BnlZC+8WtlP/CXw6t1PwMwkJ3jhP1FiXLhDF/3I6FGUzO2DSi9ABxKyyL9paZxSEz40ZCPQToDAJu1959k7QdbVxgB4icsu2s4zsTPJhcEDo+N1GX4zSk/wriRh8AqwL62972i9HJHd1ydaLXVzvKvOfGGw5RVcUVMiKXFH4APdkQU/dc5BX0YfKTNZYXCW9mb8bc8mufoQP6BbdQmT99ZjoYfr/go4TgQX9IDgztim7wyFeGMfbNaeqj8Dzs38pgcqwSv2hbqB3oSGKWKy+sesY7p57wAHldqE6NDudk/W7s/zjrK4rZFlFvaGxnSZdHbc1y47qDN6xkoK8O3bfr2j41dlJZ71rB4dlDqapPFa8N6xBrprUdtenUCHwxKNhw1uuTBh+9uU45k4REpQABN2bAO9DSLqoIL26gNroWgup5pUMxHUNSq4Gyz47vBPvilpo5f9OYI2ddAqTqmnxXERxQJ3UK8fHbVE9HagHi3+tqNRoNsArdmAxHA5LwtQo9ZAaNKUTljnokljo2x8scqVpEEIPc01fPCdHOCg0DeWBz8D5TVAAfx8aRH5X2ZYNI3ebKDZdeJ+oBDAxmRqJ30Eh2/DaeAy5diVNMpEDmXiPDsGTzBLXy8eVDdJoIafgx/gxMyQi454QrW56nCyeELgSuNNEmYkflF+t3CZQOVRWjKhIuCclmQSlAXT3+4JGG75B4t/5hQ+ldMP4LsAW6z3XmU6IJJwpnGVnsgUZhoY1fZlwTR8wSU7xRejf2uCx9Z5trVTRRJP9KnEb134dEieil6eCOGWgboI7xsqsqM99jfJLTePjygKlH2CVxxsse9QRzTBFjD/Kjqitr/CCTBt/SJ6nLxz7cKP9pFqBpp0lN5y+adKNsZjrPuroemZauH9aTTFD3EKHW8S55XBLFQAt1jgxTQCTwxmx/JyfsZDN1RroN3VaxpSenpIX7K+ZbL8VdlQDcI4Cbzg3QJLa9yVqNxUelu+EtxLVqeekaAvSJkO6sSVqbUajxqhKshNpvZqoeApF0k/0P0ikkwUcbdwc4A1ejN7Oo0O15kG7hTMoK3hZRBCX7YYeLW0wvcXx/18n/u37yLgzBYVBUvORGli+sfRcX/74uD6P4hq+7xu54TlWJLFzT63uwUDwuEDdOjJQqx7JV+ZjaEAPi7t0MMrR4Q8Rkf18uxD6RK0RKh0hL8YU+DeL97i4pa5ZSyAfXKwZRS/8gXcxdZXm62RBDj8U3sN8x95b5PpPs/mCBKYvpaA50pN5Ct/499AFTtwQ5vgeSh+NHrKIi4NVpwM/XzRaNfJD856lPE6M21zWPguFsH7jbLVyEDfRmt4VwrhCJ5VTYmcSPfGgO5clfN+vbaDZ7sakU5+2vZ2WCDY031NxJarVytfDDVtiafcTGO2rJ/taoL3zChN2qmjxofczTOYQPPVQPh0JVtYgdUQINcSiNEEy58UdYXX1MpWUCEBx7LbcGtAm8XWRQTVOaoV3ySri4RShhs/B/0m4jX6OAwXOvcA09bNSG4czEGv/Wey6V/jbTCNTW6awXdNTcA1GsPe1E9fZdGl7R0vyoVpIdJtfC6d32NNErrvq/R+d65VG+YOwRXppXxOCYyGNSf1K3x6VxAW/vtz4EC1SgCOSPdN62sLsoIzuDfg8GwZAbquVO8HIuFP/ToVoeUB7nnwMF35a1wK1tI6fkrqFKhQdeJpwyls0pIy8AZde3/6LUUbFaYJthyUJSU/kqDXTLQElnn0Jr4B2RVghNrmNmoEn7pXIeshPguXVsvwoTdmClq49JJU3LWhHyWTrJL9bRP6VKv3tZoA/th77p5Jw++OEENvyvWy/pNeExiDUVQaXIRGh8xySZTI36yueFaSXo1uJY0RnXYgEOoWWOJHeaVuX/bGNhHsh2yinznl/++NJcE9j6fBPRcBdq9hb8awNw8U7Bl6GM7x69EDOIIbX/npZ++amlHR9L/35mE/2Ss4gb0xCcY4VyTFLRE796vHysLAamqcyO+aFQyJIDBNslbH2/MrAvZiSEIedc/cqjmv4fbda2pXbv+F5a2szSsdkm9noiNURXt8edUhGUF6fSZWd1IJaXKFwD+49R6eCXD4Bkef7j9tRtNMVgW8BhRz/Qpy1TmeYk0doyjZoJSbePOReVHgkFsCFuQJ+Lgc4BxeAsK/cOiNDRmdNw0ctYhn/nQ498dYI5znzGLoJi1rav7Cn88rL3wLePVtDK5gl77Tki3gHEsIAQ2+IKgarj7Y8W1IQzV5V9N+0TjLqbg68WfKcOmBCOj3JkwJhVIkwDhc+JorXuZEPMEh0vvH3x7iqf+VAwXgd4diZiaJD1zHL9Snx6Wfg4IugreyhabQkcir+y5XgDtdx3Avs7lkeeCBwDvZoTUCXx5QrZkcEqWfYEiEYRs/EphmRALSNGR1Iclgdr5VFoELpzF4++f35w3/j0t5ucW3n2ch4PQCLuUXupsPRR7UA5FjSKrMtPcKAZJfagO4lGE7FH3YKMjorpK0ZxAv+i2JkJhtAMWWWFej4RhPR/cJ3DxwocCvXDi4SGZU4cu+K32XndiFWgopAl+0GApcwf1XvymJcFs39jExIBO4yUjU9MExBLQYc9H+W7+IgdESPRpciT+rKZPebVtaVq+1GYO/5xTAL3HASjNTGIgMvdjWbgc7JvdE1zIFpuC0U9ESiZyzBixzxWxj4Kwh8My34q+FK3KNLtmsA1qyrmKSNQOXCPUZd+ONelBTvFoUI/CYsqa/RhtKiyMf2CgSFqEPk59Y3uqnlZ8gFpswfSYyko23yVZYxzKGxGm49Zqxg1l8oz5Ra9XaRwHkuxepmgyhm0SoNy2KlbcEqK+9QqS9PNx9Ihm9U7gsR55SSJ1FBDNnkuWKxIZ0SDpXuOGwZdoUbOMDPHP4vBAgz2VlSEJAHZGJVbYIg7l/FO5KfIVvxC8pPPxMGcNMoevFDeStt2iqztE10n2TA4dgJH76YS9HDhKHD3iCx6ieFX84BAI3QQnngh76f5ruPQVbr5qZmck/5UjDc26lfrOvUBWy0Ogl8bCoOkMOns81TnC3cuUS9KW8+9A+fe3XYZOFUPG1u5epSSmDLw0s5s2F0W30ANeo+zJkJQz9SPZgzwYpEoktofhGVfmLOAB20boCbW1QWq/NpET/hnMecw/uSyAH4NJc3ECOU4nnkK1fj3S/i5dwb3R7k00AqQQUwt7Ie1qV0aY/VQX0J8hLPy7eBNXMHYZYDNxHZ2Qh6AuXJxq+AeRec/Q+JLhZV6hpXwQEzw7bf5v9uUf2vpq3qlhmy0IIGTkwYdCfSAFmqbdo+3XvDTDjFJde0mbeQLcn2n31xaAqJ0ixO/CLsT4I4G4DoncVTgRGNBtsCcjISWT+oeXZ4Iedw/8OsJI1aPnNKLX/60VvcZb94uasRxCkqlPQ11u1Sa2hHvB80WQENxVyzjns0/PiEByyil21Te6oisk3mNCEMrhouCFO3yEZTHHOCMy9eb/4Tmi8cVf3Lf7P53SY2hX3PSN033As3ETIMLHWumWEO9JXHA2y2SIBlIPpLGG2qvNsCIlIr+B1SWAqRKm2w6Blf7U+zCSBwJrfHG5i8J5Gax/cVonMlon7aHJX/gSvucIncRP93XCqkv7D8IFKFsLiBgHqUpXhE3pYjEcV1dk/JD9zFVCfEaQIVX8Jmfz7IIofcBKQ4OaG+C3xC2veX9CD+iAFXDNaGg9eTVxvkbJRJlW4Nk9Wk13kn696jWppRDe/8pDrYMO9ZyxZ98ReKSz9kWKLLyk2zCZgAniCkLJVX3n1M9DYbomyahWiv/KixRIV9hj/oFz87I+HLznbPTjpa+D+bZQnMuRsljTpv90vQUt/pK7jCFnA30B/jtroSF2/m/gpWn1aQs5WeA6ghzF8SdqWI20fghdSeDOCSCmLgTkfaGgGDmw7nHFkRzGtag57IHS2na06I+gzEphXo1w/Zx2BM/jKL2nZoFjHggtFQjYi8nSVRSXIE58RPbBObXk7uuIL9+rs/5Zo7suJInEUxgsiZZAWS25iBtpEiZeBgDtghEoAE0sjcayNq85M4tbu/LF5h51335PsGzQ09O875+vUS89lkWMyNOFoip2PuyWyMP/iU2XIZdfCCJNDjebDoBLQdpy7QQZC7s9c0wjHJervQNDu2jWzBW5MSAJMr7bP+Iv92BkS/GGgzjEn7MF1IRKFwwzbjbS4/slGOmhx9cZrFu7HSEefojNv3r0UaKfKOWzXsq1zEugbzlMDFsacRJJI/iJlK3vtkZ+PLZIVMFlKA32wbq2Kd5T0uCLZ1CPkAfCdzkz2EYscjDcZq2AWfziN2covN4kXE1lQXPPLTNM1xx3tbiepcO/t3SWm4w87qfh99SL0ZnY+LKFPLPeXVM2mIIoVWt+9Nk0I7nY4O79iGYqxZ8RVz289an6NVdJWnSKZvJQCAuHNiVaDxPAFoH392t9wot5t0/qmU95eEWNbU2udUW5sN9JVqcYlvAIfLeYC33oUzzxZgSktsv21mA7Uly1FA5VnoJFh6N244Wmv3YJGFv/TCPryaw+ZORlpZjQdq/2DYXr3EZskfed0G61P09ipTKmlTQ1067Rg5+PAk5FlQ9e0SWbGf2B/08kqymOTMVOznsALHHNFH4LFRKl2F/NOiYFl9khNHnSu9Ak5sq26Ynl/i2fdTle29Y1ugqmR5Yj4YT9pvslFyYCbw0mNFr5rVQm1LvkG27QMq9ph3t8fmn6r6SQ4oSbr5tz+J1kIawGzDxb6VYOvvWhobDTXfBeNv3b4aNm5XUinsCGqG2q/45m3+LoCOsddFceYhRx1Tsss9PLdPfJdErFMjYd3gddjiP0+XQjcRadZP6bwNLySvunFf20Czy6JqdEW2a96KxdYdOryBv1BjbuUq2yCHeh+6sk7fGmmPi50pe/1l5TyPe5oHW9oPnhPswLyf2TFDdCyYlhwBCstv5C1HwlW7xWoGT9XZt4qVj5WryLPLLD6h/5cMLEjWzgCeAIKNsLak92aBqBsHl4AJwl2N4jfvbSkBExGimv0nFvv09uDScQbjx+w4kPQjgjlW+g9ws9VEJvI2k8N6XxVu0uIwovgTFdunG24gBtaDi+y1YLQwZ8mwbip5fVlO3k0n0AEr/ETbtu8Vjkm+nNSiEb7X/3fMjBL5A8PdgG+/FnbexbFFExmEfetXAnisEKy5z44WVPpQZjSy/jzeGn4yDRsFGqhh87QPaDBWhlo37IFbe/C0xynS91d2tP/AJoJS0sVF6iwAAAAAElFTkSuQmCC");
}
#menu::after {
display: block;
content: '';
padding-top: 80px;
}
#logo {
position: fixed;
bottom: 10px;
right: 10px;
background: rgba(255,255,255,.1);
font-size: 11px;
display: block;
width: 20px;
height: 20px;
line-height: 20px;
text-align: center;
-webkit-border-radius: 20px;
-moz-border-radius: 20px;
-webkit-box-shadow: 0 0 3px rgba(0,0,0,.2);
-moz-box-shadow: 0 0 3px rgba(0,0,0,.2);
color: inherit;
}
#menu li a {
display: block;
color: white;
padding: 0 35px 0 25px;
-webkit-transition: background 300ms;
-moz-transition: background 300ms;
}
#menu li {
position: relative;
list-style: none;
}
#menu a:hover,
#menu a.active {
text-decoration: none;
background: rgba(255,255,255,.1);
}
#menu li:hover .cov {
opacity: 1;
}
#menu li .dirname {
opacity: .60;
padding-right: 2px;
}
#menu li .basename {
opacity: 1;
}
#menu .cov {
background: rgba(0,0,0,.4);
position: absolute;
top: 0;
right: 8px;
font-size: 9px;
opacity: .6;
text-align: left;
width: 17px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
padding: 2px 3px;
text-align: center;
}
#stats:nth-child(2n) {
display: inline-block;
margin-top: 15px;
border: 1px solid #eee;
padding: 10px;
-webkit-box-shadow: inset 0 0 2px #eee;
-moz-box-shadow: inset 0 0 2px #eee;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
}
#stats div {
float: left;
padding: 0 5px;
}
#stats::after {
display: block;
content: '';
clear: both;
}
#stats .sloc::after {
content: ' SLOC';
color: #b6b6b6;
}
#stats .percentage::after {
content: ' coverage';
color: #b6b6b6;
}
#stats .hits,
#stats .misses {
display: none;
}
.high {
color: #00d4b4;
}
.medium {
color: #e87d0d;
}
.low {
color: #d4081a;
}
.terrible {
color: #d4081a;
font-weight: bold;
}
table {
width: 80%;
margin-top: 10px;
border-collapse: collapse;
border: 1px solid #cbcbcb;
color: #363636;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
}
table thead {
display: none;
}
table td.line,
table td.hits {
width: 20px;
background: #eaeaea;
text-align: center;
font-size: 11px;
padding: 0 10px;
color: #949494;
}
table td.hits {
width: 10px;
padding: 2px 5px;
color: rgba(0,0,0,.2);
background: #f0f0f0;
}
tr.miss td.line,
tr.miss td.hits {
background: #e6c3c7;
}
tr.miss td {
background: #f8d5d8;
}
td.source {
padding-left: 15px;
line-height: 15px;
white-space: pre;
font: 12px monaco, monospace;
}
code .comment { color: #ddd }
code .init { color: #2F6FAD }
code .string { color: #5890AD }
code .keyword { color: #8A6343 }
code .number { color: #2F6FAD }
</style></head><body><div id="coverage"><h1 id="overview">Coverage</h1><div id="menu"><li><a href="#overview">overview</a></li><li><span class="cov terrible">4</span><a href="#compat/indexof.js"><span class="dirname">compat/</span><span class="basename">indexof.js</span></a></li><li><span class="cov low">33</span><a href="#compat/isarray.js"><span class="dirname">compat/</span><span class="basename">isarray.js</span></a></li><li><span class="cov high">100</span><a href="#core/create.js"><span class="dirname">core/</span><span class="basename">create.js</span></a></li><li><span class="cov high">100</span><a href="#core/dependency-graph.js"><span class="dirname">core/</span><span class="basename">dependency-graph.js</span></a></li><li><span class="cov high">100</span><a href="#core/resource-manager.js"><span class="dirname">core/</span><span class="basename">resource-manager.js</span></a></li><li><span class="cov high">100</span><a href="#core/resources.js"><span class="dirname">core/</span><span class="basename">resources.js</span></a></li><li><span class="cov high">84</span><a href="#core/tasks.js"><span class="dirname">core/</span><span class="basename">tasks.js</span></a></li><li><span class="cov high">100</span><a href="#date/date.js"><span class="dirname">date/</span><span class="basename">date.js</span></a></li><li><span class="cov high">100</span><a href="#date/timezone.js"><span class="dirname">date/</span><span class="basename">timezone.js</span></a></li><li><span class="cov high">100</span><a href="#sort/sort.js"><span class="dirname">sort/</span><span class="basename">sort.js</span></a></li><li><span class="cov high">100</span><a href="#sort/tasks.js"><span class="dirname">sort/</span><span class="basename">tasks.js</span></a></li><li><span class="cov high">100</span><a href="#util/functor.js"><span class="dirname">util/</span><span class="basename">functor.js</span></a></li><li><span class="cov high">100</span><a href="#util/memoized-range-fn.js"><span class="dirname">util/</span><span class="basename">memoized-range-fn.js</span></a></li><a id="logo" href="http://visionmedia.github.com/mocha/">m</a></div><div id="stats" class="high"><div class="percentage">91%</div><div class="sloc">384</div><div class="hits">352</div><div class="misses">32</div></div><div id="files"><div class="file"><h2 id="compat/indexof.js">compat/indexof.js</h2><div id="stats" class="terrible"><div class="percentage">4%</div><div class="sloc">23</div><div class="hits">1</div><div class="misses">22</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">// indexOf compares searchElement to elements of the Array using strict</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">// equality (the same method used by the ===, or triple-equals, operator).</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source">//</td></tr><tr><td class="line">4</td><td class="hits"></td><td class="source">// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf</td></tr><tr><td class="line">5</td><td class="hits"></td><td class="source">//</td></tr><tr class="hit"><td class="line">6</td><td class="hits">1</td><td class="source">if (!Array.prototype.indexOf) {</td></tr><tr class="miss"><td class="line">7</td><td class="hits">0</td><td class="source"> Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {</td></tr><tr class="miss"><td class="line">8</td><td class="hits">0</td><td class="source"> "use strict";</td></tr><tr class="miss"><td class="line">9</td><td class="hits">0</td><td class="source"> if (this == null) {</td></tr><tr class="miss"><td class="line">10</td><td class="hits">0</td><td class="source"> throw new TypeError();</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">12</td><td class="hits">0</td><td class="source"> var t = Object(this);</td></tr><tr class="miss"><td class="line">13</td><td class="hits">0</td><td class="source"> var len = t.length >>> 0;</td></tr><tr class="miss"><td class="line">14</td><td class="hits">0</td><td class="source"> if (len === 0) {</td></tr><tr class="miss"><td class="line">15</td><td class="hits">0</td><td class="source"> return -1;</td></tr><tr><td class="line">16</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">17</td><td class="hits">0</td><td class="source"> var n = 0;</td></tr><tr class="miss"><td class="line">18</td><td class="hits">0</td><td class="source"> if (arguments.length > 1) {</td></tr><tr class="miss"><td class="line">19</td><td class="hits">0</td><td class="source"> n = Number(arguments[1]);</td></tr><tr class="miss"><td class="line">20</td><td class="hits">0</td><td class="source"> if (n != n) { // shortcut for verifying if it's NaN</td></tr><tr class="miss"><td class="line">21</td><td class="hits">0</td><td class="source"> n = 0;</td></tr><tr class="miss"><td class="line">22</td><td class="hits">0</td><td class="source"> } else if (n != 0 && n != Infinity && n != -Infinity) {</td></tr><tr class="miss"><td class="line">23</td><td class="hits">0</td><td class="source"> n = (n > 0 || -1) * Math.floor(Math.abs(n));</td></tr><tr><td class="line">24</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">25</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">26</td><td class="hits">0</td><td class="source"> if (n >= len) {</td></tr><tr class="miss"><td class="line">27</td><td class="hits">0</td><td class="source"> return -1;</td></tr><tr><td class="line">28</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">29</td><td class="hits">0</td><td class="source"> var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);</td></tr><tr class="miss"><td class="line">30</td><td class="hits">0</td><td class="source"> for (; k < len; k++) {</td></tr><tr class="miss"><td class="line">31</td><td class="hits">0</td><td class="source"> if (k in t && t[k] === searchElement) {</td></tr><tr class="miss"><td class="line">32</td><td class="hits">0</td><td class="source"> return k;</td></tr><tr><td class="line">33</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">34</td><td class="hits"></td><td class="source"> }</td></tr><tr class="miss"><td class="line">35</td><td class="hits">0</td><td class="source"> return -1;</td></tr><tr><td class="line">36</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">37</td><td class="hits"></td><td class="source">}</td></tr></tbody></table></div><div class="file"><h2 id="compat/isarray.js">compat/isarray.js</h2><div id="stats" class="low"><div class="percentage">33%</div><div class="sloc">3</div><div class="hits">1</div><div class="misses">2</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">// Returns true if an object is an array, false if it is not.</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">//</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source">// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray</td></tr><tr><td class="line">4</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">5</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">6</td><td class="hits">1</td><td class="source">if(!Array.isArray) {</td></tr><tr class="miss"><td class="line">7</td><td class="hits">0</td><td class="source"> Array.isArray = function (vArg) {</td></tr><tr class="miss"><td class="line">8</td><td class="hits">0</td><td class="source"> return Object.prototype.toString.call(vArg) === "[object Array]";</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source">}</td></tr></tbody></table></div><div class="file"><h2 id="core/create.js">core/create.js</h2><div id="stats" class="high"><div class="percentage">100%</div><div class="sloc">64</div><div class="hits">64</div><div class="misses">0</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">* Schedule create</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source">* (c) 2013 Bill, BunKat LLC.</td></tr><tr><td class="line">4</td><td class="hits"></td><td class="source">*</td></tr><tr><td class="line">5</td><td class="hits"></td><td class="source">* Creates a schedule for each task that respects the task schedules, task</td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source">* dependencies, resource schedules, project schedule, and start date provided.</td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source">*</td></tr><tr><td class="line">8</td><td class="hits"></td><td class="source">* Schedule is freely distributable under the MIT license.</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source">* For all details and documentation:</td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source">* http://github.com/bunkat/schedule</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source">*/</td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">13</td><td class="hits">1</td><td class="source">schedule.create = function(tasks, resources, sched, startDate) {</td></tr><tr><td class="line">14</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">15</td><td class="hits">22</td><td class="source"> var taskGraph = schedule.dependencyGraph(tasks),</td></tr><tr><td class="line">16</td><td class="hits"></td><td class="source"> resMgr = schedule.resourceManager(resources, startDate),</td></tr><tr><td class="line">17</td><td class="hits"></td><td class="source"> scheduledTasks = {};</td></tr><tr><td class="line">18</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">19</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">20</td><td class="hits"></td><td class="source"> * Main function, coordinates the process of creating a schedule.</td></tr><tr><td class="line">21</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">22</td><td class="hits">22</td><td class="source"> function generateSchedule() {</td></tr><tr class="hit"><td class="line">23</td><td class="hits">22</td><td class="source"> var range, failedTasks = [];</td></tr><tr><td class="line">24</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">25</td><td class="hits"></td><td class="source"> // add required resources not supplied in resources array, the project</td></tr><tr><td class="line">26</td><td class="hits"></td><td class="source"> // schedule and all task schedules to the resource manager (these will</td></tr><tr><td class="line">27</td><td class="hits"></td><td class="source"> // be treated as resources to calculate valid reservations with)</td></tr><tr class="hit"><td class="line">28</td><td class="hits">22</td><td class="source"> resMgr.addResource(taskGraph.resources, '', startDate);</td></tr><tr class="hit"><td class="line">29</td><td class="hits">22</td><td class="source"> resMgr.addResource([{id: '_proj', schedule: sched}], '', startDate);</td></tr><tr class="hit"><td class="line">30</td><td class="hits">22</td><td class="source"> resMgr.addResource(tasks, '_task', startDate);</td></tr><tr><td class="line">31</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">32</td><td class="hits">22</td><td class="source"> forwardPass(taskGraph.roots);</td></tr><tr class="hit"><td class="line">33</td><td class="hits">22</td><td class="source"> range = getSummary(tasks, failedTasks);</td></tr><tr class="hit"><td class="line">34</td><td class="hits">22</td><td class="source"> backwardPass(taskGraph.leaves, range[1]);</td></tr><tr><td class="line">35</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">36</td><td class="hits">22</td><td class="source"> return {</td></tr><tr><td class="line">37</td><td class="hits"></td><td class="source"> scheduledTasks: scheduledTasks,</td></tr><tr><td class="line">38</td><td class="hits"></td><td class="source"> failedTasks: failedTasks.length ? failedTasks : null,</td></tr><tr><td class="line">39</td><td class="hits"></td><td class="source"> success: failedTasks.length === 0,</td></tr><tr><td class="line">40</td><td class="hits"></td><td class="source"> start: range[0],</td></tr><tr><td class="line">41</td><td class="hits"></td><td class="source"> end: range[1]</td></tr><tr><td class="line">42</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">43</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">44</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">45</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">46</td><td class="hits"></td><td class="source"> * Schedules each task as their dependencies are met, tracking dependency</td></tr><tr><td class="line">47</td><td class="hits"></td><td class="source"> * end dates in the dependencies map.</td></tr><tr><td class="line">48</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">49</td><td class="hits">22</td><td class="source"> function forwardPass(roots) {</td></tr><tr class="hit"><td class="line">50</td><td class="hits">22</td><td class="source"> var readyTasks = roots.slice(0),</td></tr><tr><td class="line">51</td><td class="hits"></td><td class="source"> dependencies = {}; // holds count and earliest start date of dependencies</td></tr><tr><td class="line">52</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">53</td><td class="hits">22</td><td class="source"> for(var i = 0, len = roots.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">54</td><td class="hits">46</td><td class="source"> dependencies[roots[i]] = [0, startDate.getTime()];</td></tr><tr><td class="line">55</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">56</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">57</td><td class="hits">22</td><td class="source"> while(readyTasks.length) {</td></tr><tr class="hit"><td class="line">58</td><td class="hits">69</td><td class="source"> schedule.sort.tasks(taskGraph, readyTasks);</td></tr><tr><td class="line">59</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">60</td><td class="hits">69</td><td class="source"> var task = taskGraph.tasks[readyTasks.pop()],</td></tr><tr><td class="line">61</td><td class="hits"></td><td class="source"> start = dependencies[task.id][1],</td></tr><tr><td class="line">62</td><td class="hits"></td><td class="source"> end = forwardPassTask(task, start);</td></tr><tr><td class="line">63</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">64</td><td class="hits">69</td><td class="source"> if(end && task.requiredBy) {</td></tr><tr class="hit"><td class="line">65</td><td class="hits">20</td><td class="source"> updateDependencies(readyTasks, dependencies, task.requiredBy, end);</td></tr><tr class="hit"><td class="line">66</td><td class="hits">20</td><td class="source"> resMgr.optimize(getMinStart(dependencies)); // clean up expired exceptions</td></tr><tr><td class="line">67</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">68</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">69</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">70</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">71</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">72</td><td class="hits"></td><td class="source"> * Finds the next available time that all of a tasks constraints are met and</td></tr><tr><td class="line">73</td><td class="hits"></td><td class="source"> * makes the appropriate resource reservations. A task may be scheduled in a</td></tr><tr><td class="line">74</td><td class="hits"></td><td class="source"> * single contiguous block or multiple blocks of time.</td></tr><tr><td class="line">75</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">76</td><td class="hits">22</td><td class="source"> function forwardPassTask(task, start) {</td></tr><tr class="hit"><td class="line">77</td><td class="hits">69</td><td class="source"> var resAll = ['_proj', '_task' + task.id],</td></tr><tr><td class="line">78</td><td class="hits"></td><td class="source"> resources = task.resources ? resAll.concat(task.resources) : resAll,</td></tr><tr><td class="line">79</td><td class="hits"></td><td class="source"> duration = task.duration,</td></tr><tr><td class="line">80</td><td class="hits"></td><td class="source"> next = start,</td></tr><tr><td class="line">81</td><td class="hits"></td><td class="source"> scheduledTask = {schedule: [], duration: task.duration};</td></tr><tr><td class="line">82</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">83</td><td class="hits">69</td><td class="source"> while(duration) {</td></tr><tr class="hit"><td class="line">84</td><td class="hits">73</td><td class="source"> var r = resMgr.makeReservation(resources, next, task.minSchedule || 1, duration);</td></tr><tr class="hit"><td class="line">85</td><td class="hits">75</td><td class="source"> if(!r.success) return undefined;</td></tr><tr><td class="line">86</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">87</td><td class="hits">71</td><td class="source"> scheduledTask.earlyStart = scheduledTask.earlyStart || r.start;</td></tr><tr class="hit"><td class="line">88</td><td class="hits">71</td><td class="source"> scheduledTask.schedule.push(r);</td></tr><tr class="hit"><td class="line">89</td><td class="hits">71</td><td class="source"> duration -= r.duration;</td></tr><tr class="hit"><td class="line">90</td><td class="hits">71</td><td class="source"> next = r.end;</td></tr><tr><td class="line">91</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">92</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">93</td><td class="hits">67</td><td class="source"> scheduledTask.earlyFinish = next;</td></tr><tr class="hit"><td class="line">94</td><td class="hits">67</td><td class="source"> scheduledTasks[task.id] = scheduledTask;</td></tr><tr><td class="line">95</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">96</td><td class="hits">67</td><td class="source"> return next;</td></tr><tr><td class="line">97</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">98</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">99</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">100</td><td class="hits"></td><td class="source"> * Finds the start and end date of the schedule and adds any tasks that were</td></tr><tr><td class="line">101</td><td class="hits"></td><td class="source"> * scheduled to the failedTasks array.</td></tr><tr><td class="line">102</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">103</td><td class="hits">22</td><td class="source"> function getSummary(tasks, failedTasks) {</td></tr><tr class="hit"><td class="line">104</td><td class="hits">22</td><td class="source"> var start, end;</td></tr><tr><td class="line">105</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">106</td><td class="hits">22</td><td class="source"> for(var i = 0, len = tasks.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">107</td><td class="hits">72</td><td class="source"> var t = scheduledTasks[tasks[i].id];</td></tr><tr class="hit"><td class="line">108</td><td class="hits">72</td><td class="source"> if(t) {</td></tr><tr class="hit"><td class="line">109</td><td class="hits">67</td><td class="source"> start = !start || t.earlyStart < start ? t.earlyStart : start;</td></tr><tr class="hit"><td class="line">110</td><td class="hits">67</td><td class="source"> end = !end || t.earlyFinish > end ? t.earlyFinish : end;</td></tr><tr><td class="line">111</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">112</td><td class="hits"></td><td class="source"> else {</td></tr><tr class="hit"><td class="line">113</td><td class="hits">5</td><td class="source"> failedTasks.push(tasks[i].id);</td></tr><tr><td class="line">114</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">115</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">116</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">117</td><td class="hits">22</td><td class="source"> return [start, end];</td></tr><tr><td class="line">118</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">119</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">120</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">121</td><td class="hits"></td><td class="source"> * As tasks are scheduled, the information is tracked in the dependencies</td></tr><tr><td class="line">122</td><td class="hits"></td><td class="source"> * array. As a tasks dependencies are all met, the task is pushed onto the</td></tr><tr><td class="line">123</td><td class="hits"></td><td class="source"> * readyTasks array which means it is available to be scheduled.</td></tr><tr><td class="line">124</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">125</td><td class="hits">22</td><td class="source"> function updateDependencies(readyTasks, dependencies, tasks, end) {</td></tr><tr class="hit"><td class="line">126</td><td class="hits">20</td><td class="source"> for(var i = 0, len = tasks.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">127</td><td class="hits">34</td><td class="source"> var tid = tasks[i],</td></tr><tr><td class="line">128</td><td class="hits"></td><td class="source"> dependsOn = taskGraph.tasks[tid].dependsOn,</td></tr><tr><td class="line">129</td><td class="hits"></td><td class="source"> metDeps = dependencies[tid] || (dependencies[tid] = [0, 0]);</td></tr><tr><td class="line">130</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">131</td><td class="hits">34</td><td class="source"> metDeps[0] += 1;</td></tr><tr class="hit"><td class="line">132</td><td class="hits">34</td><td class="source"> metDeps[1] = end > metDeps[1] ? end : metDeps[1];</td></tr><tr><td class="line">133</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">134</td><td class="hits">34</td><td class="source"> if(!dependsOn || metDeps[0] >= dependsOn.length) {</td></tr><tr class="hit"><td class="line">135</td><td class="hits">23</td><td class="source"> readyTasks.push(tid);</td></tr><tr><td class="line">136</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">137</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">138</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">139</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">140</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">141</td><td class="hits"></td><td class="source"> * Finds the earliest time that any of the remaining tasks could be scheduled</td></tr><tr><td class="line">142</td><td class="hits"></td><td class="source"> * for. It is used to optimize the resource manager since nothing can be</td></tr><tr><td class="line">143</td><td class="hits"></td><td class="source"> * scheduled before this time.</td></tr><tr><td class="line">144</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">145</td><td class="hits">22</td><td class="source"> function getMinStart(dependencies) {</td></tr><tr class="hit"><td class="line">146</td><td class="hits">20</td><td class="source"> var min;</td></tr><tr class="hit"><td class="line">147</td><td class="hits">20</td><td class="source"> for(var id in dependencies) {</td></tr><tr class="hit"><td class="line">148</td><td class="hits">89</td><td class="source"> if(!min || min > dependencies[id][1]) {</td></tr><tr class="hit"><td class="line">149</td><td class="hits">20</td><td class="source"> min = dependencies[id][1];</td></tr><tr><td class="line">150</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">151</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">152</td><td class="hits">20</td><td class="source"> return min;</td></tr><tr><td class="line">153</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">154</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">155</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">156</td><td class="hits"></td><td class="source"> * Calculates when a task must be completed by before it ends up slipping</td></tr><tr><td class="line">157</td><td class="hits"></td><td class="source"> * one of its dependencies or the schedule. Tasks with zero float amount</td></tr><tr><td class="line">158</td><td class="hits"></td><td class="source"> * are in the critical path.</td></tr><tr><td class="line">159</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">160</td><td class="hits">22</td><td class="source"> function backwardPass(tasks, finishDate) {</td></tr><tr class="hit"><td class="line">161</td><td class="hits">59</td><td class="source"> for(var i = 0, len = tasks.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">162</td><td class="hits">114</td><td class="source"> var sTask = scheduledTasks[tasks[i]],</td></tr><tr><td class="line">163</td><td class="hits"></td><td class="source"> dependsOn = taskGraph.tasks[tasks[i]].dependsOn;</td></tr><tr><td class="line">164</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">165</td><td class="hits">114</td><td class="source"> if(sTask) {</td></tr><tr class="hit"><td class="line">166</td><td class="hits">112</td><td class="source"> sTask.lateFinish = finishDate;</td></tr><tr class="hit"><td class="line">167</td><td class="hits">112</td><td class="source"> sTask.floatAmt = (sTask.lateFinish - sTask.earlyFinish) / later.MIN;</td></tr><tr><td class="line">168</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">169</td><td class="hits">112</td><td class="source"> if(dependsOn) {</td></tr><tr class="hit"><td class="line">170</td><td class="hits">37</td><td class="source"> backwardPass(dependsOn, sTask.earlyStart);</td></tr><tr><td class="line">171</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">172</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">173</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">174</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">175</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">176</td><td class="hits">22</td><td class="source"> return generateSchedule();</td></tr><tr><td class="line">177</td><td class="hits"></td><td class="source">};</td></tr></tbody></table></div><div class="file"><h2 id="core/dependency-graph.js">core/dependency-graph.js</h2><div id="stats" class="high"><div class="percentage">100%</div><div class="sloc">79</div><div class="hits">79</div><div class="misses">0</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">* Dependency graph</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source">* (c) 2013 Bill, BunKat LLC.</td></tr><tr><td class="line">4</td><td class="hits"></td><td class="source">*</td></tr><tr><td class="line">5</td><td class="hits"></td><td class="source">* Generates a dependency graph from a set of tasks and finds the root nodes,</td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source">* leaf nodes, depth, and optimistic float (time between when a schedule starts</td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source">* and when it must start to prevent a schedule slip). This information is used</td></tr><tr><td class="line">8</td><td class="hits"></td><td class="source">* by the schedule generator to schedule tasks against an actual timeline.</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source">*</td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source">* Schedule is freely distributable under the MIT license.</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source">* For all details and documentation:</td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source">* http://github.com/bunkat/schedule</td></tr><tr><td class="line">13</td><td class="hits"></td><td class="source">*/</td></tr><tr><td class="line">14</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">15</td><td class="hits">1</td><td class="source">schedule.dependencyGraph = function(taskArr) {</td></tr><tr><td class="line">16</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">17</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">18</td><td class="hits"></td><td class="source"> * Starting point for creating the dependency graph, clones the tasks and</td></tr><tr><td class="line">19</td><td class="hits"></td><td class="source"> * then fills out the graph properties.</td></tr><tr><td class="line">20</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">21</td><td class="hits">33</td><td class="source"> function createDependencyGraph(tasks) {</td></tr><tr class="hit"><td class="line">22</td><td class="hits">33</td><td class="source"> var graph = {</td></tr><tr><td class="line">23</td><td class="hits"></td><td class="source"> tasks: {},</td></tr><tr><td class="line">24</td><td class="hits"></td><td class="source"> roots: [],</td></tr><tr><td class="line">25</td><td class="hits"></td><td class="source"> leaves: [],</td></tr><tr><td class="line">26</td><td class="hits"></td><td class="source"> resources: [],</td></tr><tr><td class="line">27</td><td class="hits"></td><td class="source"> depth: 0,</td></tr><tr><td class="line">28</td><td class="hits"></td><td class="source"> end : 0</td></tr><tr><td class="line">29</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">30</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">31</td><td class="hits">33</td><td class="source"> for(var i = 0, len = tasks.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">32</td><td class="hits">107</td><td class="source"> var t = tasks[i];</td></tr><tr class="hit"><td class="line">33</td><td class="hits">107</td><td class="source"> graph.tasks[t.id] = {</td></tr><tr><td class="line">34</td><td class="hits"></td><td class="source"> id: t.id,</td></tr><tr><td class="line">35</td><td class="hits"></td><td class="source"> duration: t.duration,</td></tr><tr><td class="line">36</td><td class="hits"></td><td class="source"> priority: t.priority,</td></tr><tr><td class="line">37</td><td class="hits"></td><td class="source"> schedule: t.schedule,</td></tr><tr><td class="line">38</td><td class="hits"></td><td class="source"> minSchedule: t.minSchedule,</td></tr><tr><td class="line">39</td><td class="hits"></td><td class="source"> dependsOn: t.dependsOn,</td></tr><tr><td class="line">40</td><td class="hits"></td><td class="source"> resources: t.resources</td></tr><tr><td class="line">41</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">42</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">43</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">44</td><td class="hits">33</td><td class="source"> setResources(graph);</td></tr><tr class="hit"><td class="line">45</td><td class="hits">33</td><td class="source"> setRequiredBy(graph.tasks);</td></tr><tr class="hit"><td class="line">46</td><td class="hits">33</td><td class="source"> setRootsAndLeaves(graph);</td></tr><tr><td class="line">47</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">48</td><td class="hits">33</td><td class="source"> setDepth(graph, graph.leaves, 0);</td></tr><tr class="hit"><td class="line">49</td><td class="hits">33</td><td class="source"> graph.depth += 1; // increment depth so it is 1 based</td></tr><tr><td class="line">50</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">51</td><td class="hits">33</td><td class="source"> forwardPass(graph, {}, graph.roots, 0);</td></tr><tr class="hit"><td class="line">52</td><td class="hits">33</td><td class="source"> setEnd(graph, graph.leaves);</td></tr><tr class="hit"><td class="line">53</td><td class="hits">33</td><td class="source"> backwardPass(graph, {}, graph.leaves, graph.end);</td></tr><tr><td class="line">54</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">55</td><td class="hits">33</td><td class="source"> return graph;</td></tr><tr><td class="line">56</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">57</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">58</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">59</td><td class="hits"></td><td class="source"> * Creates an array of all the unique resources that are used by the tasks.</td></tr><tr><td class="line">60</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">61</td><td class="hits">33</td><td class="source"> function setResources(graph) {</td></tr><tr class="hit"><td class="line">62</td><td class="hits">33</td><td class="source"> for(var id in graph.tasks) {</td></tr><tr class="hit"><td class="line">63</td><td class="hits">107</td><td class="source"> var task = graph.tasks[id];</td></tr><tr class="hit"><td class="line">64</td><td class="hits">107</td><td class="source"> if(!isEmpty(task.resources)) {</td></tr><tr class="hit"><td class="line">65</td><td class="hits">38</td><td class="source"> for(var i = 0, len = task.resources.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">66</td><td class="hits">40</td><td class="source"> var resId = task.resources[i];</td></tr><tr class="hit"><td class="line">67</td><td class="hits">40</td><td class="source"> if(graph.resources.indexOf(resId) === -1) {</td></tr><tr class="hit"><td class="line">68</td><td class="hits">13</td><td class="source"> graph.resources.push(resId);</td></tr><tr><td class="line">69</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">70</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">71</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">72</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">73</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">74</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">75</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">76</td><td class="hits"></td><td class="source"> * Creates the back links from child to parent based on the dependsOn property.</td></tr><tr><td class="line">77</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">78</td><td class="hits">33</td><td class="source"> function setRequiredBy(tasks) {</td></tr><tr class="hit"><td class="line">79</td><td class="hits">33</td><td class="source"> for(var id in tasks) {</td></tr><tr class="hit"><td class="line">80</td><td class="hits">107</td><td class="source"> var child = tasks[id],</td></tr><tr><td class="line">81</td><td class="hits"></td><td class="source"> dependsOn = child.dependsOn;</td></tr><tr><td class="line">82</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">83</td><td class="hits">107</td><td class="source"> if(!isEmpty(dependsOn)) {</td></tr><tr class="hit"><td class="line">84</td><td class="hits">48</td><td class="source"> for(var i = 0, len = dependsOn.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">85</td><td class="hits">63</td><td class="source"> var parent = tasks[dependsOn[i]];</td></tr><tr class="hit"><td class="line">86</td><td class="hits">63</td><td class="source"> (parent.requiredBy || (parent.requiredBy = [])).push(child.id);</td></tr><tr><td class="line">87</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">88</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">89</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">90</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">91</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">92</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">93</td><td class="hits"></td><td class="source"> * Finds the roots and leaves of the dependency graph.</td></tr><tr><td class="line">94</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">95</td><td class="hits">33</td><td class="source"> function setRootsAndLeaves(graph) {</td></tr><tr class="hit"><td class="line">96</td><td class="hits">33</td><td class="source"> for(var id in graph.tasks) {</td></tr><tr class="hit"><td class="line">97</td><td class="hits">107</td><td class="source"> var task = graph.tasks[id];</td></tr><tr><td class="line">98</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">99</td><td class="hits">107</td><td class="source"> if(isEmpty(task.dependsOn)) {</td></tr><tr class="hit"><td class="line">100</td><td class="hits">59</td><td class="source"> graph.roots.push(task.id);</td></tr><tr><td class="line">101</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">102</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">103</td><td class="hits">107</td><td class="source"> if(isEmpty(task.requiredBy)) {</td></tr><tr class="hit"><td class="line">104</td><td class="hits">66</td><td class="source"> graph.leaves.push(task.id);</td></tr><tr><td class="line">105</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">106</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">107</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">108</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">109</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">110</td><td class="hits"></td><td class="source"> * Determines the depth (maximum number of nodes that depend on the current</td></tr><tr><td class="line">111</td><td class="hits"></td><td class="source"> * node) of each node in the dependency graph.</td></tr><tr><td class="line">112</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">113</td><td class="hits">33</td><td class="source"> function setDepth(graph, tasks, depth) {</td></tr><tr class="hit"><td class="line">114</td><td class="hits">96</td><td class="source"> for(var i = 0, len = tasks.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">115</td><td class="hits">162</td><td class="source"> var task = graph.tasks[tasks[i]],</td></tr><tr><td class="line">116</td><td class="hits"></td><td class="source"> dependsOn = task.dependsOn;</td></tr><tr><td class="line">117</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">118</td><td class="hits">162</td><td class="source"> task.depth = !task.depth || depth > task.depth ? depth : task.depth;</td></tr><tr class="hit"><td class="line">119</td><td class="hits">162</td><td class="source"> graph.depth = depth > graph.depth ? depth : graph.depth;</td></tr><tr><td class="line">120</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">121</td><td class="hits">162</td><td class="source"> if(!isEmpty(dependsOn)) {</td></tr><tr class="hit"><td class="line">122</td><td class="hits">63</td><td class="source"> setDepth(graph, dependsOn, task.depth + 1);</td></tr><tr><td class="line">123</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">124</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">125</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">126</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">127</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">128</td><td class="hits"></td><td class="source"> * Generates an optimistic (assume all resources are available when needed)</td></tr><tr><td class="line">129</td><td class="hits"></td><td class="source"> * forward schedule for each node in the graph, respecting node dependencies.</td></tr><tr><td class="line">130</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">131</td><td class="hits">33</td><td class="source"> function forwardPass(graph, depEnds, tasks, start) {</td></tr><tr class="hit"><td class="line">132</td><td class="hits">71</td><td class="source"> updateDependencies(depEnds, tasks, start);</td></tr><tr class="hit"><td class="line">133</td><td class="hits">71</td><td class="source"> for(var i = 0, len = tasks.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">134</td><td class="hits">119</td><td class="source"> var tid = tasks[i],</td></tr><tr><td class="line">135</td><td class="hits"></td><td class="source"> task = graph.tasks[tid],</td></tr><tr><td class="line">136</td><td class="hits"></td><td class="source"> dependsOn = task.dependsOn,</td></tr><tr><td class="line">137</td><td class="hits"></td><td class="source"> dep = depEnds[tid];</td></tr><tr><td class="line">138</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">139</td><td class="hits">119</td><td class="source"> if(!task.earlyFinish && (isEmpty(dependsOn) || (dep && dep[0] === dependsOn.length))) {</td></tr><tr class="hit"><td class="line">140</td><td class="hits">104</td><td class="source"> task.earlyStart = dep[1];</td></tr><tr class="hit"><td class="line">141</td><td class="hits">104</td><td class="source"> task.earlyFinish = dep[1] + task.duration;</td></tr><tr><td class="line">142</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">143</td><td class="hits">104</td><td class="source"> if(!isEmpty(task.requiredBy)) {</td></tr><tr class="hit"><td class="line">144</td><td class="hits">38</td><td class="source"> forwardPass(graph, depEnds, task.requiredBy, task.earlyFinish);</td></tr><tr><td class="line">145</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">146</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">147</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">148</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">149</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">150</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">151</td><td class="hits"></td><td class="source"> * Finds the end of the optimistic forward pass schedule.</td></tr><tr><td class="line">152</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">153</td><td class="hits">33</td><td class="source"> function setEnd(graph, tasks) {</td></tr><tr class="hit"><td class="line">154</td><td class="hits">33</td><td class="source"> for(var i = 0, len = tasks.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">155</td><td class="hits">66</td><td class="source"> var finish = graph.tasks[tasks[i]].earlyFinish;</td></tr><tr class="hit"><td class="line">156</td><td class="hits">66</td><td class="source"> graph.end = finish > graph.end ? finish : graph.end;</td></tr><tr><td class="line">157</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">158</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">159</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">160</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">161</td><td class="hits"></td><td class="source"> * Generates an optimistic (assume all resources are available when needed)</td></tr><tr><td class="line">162</td><td class="hits"></td><td class="source"> * backward schedule for each node in the graph, respecting node dependencies.</td></tr><tr><td class="line">163</td><td class="hits"></td><td class="source"> * Computes the float (time between earliest finish and latest finish).</td></tr><tr><td class="line">164</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">165</td><td class="hits">33</td><td class="source"> function backwardPass(graph, depEnds, tasks, end) {</td></tr><tr class="hit"><td class="line">166</td><td class="hits">78</td><td class="source"> updateDependencies(depEnds, tasks, end, true);</td></tr><tr class="hit"><td class="line">167</td><td class="hits">78</td><td class="source"> for(var i = 0, len = tasks.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">168</td><td class="hits">125</td><td class="source"> var tid = tasks[i],</td></tr><tr><td class="line">169</td><td class="hits"></td><td class="source"> task = graph.tasks[tid],</td></tr><tr><td class="line">170</td><td class="hits"></td><td class="source"> requiredBy = task.requiredBy,</td></tr><tr><td class="line">171</td><td class="hits"></td><td class="source"> dep = depEnds[tid];</td></tr><tr><td class="line">172</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">173</td><td class="hits">125</td><td class="source"> if(isEmpty(requiredBy) || (dep && dep[0] === requiredBy.length)) {</td></tr><tr class="hit"><td class="line">174</td><td class="hits">103</td><td class="source"> task.lateStart = dep[1] - task.duration;</td></tr><tr class="hit"><td class="line">175</td><td class="hits">103</td><td class="source"> task.lateFinish = dep[1];</td></tr><tr class="hit"><td class="line">176</td><td class="hits">103</td><td class="source"> task.floatAmt = task.lateFinish - task.earlyFinish;</td></tr><tr><td class="line">177</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">178</td><td class="hits">103</td><td class="source"> if(!isEmpty(task.dependsOn)) {</td></tr><tr class="hit"><td class="line">179</td><td class="hits">45</td><td class="source"> backwardPass(graph, depEnds, task.dependsOn, task.lateStart);</td></tr><tr><td class="line">180</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">181</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">182</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">183</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">184</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">185</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">186</td><td class="hits"></td><td class="source"> * Tracks dependencies between nodes to ensure nodes are only scheduled once</td></tr><tr><td class="line">187</td><td class="hits"></td><td class="source"> * their dependencies have completed.</td></tr><tr><td class="line">188</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">189</td><td class="hits">33</td><td class="source"> function updateDependencies(deps, tasks, start, rev) {</td></tr><tr class="hit"><td class="line">190</td><td class="hits">171</td><td class="source"> var compare = rev ? function(a,b) { return b > a; } :</td></tr><tr class="hit"><td class="line">191</td><td class="hits">14</td><td class="source"> function(a,b) { return a > b; };</td></tr><tr><td class="line">192</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">193</td><td class="hits">149</td><td class="source"> for(var i = 0, len = tasks.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">194</td><td class="hits">244</td><td class="source"> var id = tasks[i];</td></tr><tr><td class="line">195</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">196</td><td class="hits">244</td><td class="source"> if(deps[id]) {</td></tr><tr class="hit"><td class="line">197</td><td class="hits">36</td><td class="source"> deps[id][0] = deps[id][0] + 1;</td></tr><tr class="hit"><td class="line">198</td><td class="hits">36</td><td class="source"> deps[id][1] = compare(start, deps[id][1]) ? start : deps[id][1];</td></tr><tr><td class="line">199</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">200</td><td class="hits"></td><td class="source"> else {</td></tr><tr class="hit"><td class="line">201</td><td class="hits">208</td><td class="source"> deps[id] = [1, start];</td></tr><tr><td class="line">202</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">203</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">204</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">205</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">206</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">207</td><td class="hits"></td><td class="source"> * Returns true if the array is undefined or empty.</td></tr><tr><td class="line">208</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">209</td><td class="hits">33</td><td class="source"> function isEmpty(arr) {</td></tr><tr class="hit"><td class="line">210</td><td class="hits">1041</td><td class="source"> return !arr || arr.length === 0;</td></tr><tr><td class="line">211</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">212</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">213</td><td class="hits">33</td><td class="source"> return createDependencyGraph(taskArr);</td></tr><tr><td class="line">214</td><td class="hits"></td><td class="source">};</td></tr></tbody></table></div><div class="file"><h2 id="core/resource-manager.js">core/resource-manager.js</h2><div id="stats" class="high"><div class="percentage">100%</div><div class="sloc">116</div><div class="hits">116</div><div class="misses">0</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">* Resource manager</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source">* (c) 2013 Bill, BunKat LLC.</td></tr><tr><td class="line">4</td><td class="hits"></td><td class="source">*</td></tr><tr><td class="line">5</td><td class="hits"></td><td class="source">* Manages all of the resources and schedule constraints (project schedule,</td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source">* task schedule, and resource schedules) and reserves resources as needed. Finds</td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source">* the earliest time that a set of resources can be reserved.</td></tr><tr><td class="line">8</td><td class="hits"></td><td class="source">*</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source">* Schedule is freely distributable under the MIT license.</td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source">* For all details and documentation:</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source">* http://github.com/bunkat/schedule</td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source">*/</td></tr><tr><td class="line">13</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">14</td><td class="hits">1</td><td class="source">schedule.resourceManager = function(resourceDefinitions, startDate) {</td></tr><tr><td class="line">15</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">16</td><td class="hits">36</td><td class="source"> var defaultSched = {schedules: [{fd_a: [startDate.getTime()]}]},</td></tr><tr><td class="line">17</td><td class="hits"></td><td class="source"> rMap = buildResourceMap(resourceDefinitions, startDate);</td></tr><tr><td class="line">18</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">19</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">20</td><td class="hits"></td><td class="source"> * Creates a map from the resource definitions that contains the schedule</td></tr><tr><td class="line">21</td><td class="hits"></td><td class="source"> * information for each of the resources (specifically when the resource</td></tr><tr><td class="line">22</td><td class="hits"></td><td class="source"> * will be next available and how to calculate future availability).</td></tr><tr><td class="line">23</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">24</td><td class="hits">36</td><td class="source"> function buildResourceMap(resourceDefinitions, start) {</td></tr><tr class="hit"><td class="line">25</td><td class="hits">36</td><td class="source"> var map = {};</td></tr><tr class="hit"><td class="line">26</td><td class="hits">36</td><td class="source"> if(resourceDefinitions) {</td></tr><tr class="hit"><td class="line">27</td><td class="hits">35</td><td class="source"> for(var i = 0, len = resourceDefinitions.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">28</td><td class="hits">90</td><td class="source"> addResourceToMap(map, resourceDefinitions[i], start);</td></tr><tr><td class="line">29</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">30</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">31</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">32</td><td class="hits">36</td><td class="source"> return map;</td></tr><tr><td class="line">33</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">34</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">35</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">36</td><td class="hits"></td><td class="source"> * Adds a resource to the resource map.</td></tr><tr><td class="line">37</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">38</td><td class="hits">36</td><td class="source"> function addResourceToMap(map, def, start) {</td></tr><tr class="hit"><td class="line">39</td><td class="hits">188</td><td class="source"> var sched = JSON.parse(JSON.stringify(def.schedule || defaultSched)),</td></tr><tr><td class="line">40</td><td class="hits"></td><td class="source"> nextFn = schedule.memoizedRangeFn(later.schedule(sched).nextRange);</td></tr><tr><td class="line">41</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">42</td><td class="hits">188</td><td class="source"> map[def.id] = { schedule: sched, next: nextFn, nextAvail: nextFn(start) };</td></tr><tr><td class="line">43</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">44</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">45</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">46</td><td class="hits"></td><td class="source"> * Attempts to find the next time that all resources are available, starting</td></tr><tr><td class="line">47</td><td class="hits"></td><td class="source"> * from the start time, with a duration of at least min minutes but no more</td></tr><tr><td class="line">48</td><td class="hits"></td><td class="source"> * than max minutes.</td></tr><tr><td class="line">49</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">50</td><td class="hits">36</td><td class="source"> function getReservation(resources, start, min, max) {</td></tr><tr class="hit"><td class="line">51</td><td class="hits">92</td><td class="source"> var reservation, schedules = [], delays = {};</td></tr><tr class="hit"><td class="line">52</td><td class="hits">92</td><td class="source"> maxTries = 50;</td></tr><tr><td class="line">53</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">54</td><td class="hits">92</td><td class="source"> initRanges(resources, start, schedules, delays);</td></tr><tr class="hit"><td class="line">55</td><td class="hits">92</td><td class="source"> while(!(reservation = tryReservation(schedules, min, max)).success && --maxTries) {</td></tr><tr class="hit"><td class="line">56</td><td class="hits">199</td><td class="source"> updateRanges(schedules, nextValidStart(schedules), delays);</td></tr><tr><td class="line">57</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">58</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">59</td><td class="hits">92</td><td class="source"> reservation.delays = delays;</td></tr><tr class="hit"><td class="line">60</td><td class="hits">92</td><td class="source"> return reservation;</td></tr><tr><td class="line">61</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">62</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">63</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">64</td><td class="hits"></td><td class="source"> * Initializes the resource schedule availablity based on the start date</td></tr><tr><td class="line">65</td><td class="hits"></td><td class="source"> * provided. Resources that were not immediately available are captured in</td></tr><tr><td class="line">66</td><td class="hits"></td><td class="source"> * the delays array to be reported with the reservation.</td></tr><tr><td class="line">67</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">68</td><td class="hits">36</td><td class="source"> function initRanges(resources, start, ranges, delays) {</td></tr><tr class="hit"><td class="line">69</td><td class="hits">115</td><td class="source"> for(var i = 0, len = resources.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">70</td><td class="hits">282</td><td class="source"> var resId = resources[i];</td></tr><tr><td class="line">71</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">72</td><td class="hits"></td><td class="source"> // handles nested resources (OR)</td></tr><tr class="hit"><td class="line">73</td><td class="hits">282</td><td class="source"> if(Array.isArray(resId)) {</td></tr><tr class="hit"><td class="line">74</td><td class="hits">23</td><td class="source"> var subRanges = [], subDelays = {};</td></tr><tr class="hit"><td class="line">75</td><td class="hits">23</td><td class="source"> initRanges(resId, start, subRanges, subDelays);</td></tr><tr><td class="line">76</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">77</td><td class="hits">23</td><td class="source"> var longDelay = getLongestDelay(subDelays);</td></tr><tr class="hit"><td class="line">78</td><td class="hits">23</td><td class="source"> if(longDelay) {</td></tr><tr class="hit"><td class="line">79</td><td class="hits">21</td><td class="source"> delays[longDelay] = subDelays[longDelay];</td></tr><tr><td class="line">80</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">81</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">82</td><td class="hits">23</td><td class="source"> var schedule = {subRanges: subRanges};</td></tr><tr class="hit"><td class="line">83</td><td class="hits">23</td><td class="source"> setEarliestSubRange(schedule);</td></tr><tr class="hit"><td class="line">84</td><td class="hits">23</td><td class="source"> ranges.push(schedule);</td></tr><tr><td class="line">85</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">86</td><td class="hits"></td><td class="source"> else {</td></tr><tr class="hit"><td class="line">87</td><td class="hits">259</td><td class="source"> var res = rMap[resId],</td></tr><tr><td class="line">88</td><td class="hits"></td><td class="source"> range = res.nextAvail[0] >= start ? res.nextAvail :</td></tr><tr><td class="line">89</td><td class="hits"></td><td class="source"> res.next(start);</td></tr><tr><td class="line">90</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">91</td><td class="hits">259</td><td class="source"> if(range[0] > start && resId !== '_proj') {</td></tr><tr class="hit"><td class="line">92</td><td class="hits">89</td><td class="source"> delays[resId] = { needed: start, available: range[0] };</td></tr><tr><td class="line">93</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">94</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">95</td><td class="hits">259</td><td class="source"> ranges.push({id: resId, range: range});</td></tr><tr><td class="line">96</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">97</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">98</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">99</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">100</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">101</td><td class="hits"></td><td class="source"> * Determines if the current schedules overlap for at least min minutes. If</td></tr><tr><td class="line">102</td><td class="hits"></td><td class="source"> * they do, a reservation is created, otherwise a failure is reported.</td></tr><tr><td class="line">103</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">104</td><td class="hits">36</td><td class="source"> function tryReservation(schedules, min,max) {</td></tr><tr class="hit"><td class="line">105</td><td class="hits">291</td><td class="source"> var reservation = {success: false},</td></tr><tr><td class="line">106</td><td class="hits"></td><td class="source"> resources = [], start, end;</td></tr><tr><td class="line">107</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">108</td><td class="hits">291</td><td class="source"> for(var i = 0, len = schedules.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">109</td><td class="hits">733</td><td class="source"> var schedule = schedules[i],</td></tr><tr><td class="line">110</td><td class="hits"></td><td class="source"> range = schedule.range;</td></tr><tr><td class="line">111</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">112</td><td class="hits">733</td><td class="source"> if(!isInternal(schedule)) {</td></tr><tr class="hit"><td class="line">113</td><td class="hits">239</td><td class="source"> resources.push(schedule.id);</td></tr><tr><td class="line">114</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">115</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">116</td><td class="hits">733</td><td class="source"> start = !start || range[0] > start ? range[0] : start;</td></tr><tr class="hit"><td class="line">117</td><td class="hits">733</td><td class="source"> end = !end || range[1] < end ? range[1] : end;</td></tr><tr><td class="line">118</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">119</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">120</td><td class="hits">291</td><td class="source"> var duration = (end - start) / later.MIN;</td></tr><tr class="hit"><td class="line">121</td><td class="hits">291</td><td class="source"> if(duration >= min) {</td></tr><tr class="hit"><td class="line">122</td><td class="hits">89</td><td class="source"> duration = max && duration > max ? max : duration;</td></tr><tr class="hit"><td class="line">123</td><td class="hits">89</td><td class="source"> reservation = createReservation(resources, start, duration);</td></tr><tr><td class="line">124</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">125</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">126</td><td class="hits">291</td><td class="source"> return reservation;</td></tr><tr><td class="line">127</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">128</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">129</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">130</td><td class="hits"></td><td class="source"> * Generates a new reservation object and reserves the associated resources.</td></tr><tr><td class="line">131</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">132</td><td class="hits">36</td><td class="source"> function createReservation(resources, start, duration) {</td></tr><tr class="hit"><td class="line">133</td><td class="hits">89</td><td class="source"> var end = start + (duration * later.MIN),</td></tr><tr><td class="line">134</td><td class="hits"></td><td class="source"> reservation = {</td></tr><tr><td class="line">135</td><td class="hits"></td><td class="source"> resources: resources,</td></tr><tr><td class="line">136</td><td class="hits"></td><td class="source"> start: start,</td></tr><tr><td class="line">137</td><td class="hits"></td><td class="source"> end: end,</td></tr><tr><td class="line">138</td><td class="hits"></td><td class="source"> duration: duration,</td></tr><tr><td class="line">139</td><td class="hits"></td><td class="source"> success: true</td></tr><tr><td class="line">140</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">141</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">142</td><td class="hits">89</td><td class="source"> applyReservation(resources, start, end);</td></tr><tr class="hit"><td class="line">143</td><td class="hits">89</td><td class="source"> return reservation;</td></tr><tr><td class="line">144</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">145</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">146</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">147</td><td class="hits"></td><td class="source"> * Updates ranges after a failed reservation attempt. Resources that were not</td></tr><tr><td class="line">148</td><td class="hits"></td><td class="source"> * immediately available are captured in the delays array to be reported with</td></tr><tr><td class="line">149</td><td class="hits"></td><td class="source"> * the reservation.</td></tr><tr><td class="line">150</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">151</td><td class="hits">36</td><td class="source"> function updateRanges(resources, start, delays) {</td></tr><tr class="hit"><td class="line">152</td><td class="hits">206</td><td class="source"> for(var i = 0, len = resources.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">153</td><td class="hits">511</td><td class="source"> var res = resources[i];</td></tr><tr class="hit"><td class="line">154</td><td class="hits">789</td><td class="source"> if(res.range[1] > start) continue;</td></tr><tr><td class="line">155</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">156</td><td class="hits">233</td><td class="source"> if(res.subRanges) {</td></tr><tr class="hit"><td class="line">157</td><td class="hits">7</td><td class="source"> updateRanges(res.subRanges, start, {});</td></tr><tr class="hit"><td class="line">158</td><td class="hits">7</td><td class="source"> setEarliestSubRange(res);</td></tr><tr><td class="line">159</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">160</td><td class="hits"></td><td class="source"> else {</td></tr><tr class="hit"><td class="line">161</td><td class="hits">226</td><td class="source"> res.range = rMap[res.id].next(start);</td></tr><tr><td class="line">162</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">163</td><td class="hits">226</td><td class="source"> if(res.id !== '_proj' && !delays[res.id]) {</td></tr><tr class="hit"><td class="line">164</td><td class="hits">15</td><td class="source"> delays[res.id] = { needed: start, available: res.range[0] };</td></tr><tr><td class="line">165</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">166</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">167</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">168</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">169</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">170</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">171</td><td class="hits"></td><td class="source"> * Applies a schedule reservation (by adding schedule exceptions) to any</td></tr><tr><td class="line">172</td><td class="hits"></td><td class="source"> * reservable resources that are indicated.</td></tr><tr><td class="line">173</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">174</td><td class="hits">36</td><td class="source"> function applyReservation(resources, start, end) {</td></tr><tr class="hit"><td class="line">175</td><td class="hits">89</td><td class="source"> for(var i = 0, len = resources.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">176</td><td class="hits">69</td><td class="source"> var res = rMap[resources[i]];</td></tr><tr><td class="line">177</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">178</td><td class="hits"></td><td class="source"> // skip if this resource should not be reserved for single use</td></tr><tr class="hit"><td class="line">179</td><td class="hits">69</td><td class="source"> if(res.isNotReservable) continue;</td></tr><tr><td class="line">180</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">181</td><td class="hits">69</td><td class="source"> if(start !== res.nextAvail[0]) {</td></tr><tr class="hit"><td class="line">182</td><td class="hits">48</td><td class="source"> if(!res.schedule.exceptions) res.schedule.exceptions = [];</td></tr><tr class="hit"><td class="line">183</td><td class="hits">38</td><td class="source"> res.schedule.exceptions.push({fd_a: [start], fd_b: [end] });</td></tr><tr class="hit"><td class="line">184</td><td class="hits">38</td><td class="source"> res.next = schedule.memoizedRangeFn(later.schedule(res.schedule).nextRange);</td></tr><tr class="hit"><td class="line">185</td><td class="hits">38</td><td class="source"> end = res.nextAvail[0];</td></tr><tr><td class="line">186</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">187</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">188</td><td class="hits">69</td><td class="source"> res.nextAvail = res.next(end);</td></tr><tr><td class="line">189</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">190</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">191</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">192</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">193</td><td class="hits"></td><td class="source"> * Determines the earliest time that a schedule goes invalid which is the</td></tr><tr><td class="line">194</td><td class="hits"></td><td class="source"> * time that should be used to update resource ranges from.</td></tr><tr><td class="line">195</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">196</td><td class="hits">36</td><td class="source"> function nextValidStart(schedules) {</td></tr><tr class="hit"><td class="line">197</td><td class="hits">199</td><td class="source"> var latest;</td></tr><tr class="hit"><td class="line">198</td><td class="hits">199</td><td class="source"> for(var i = 0, len = schedules.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">199</td><td class="hits">497</td><td class="source"> var end = schedules[i].range[1];</td></tr><tr class="hit"><td class="line">200</td><td class="hits">497</td><td class="source"> latest = !latest || end < latest ? end : latest;</td></tr><tr><td class="line">201</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">202</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">203</td><td class="hits">199</td><td class="source"> return latest;</td></tr><tr><td class="line">204</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">205</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">206</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">207</td><td class="hits"></td><td class="source"> * Resources that are OR'd together (using a nested array) are treated as a</td></tr><tr><td class="line">208</td><td class="hits"></td><td class="source"> * single resource with sub resources. This function determines the resource</td></tr><tr><td class="line">209</td><td class="hits"></td><td class="source"> * that has the earliest start date which is then used for future calculations.</td></tr><tr><td class="line">210</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">211</td><td class="hits">36</td><td class="source"> function setEarliestSubRange(schedule) {</td></tr><tr class="hit"><td class="line">212</td><td class="hits">30</td><td class="source"> var minId, minRange;</td></tr><tr class="hit"><td class="line">213</td><td class="hits">30</td><td class="source"> for(var i = 0, len = schedule.subRanges.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">214</td><td class="hits">60</td><td class="source"> var sub = schedule.subRanges[i];</td></tr><tr><td class="line">215</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">216</td><td class="hits">60</td><td class="source"> if(!minId || (sub.range[0] < minRange[0])) {</td></tr><tr class="hit"><td class="line">217</td><td class="hits">40</td><td class="source"> minId = sub.id;</td></tr><tr class="hit"><td class="line">218</td><td class="hits">40</td><td class="source"> minRange = sub.range;</td></tr><tr><td class="line">219</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">220</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">221</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">222</td><td class="hits">30</td><td class="source"> schedule.id = minId;</td></tr><tr class="hit"><td class="line">223</td><td class="hits">30</td><td class="source"> schedule.range = minRange;</td></tr><tr><td class="line">224</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">225</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">226</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">227</td><td class="hits"></td><td class="source"> * Determines the longest delay amongst a set of delays. Used to determine</td></tr><tr><td class="line">228</td><td class="hits"></td><td class="source"> * which resource to report for resources that are OR'd together.</td></tr><tr><td class="line">229</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">230</td><td class="hits">36</td><td class="source"> function getLongestDelay(delays) {</td></tr><tr class="hit"><td class="line">231</td><td class="hits">23</td><td class="source"> var latest, lid;</td></tr><tr class="hit"><td class="line">232</td><td class="hits">23</td><td class="source"> for(var id in delays) {</td></tr><tr class="hit"><td class="line">233</td><td class="hits">40</td><td class="source"> var available = delays[id].available;</td></tr><tr class="hit"><td class="line">234</td><td class="hits">40</td><td class="source"> if(!latest || available < latest) {</td></tr><tr class="hit"><td class="line">235</td><td class="hits">27</td><td class="source"> latest = available;</td></tr><tr class="hit"><td class="line">236</td><td class="hits">27</td><td class="source"> lid = id;</td></tr><tr><td class="line">237</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">238</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">239</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">240</td><td class="hits">23</td><td class="source"> return lid;</td></tr><tr><td class="line">241</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">242</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">243</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">244</td><td class="hits"></td><td class="source"> * Returns true if resource provided is an internal (not user specified)</td></tr><tr><td class="line">245</td><td class="hits"></td><td class="source"> * resource.</td></tr><tr><td class="line">246</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">247</td><td class="hits">36</td><td class="source"> function isInternal(resource) {</td></tr><tr class="hit"><td class="line">248</td><td class="hits">733</td><td class="source"> return resource.id[0] === '_';</td></tr><tr><td class="line">249</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">250</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">251</td><td class="hits">36</td><td class="source"> return {</td></tr><tr><td class="line">252</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">253</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">254</td><td class="hits"></td><td class="source"> * Returns the current resource schedule state for the specified resoruce id.</td></tr><tr><td class="line">255</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">256</td><td class="hits"></td><td class="source"> getResource: function(id) {</td></tr><tr class="hit"><td class="line">257</td><td class="hits">4</td><td class="source"> return rMap[id];</td></tr><tr><td class="line">258</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">259</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">260</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">261</td><td class="hits"></td><td class="source"> * Adds a new resource to the resource map if a resource doesn't already exist</td></tr><tr><td class="line">262</td><td class="hits"></td><td class="source"> * with that id. Expects resources to be passed in as an array and will</td></tr><tr><td class="line">263</td><td class="hits"></td><td class="source"> * prefix each resource with the prefix specified.</td></tr><tr><td class="line">264</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">265</td><td class="hits"></td><td class="source"> addResource: function(arr, prefix, start) {</td></tr><tr class="hit"><td class="line">266</td><td class="hits">66</td><td class="source"> for(var i = 0, len = arr.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">267</td><td class="hits">107</td><td class="source"> var def = typeof arr[i] !== 'object' ?</td></tr><tr><td class="line">268</td><td class="hits"></td><td class="source"> { id: prefix + arr[i] } :</td></tr><tr><td class="line">269</td><td class="hits"></td><td class="source"> { id: prefix + arr[i].id, schedule: arr[i].schedule, isNotReservable: arr[i].isNotReservable };</td></tr><tr><td class="line">270</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">271</td><td class="hits">107</td><td class="source"> if(!rMap[def.id]) {</td></tr><tr class="hit"><td class="line">272</td><td class="hits">98</td><td class="source"> addResourceToMap(rMap, def, start);</td></tr><tr><td class="line">273</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">274</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">275</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">276</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">277</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">278</td><td class="hits"></td><td class="source"> * Attempts to reserve the set of resources at the earliest possible time from</td></tr><tr><td class="line">279</td><td class="hits"></td><td class="source"> * start time provide with a duration of at least min and no more than max</td></tr><tr><td class="line">280</td><td class="hits"></td><td class="source"> * minutes.</td></tr><tr><td class="line">281</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">282</td><td class="hits"></td><td class="source"> makeReservation: function(resources, start, min, max) {</td></tr><tr class="hit"><td class="line">283</td><td class="hits">92</td><td class="source"> start = start ? new Date(start) : new Date();</td></tr><tr class="hit"><td class="line">284</td><td class="hits">92</td><td class="source"> return getReservation(resources, start.getTime(), min || 1, max);</td></tr><tr><td class="line">285</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">286</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">287</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">288</td><td class="hits"></td><td class="source"> * Optimizes the resource schedules by eliminating schedule reservations that</td></tr><tr><td class="line">289</td><td class="hits"></td><td class="source"> * occur before the start date provided (i.e. ones that can never occur</td></tr><tr><td class="line">290</td><td class="hits"></td><td class="source"> * again).</td></tr><tr><td class="line">291</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">292</td><td class="hits"></td><td class="source"> optimize: function(start) {</td></tr><tr class="hit"><td class="line">293</td><td class="hits">23</td><td class="source"> for(var id in rMap) {</td></tr><tr class="hit"><td class="line">294</td><td class="hits">174</td><td class="source"> var res = rMap[id];</td></tr><tr><td class="line">295</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">296</td><td class="hits">174</td><td class="source"> if(res.schedule.exceptions) {</td></tr><tr class="hit"><td class="line">297</td><td class="hits">28</td><td class="source"> var curExceptions = res.schedule.exceptions;</td></tr><tr class="hit"><td class="line">298</td><td class="hits">28</td><td class="source"> res.schedule.exceptions = [];</td></tr><tr><td class="line">299</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">300</td><td class="hits">28</td><td class="source"> for(var i = 0, len = curExceptions.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">301</td><td class="hits">33</td><td class="source"> if(!curExceptions[i].fd_b || curExceptions[i].fd_b > start) {</td></tr><tr class="hit"><td class="line">302</td><td class="hits">26</td><td class="source"> res.schedule.exceptions.push(curExceptions[i]);</td></tr><tr><td class="line">303</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">304</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">305</td><td class="hits">28</td><td class="source"> res.next = schedule.memoizedRangeFn(later.schedule(res.schedule).nextRange);</td></tr><tr><td class="line">306</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">307</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">308</td><td class="hits">174</td><td class="source"> if(res.nextAvail[0] < start) {</td></tr><tr class="hit"><td class="line">309</td><td class="hits">18</td><td class="source"> res.nextAvail = res.next(start);</td></tr><tr><td class="line">310</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">311</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">312</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">313</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">314</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">315</td><td class="hits"></td><td class="source">};</td></tr></tbody></table></div><div class="file"><h2 id="core/resources.js">core/resources.js</h2><div id="stats" class="high"><div class="percentage">100%</div><div class="sloc">27</div><div class="hits">27</div><div class="misses">0</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">* Resources</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source">* (c) 2013 Bill, BunKat LLC.</td></tr><tr><td class="line">4</td><td class="hits"></td><td class="source">*</td></tr><tr><td class="line">5</td><td class="hits"></td><td class="source">* Takes an array of objects and generates an array of valid schedule resources</td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source">* objects.</td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source">*</td></tr><tr><td class="line">8</td><td class="hits"></td><td class="source">* Schedule is freely distributable under the MIT license.</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source">* For all details and documentation:</td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source">* http://github.com/bunkat/schedule</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source">*/</td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">13</td><td class="hits">1</td><td class="source">schedule.resources = function() {</td></tr><tr class="hit"><td class="line">14</td><td class="hits">9</td><td class="source"> var id = resourcesId,</td></tr><tr><td class="line">15</td><td class="hits"></td><td class="source"> sched = resourcesSched,</td></tr><tr><td class="line">16</td><td class="hits"></td><td class="source"> isNotReservable = resourcesIsNotReservable;</td></tr><tr><td class="line">17</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">18</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">19</td><td class="hits"></td><td class="source"> * Takes an array of objects and returns an array of schedule resource objects.</td></tr><tr><td class="line">20</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">21</td><td class="hits">9</td><td class="source"> function resources(data) {</td></tr><tr class="hit"><td class="line">22</td><td class="hits">6</td><td class="source"> var items = [],</td></tr><tr><td class="line">23</td><td class="hits"></td><td class="source"> fid = schedule.functor(id),</td></tr><tr><td class="line">24</td><td class="hits"></td><td class="source"> fsched = schedule.functor(sched),</td></tr><tr><td class="line">25</td><td class="hits"></td><td class="source"> freserve = schedule.functor(isNotReservable);</td></tr><tr><td class="line">26</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">27</td><td class="hits">6</td><td class="source"> for(var i = 0, len = data.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">28</td><td class="hits">16</td><td class="source"> var resource = data[i],</td></tr><tr><td class="line">29</td><td class="hits"></td><td class="source"> rId = fid.call(this, resource, i),</td></tr><tr><td class="line">30</td><td class="hits"></td><td class="source"> rSched = fsched.call(this, resource, i),</td></tr><tr><td class="line">31</td><td class="hits"></td><td class="source"> rReserve = freserve.call(this, resource, i);</td></tr><tr><td class="line">32</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">33</td><td class="hits">16</td><td class="source"> items.push({id: rId, schedule: rSched, isNotReservable: rReserve});</td></tr><tr><td class="line">34</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">35</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">36</td><td class="hits">6</td><td class="source"> return items;</td></tr><tr><td class="line">37</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">38</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">39</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">40</td><td class="hits"></td><td class="source"> * The function or value that should be used to generate the resource id. Sets the</td></tr><tr><td class="line">41</td><td class="hits"></td><td class="source"> * value to the argument passed in, returns current value if no arguments are</td></tr><tr><td class="line">42</td><td class="hits"></td><td class="source"> * passed in.</td></tr><tr><td class="line">43</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">44</td><td class="hits">9</td><td class="source"> resources.id = function(_) {</td></tr><tr class="hit"><td class="line">45</td><td class="hits">3</td><td class="source"> if (!arguments.length) return id;</td></tr><tr class="hit"><td class="line">46</td><td class="hits">3</td><td class="source"> id = _;</td></tr><tr class="hit"><td class="line">47</td><td class="hits">3</td><td class="source"> return resources;</td></tr><tr><td class="line">48</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">49</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">50</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">51</td><td class="hits"></td><td class="source"> * The function or value that should be used to generate the resource schedule. The</td></tr><tr><td class="line">52</td><td class="hits"></td><td class="source"> * schedule must be a valid Later.js schedule. Sets the value to the argument</td></tr><tr><td class="line">53</td><td class="hits"></td><td class="source"> * passed in, returns current value if no arguments are passed in.</td></tr><tr><td class="line">54</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">55</td><td class="hits">9</td><td class="source"> resources.schedule = function(_) {</td></tr><tr class="hit"><td class="line">56</td><td class="hits">3</td><td class="source"> if (!arguments.length) return sched;</td></tr><tr class="hit"><td class="line">57</td><td class="hits">3</td><td class="source"> sched = _;</td></tr><tr class="hit"><td class="line">58</td><td class="hits">3</td><td class="source"> return resources;</td></tr><tr><td class="line">59</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">60</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">61</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">62</td><td class="hits"></td><td class="source"> * The function or value that should be used to generate the resource is not</td></tr><tr><td class="line">63</td><td class="hits"></td><td class="source"> * reservable value. Sets the value to the argument passed in, returns current</td></tr><tr><td class="line">64</td><td class="hits"></td><td class="source"> * value if no arguments are passed in.</td></tr><tr><td class="line">65</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">66</td><td class="hits">9</td><td class="source"> resources.isNotReservable = function(_) {</td></tr><tr class="hit"><td class="line">67</td><td class="hits">1</td><td class="source"> if (!arguments.length) return isNotReservable;</td></tr><tr class="hit"><td class="line">68</td><td class="hits">1</td><td class="source"> isNotReservable = _;</td></tr><tr class="hit"><td class="line">69</td><td class="hits">1</td><td class="source"> return resources;</td></tr><tr><td class="line">70</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">71</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">72</td><td class="hits">9</td><td class="source"> return resources;</td></tr><tr><td class="line">73</td><td class="hits"></td><td class="source">};</td></tr><tr><td class="line">74</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">75</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">76</td><td class="hits"></td><td class="source">* The default id function.</td></tr><tr><td class="line">77</td><td class="hits"></td><td class="source">*/</td></tr><tr class="hit"><td class="line">78</td><td class="hits">1</td><td class="source">function resourcesId(d) {</td></tr><tr class="hit"><td class="line">79</td><td class="hits">9</td><td class="source"> return d.id;</td></tr><tr><td class="line">80</td><td class="hits"></td><td class="source">}</td></tr><tr><td class="line">81</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">82</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">83</td><td class="hits"></td><td class="source">* The default schedule function.</td></tr><tr><td class="line">84</td><td class="hits"></td><td class="source">*/</td></tr><tr class="hit"><td class="line">85</td><td class="hits">1</td><td class="source">function resourcesSched(d) {</td></tr><tr class="hit"><td class="line">86</td><td class="hits">9</td><td class="source"> return d.schedule;</td></tr><tr><td class="line">87</td><td class="hits"></td><td class="source">}</td></tr><tr><td class="line">88</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">89</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">90</td><td class="hits"></td><td class="source">* The default is not reservable function.</td></tr><tr><td class="line">91</td><td class="hits"></td><td class="source">*/</td></tr><tr class="hit"><td class="line">92</td><td class="hits">1</td><td class="source">function resourcesIsNotReservable(d) {</td></tr><tr class="hit"><td class="line">93</td><td class="hits">13</td><td class="source"> return d.isNotReservable || false;</td></tr><tr><td class="line">94</td><td class="hits"></td><td class="source">}</td></tr></tbody></table></div><div class="file"><h2 id="core/tasks.js">core/tasks.js</h2><div id="stats" class="high"><div class="percentage">84%</div><div class="sloc">51</div><div class="hits">43</div><div class="misses">8</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">* Tasks</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source">* (c) 2013 Bill, BunKat LLC.</td></tr><tr><td class="line">4</td><td class="hits"></td><td class="source">*</td></tr><tr><td class="line">5</td><td class="hits"></td><td class="source">* Takes an array of objects and generates an of array valid schedule task objects.</td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source">*</td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source">* Schedule is freely distributable under the MIT license.</td></tr><tr><td class="line">8</td><td class="hits"></td><td class="source">* For all details and documentation:</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source">* http://github.com/bunkat/schedule</td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source">*/</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">12</td><td class="hits">1</td><td class="source">schedule.tasks = function() {</td></tr><tr class="hit"><td class="line">13</td><td class="hits">9</td><td class="source"> var id = tasksId,</td></tr><tr><td class="line">14</td><td class="hits"></td><td class="source"> duration = tasksDuration,</td></tr><tr><td class="line">15</td><td class="hits"></td><td class="source"> sched = tasksSched,</td></tr><tr><td class="line">16</td><td class="hits"></td><td class="source"> resources = tasksResources,</td></tr><tr><td class="line">17</td><td class="hits"></td><td class="source"> dependsOn = tasksDependsOn,</td></tr><tr><td class="line">18</td><td class="hits"></td><td class="source"> minSchedule = tasksMinSchedule,</td></tr><tr><td class="line">19</td><td class="hits"></td><td class="source"> priority = tasksPriority;</td></tr><tr><td class="line">20</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">21</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">22</td><td class="hits"></td><td class="source"> * Takes an array of objects and returns an array of schedule task objects.</td></tr><tr><td class="line">23</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">24</td><td class="hits">9</td><td class="source"> function tasks(data) {</td></tr><tr class="hit"><td class="line">25</td><td class="hits">3</td><td class="source"> var items = [],</td></tr><tr><td class="line">26</td><td class="hits"></td><td class="source"> fid = schedule.functor(id),</td></tr><tr><td class="line">27</td><td class="hits"></td><td class="source"> fduration = schedule.functor(duration),</td></tr><tr><td class="line">28</td><td class="hits"></td><td class="source"> fsched = schedule.functor(sched),</td></tr><tr><td class="line">29</td><td class="hits"></td><td class="source"> fresources = schedule.functor(resources),</td></tr><tr><td class="line">30</td><td class="hits"></td><td class="source"> fdependsOn = schedule.functor(dependsOn),</td></tr><tr><td class="line">31</td><td class="hits"></td><td class="source"> fminschedule = schedule.functor(minSchedule),</td></tr><tr><td class="line">32</td><td class="hits"></td><td class="source"> fpriority = schedule.functor(priority);</td></tr><tr><td class="line">33</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">34</td><td class="hits">3</td><td class="source"> for(var i = 0, len = data.length; i < len; i++) {</td></tr><tr class="hit"><td class="line">35</td><td class="hits">32</td><td class="source"> var task = data[i],</td></tr><tr><td class="line">36</td><td class="hits"></td><td class="source"> item = {</td></tr><tr><td class="line">37</td><td class="hits"></td><td class="source"> id: fid.call(this, task, i),</td></tr><tr><td class="line">38</td><td class="hits"></td><td class="source"> duration: fduration.call(this, task, i),</td></tr><tr><td class="line">39</td><td class="hits"></td><td class="source"> schedule: fsched.call(this, task, i),</td></tr><tr><td class="line">40</td><td class="hits"></td><td class="source"> resources: fresources.call(this, task, i),</td></tr><tr><td class="line">41</td><td class="hits"></td><td class="source"> dependsOn: fdependsOn.call(this, task, i),</td></tr><tr><td class="line">42</td><td class="hits"></td><td class="source"> minSchedule: fminschedule.call(this, task, i),</td></tr><tr><td class="line">43</td><td class="hits"></td><td class="source"> priority: fpriority.call(this, task, i)</td></tr><tr><td class="line">44</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">45</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">46</td><td class="hits">32</td><td class="source"> items.push(item);</td></tr><tr><td class="line">47</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">48</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">49</td><td class="hits">3</td><td class="source"> return items;</td></tr><tr><td class="line">50</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">51</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">52</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">53</td><td class="hits"></td><td class="source"> * The function or value that should be used to generate the task id. Sets the</td></tr><tr><td class="line">54</td><td class="hits"></td><td class="source"> * value to the argument passed in, returns current value if no arguments are</td></tr><tr><td class="line">55</td><td class="hits"></td><td class="source"> * passed in.</td></tr><tr><td class="line">56</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">57</td><td class="hits">9</td><td class="source"> tasks.id = function(_) {</td></tr><tr class="hit"><td class="line">58</td><td class="hits">2</td><td class="source"> if (!arguments.length) return id;</td></tr><tr class="hit"><td class="line">59</td><td class="hits">2</td><td class="source"> id = _;</td></tr><tr class="hit"><td class="line">60</td><td class="hits">2</td><td class="source"> return tasks;</td></tr><tr><td class="line">61</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">62</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">63</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">64</td><td class="hits"></td><td class="source"> * The function or value that should be used to generate the task duration. Sets the</td></tr><tr><td class="line">65</td><td class="hits"></td><td class="source"> * value to the argument passed in, returns current value if no arguments are</td></tr><tr><td class="line">66</td><td class="hits"></td><td class="source"> * passed in.</td></tr><tr><td class="line">67</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">68</td><td class="hits">9</td><td class="source"> tasks.duration = function(_) {</td></tr><tr class="hit"><td class="line">69</td><td class="hits">2</td><td class="source"> if (!arguments.length) return duration;</td></tr><tr class="hit"><td class="line">70</td><td class="hits">2</td><td class="source"> duration = _;</td></tr><tr class="hit"><td class="line">71</td><td class="hits">2</td><td class="source"> return tasks;</td></tr><tr><td class="line">72</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">73</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">74</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">75</td><td class="hits"></td><td class="source"> * The function or value that should be used to generate the task schedule. The</td></tr><tr><td class="line">76</td><td class="hits"></td><td class="source"> * schedule must be a valid Later.js schedule. Sets the value to the argument</td></tr><tr><td class="line">77</td><td class="hits"></td><td class="source"> * passed in, returns current value if no arguments are passed in.</td></tr><tr><td class="line">78</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">79</td><td class="hits">9</td><td class="source"> tasks.schedule = function(_) {</td></tr><tr class="hit"><td class="line">80</td><td class="hits">2</td><td class="source"> if (!arguments.length) return sched;</td></tr><tr class="hit"><td class="line">81</td><td class="hits">2</td><td class="source"> sched = _;</td></tr><tr class="hit"><td class="line">82</td><td class="hits">2</td><td class="source"> return tasks;</td></tr><tr><td class="line">83</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">84</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">85</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">86</td><td class="hits"></td><td class="source"> * The function or value that should be used to generate the resources array. Sets the</td></tr><tr><td class="line">87</td><td class="hits"></td><td class="source"> * value to the argument passed in, returns current value if no arguments are</td></tr><tr><td class="line">88</td><td class="hits"></td><td class="source"> * passed in.</td></tr><tr><td class="line">89</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">90</td><td class="hits">9</td><td class="source"> tasks.resources = function(_) {</td></tr><tr class="hit"><td class="line">91</td><td class="hits">3</td><td class="source"> if (!arguments.length) return resources;</td></tr><tr class="hit"><td class="line">92</td><td class="hits">3</td><td class="source"> resources = _;</td></tr><tr class="hit"><td class="line">93</td><td class="hits">3</td><td class="source"> return tasks;</td></tr><tr><td class="line">94</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">95</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">96</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">97</td><td class="hits"></td><td class="source"> * The function or value that should be used to generate the dependency array. Sets the</td></tr><tr><td class="line">98</td><td class="hits"></td><td class="source"> * value to the argument passed in, returns current value if no arguments are</td></tr><tr><td class="line">99</td><td class="hits"></td><td class="source"> * passed in.</td></tr><tr><td class="line">100</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">101</td><td class="hits">9</td><td class="source"> tasks.dependsOn = function(_) {</td></tr><tr class="miss"><td class="line">102</td><td class="hits">0</td><td class="source"> if (!arguments.length) return dependsOn;</td></tr><tr class="miss"><td class="line">103</td><td class="hits">0</td><td class="source"> dependsOn = _;</td></tr><tr class="miss"><td class="line">104</td><td class="hits">0</td><td class="source"> return tasks;</td></tr><tr><td class="line">105</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">106</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">107</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">108</td><td class="hits"></td><td class="source"> * The function or value that should be used to generate the min schedule. Sets the</td></tr><tr><td class="line">109</td><td class="hits"></td><td class="source"> * value to the argument passed in, returns current value if no arguments are</td></tr><tr><td class="line">110</td><td class="hits"></td><td class="source"> * passed in.</td></tr><tr><td class="line">111</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">112</td><td class="hits">9</td><td class="source"> tasks.minSchedule = function(_) {</td></tr><tr class="hit"><td class="line">113</td><td class="hits">2</td><td class="source"> if (!arguments.length) return minSchedule;</td></tr><tr class="hit"><td class="line">114</td><td class="hits">2</td><td class="source"> minSchedule = _;</td></tr><tr class="hit"><td class="line">115</td><td class="hits">2</td><td class="source"> return tasks;</td></tr><tr><td class="line">116</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">117</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">118</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">119</td><td class="hits"></td><td class="source"> * The function or value that should be used to generate the priority. Sets the</td></tr><tr><td class="line">120</td><td class="hits"></td><td class="source"> * value to the argument passed in, returns current value if no arguments are</td></tr><tr><td class="line">121</td><td class="hits"></td><td class="source"> * passed in.</td></tr><tr><td class="line">122</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">123</td><td class="hits">9</td><td class="source"> tasks.priority = function(_) {</td></tr><tr class="hit"><td class="line">124</td><td class="hits">1</td><td class="source"> if (!arguments.length) return priority;</td></tr><tr class="hit"><td class="line">125</td><td class="hits">1</td><td class="source"> priority = _;</td></tr><tr class="hit"><td class="line">126</td><td class="hits">1</td><td class="source"> return tasks;</td></tr><tr><td class="line">127</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">128</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">129</td><td class="hits">9</td><td class="source"> return tasks;</td></tr><tr><td class="line">130</td><td class="hits"></td><td class="source">};</td></tr><tr><td class="line">131</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">132</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">133</td><td class="hits"></td><td class="source">* The default id function.</td></tr><tr><td class="line">134</td><td class="hits"></td><td class="source">*/</td></tr><tr class="hit"><td class="line">135</td><td class="hits">1</td><td class="source">function tasksId(d) {</td></tr><tr class="miss"><td class="line">136</td><td class="hits">0</td><td class="source"> return d.id;</td></tr><tr><td class="line">137</td><td class="hits"></td><td class="source">}</td></tr><tr><td class="line">138</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">139</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">140</td><td class="hits"></td><td class="source">* The default duration function.</td></tr><tr><td class="line">141</td><td class="hits"></td><td class="source">*/</td></tr><tr class="hit"><td class="line">142</td><td class="hits">1</td><td class="source">function tasksDuration(d) {</td></tr><tr class="miss"><td class="line">143</td><td class="hits">0</td><td class="source"> return d.duration;</td></tr><tr><td class="line">144</td><td class="hits"></td><td class="source">}</td></tr><tr><td class="line">145</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">146</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">147</td><td class="hits"></td><td class="source">* The default schedule function.</td></tr><tr><td class="line">148</td><td class="hits"></td><td class="source">*/</td></tr><tr class="hit"><td class="line">149</td><td class="hits">1</td><td class="source">function tasksSched(d) {</td></tr><tr class="miss"><td class="line">150</td><td class="hits">0</td><td class="source"> return d.schedule;</td></tr><tr><td class="line">151</td><td class="hits"></td><td class="source">}</td></tr><tr><td class="line">152</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">153</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">154</td><td class="hits"></td><td class="source">* The default resources function.</td></tr><tr><td class="line">155</td><td class="hits"></td><td class="source">*/</td></tr><tr class="hit"><td class="line">156</td><td class="hits">1</td><td class="source">function tasksResources(d) {</td></tr><tr class="miss"><td class="line">157</td><td class="hits">0</td><td class="source"> return d.resources;</td></tr><tr><td class="line">158</td><td class="hits"></td><td class="source">}</td></tr><tr><td class="line">159</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">160</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">161</td><td class="hits"></td><td class="source">* The default depends on function.</td></tr><tr><td class="line">162</td><td class="hits"></td><td class="source">*/</td></tr><tr class="hit"><td class="line">163</td><td class="hits">1</td><td class="source">function tasksDependsOn(d) {</td></tr><tr class="hit"><td class="line">164</td><td class="hits">32</td><td class="source"> return d.dependsOn;</td></tr><tr><td class="line">165</td><td class="hits"></td><td class="source">}</td></tr><tr><td class="line">166</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">167</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">168</td><td class="hits"></td><td class="source">* The default min schedule function.</td></tr><tr><td class="line">169</td><td class="hits"></td><td class="source">*/</td></tr><tr class="hit"><td class="line">170</td><td class="hits">1</td><td class="source">function tasksMinSchedule(d) {</td></tr><tr class="miss"><td class="line">171</td><td class="hits">0</td><td class="source"> return d.minSchedule;</td></tr><tr><td class="line">172</td><td class="hits"></td><td class="source">}</td></tr><tr><td class="line">173</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">174</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">175</td><td class="hits"></td><td class="source">* The default priority function.</td></tr><tr><td class="line">176</td><td class="hits"></td><td class="source">*/</td></tr><tr class="hit"><td class="line">177</td><td class="hits">1</td><td class="source">function tasksPriority(d) {</td></tr><tr class="hit"><td class="line">178</td><td class="hits">10</td><td class="source"> return d.priority;</td></tr><tr><td class="line">179</td><td class="hits"></td><td class="source">}</td></tr></tbody></table></div><div class="file"><h2 id="date/date.js">date/date.js</h2><div id="stats" class="high"><div class="percentage">100%</div><div class="sloc">1</div><div class="hits">1</div><div class="misses">0</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr class="hit"><td class="line">1</td><td class="hits">1</td><td class="source">schedule.date = {};</td></tr></tbody></table></div><div class="file"><h2 id="date/timezone.js">date/timezone.js</h2><div id="stats" class="high"><div class="percentage">100%</div><div class="sloc">2</div><div class="hits">2</div><div class="misses">0</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">* Timezone</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source">* (c) 2013 Bill, BunKat LLC.</td></tr><tr><td class="line">4</td><td class="hits"></td><td class="source">*</td></tr><tr><td class="line">5</td><td class="hits"></td><td class="source">* Configures Schedule to use local time or UTC. Schedule uses UTC time by default.</td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source">*</td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source">* Schedule is freely distributable under the MIT license.</td></tr><tr><td class="line">8</td><td class="hits"></td><td class="source">* For all details and documentation:</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source">* http://github.com/bunkat/schedule</td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source">*/</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source">// pass through to Later to configure timezones</td></tr><tr class="hit"><td class="line">13</td><td class="hits">1</td><td class="source">schedule.date.UTC = function() { later.date.UTC(); };</td></tr><tr class="hit"><td class="line">14</td><td class="hits">5</td><td class="source">schedule.date.localTime = function() { later.date.localTime(); };</td></tr></tbody></table></div><div class="file"><h2 id="sort/sort.js">sort/sort.js</h2><div id="stats" class="high"><div class="percentage">100%</div><div class="sloc">1</div><div class="hits">1</div><div class="misses">0</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr class="hit"><td class="line">1</td><td class="hits">1</td><td class="source">schedule.sort = {};</td></tr></tbody></table></div><div class="file"><h2 id="sort/tasks.js">sort/tasks.js</h2><div id="stats" class="high"><div class="percentage">100%</div><div class="sloc">8</div><div class="hits">8</div><div class="misses">0</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">* Sort tasks</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source">* (c) 2013 Bill, BunKat LLC.</td></tr><tr><td class="line">4</td><td class="hits"></td><td class="source">*</td></tr><tr><td class="line">5</td><td class="hits"></td><td class="source">* Determines the order that tasks are scheduled in when multiple tasks can be</td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source">* scheduled in parallel. Default it to do highest priority tasks first, then</td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source">* tasks that have been determined to have the largest float.</td></tr><tr><td class="line">8</td><td class="hits"></td><td class="source">*</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source">* Schedule is freely distributable under the MIT license.</td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source">* For all details and documentation:</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source">* http://github.com/bunkat/schedule</td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source">*/</td></tr><tr><td class="line">13</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">14</td><td class="hits">1</td><td class="source">schedule.sort.tasks = function(taskGraph, readyTasks) {</td></tr><tr class="hit"><td class="line">15</td><td class="hits">69</td><td class="source"> readyTasks.sort(function(a,b) {</td></tr><tr class="hit"><td class="line">16</td><td class="hits">155</td><td class="source"> var ta = taskGraph.tasks[a],</td></tr><tr><td class="line">17</td><td class="hits"></td><td class="source"> tb = taskGraph.tasks[b];</td></tr><tr><td class="line">18</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">19</td><td class="hits">155</td><td class="source"> if(tb.priority && (!ta.priority || tb.priority > ta.priority)) {</td></tr><tr class="hit"><td class="line">20</td><td class="hits">118</td><td class="source"> return -1;</td></tr><tr><td class="line">21</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">22</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">23</td><td class="hits">37</td><td class="source"> if(ta.priority && (!tb.priority || ta.priority > tb.priority)) {</td></tr><tr class="hit"><td class="line">24</td><td class="hits">19</td><td class="source"> return 1;</td></tr><tr><td class="line">25</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">26</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">27</td><td class="hits">18</td><td class="source"> return taskGraph.tasks[b].floatAmt > taskGraph.tasks[a].floatAmt;</td></tr><tr><td class="line">28</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">29</td><td class="hits"></td><td class="source">};</td></tr></tbody></table></div><div class="file"><h2 id="util/functor.js">util/functor.js</h2><div id="stats" class="high"><div class="percentage">100%</div><div class="sloc">2</div><div class="hits">2</div><div class="misses">0</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">* Functor</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source">*</td></tr><tr><td class="line">4</td><td class="hits"></td><td class="source">* Wraps values in functions so that they can be called. Usage inspired by</td></tr><tr><td class="line">5</td><td class="hits"></td><td class="source">* Mike Bostock in d3.</td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source">*</td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source">* Schedule is freely distributable under the MIT license.</td></tr><tr><td class="line">8</td><td class="hits"></td><td class="source">* For all details and documentation:</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source">* http://github.com/bunkat/schedule</td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source">*/</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">12</td><td class="hits">1</td><td class="source">schedule.functor = function(v) {</td></tr><tr class="hit"><td class="line">13</td><td class="hits">64</td><td class="source"> return typeof v === "function" ? v : function() { return v; };</td></tr><tr><td class="line">14</td><td class="hits"></td><td class="source">};</td></tr></tbody></table></div><div class="file"><h2 id="util/memoized-range-fn.js">util/memoized-range-fn.js</h2><div id="stats" class="high"><div class="percentage">100%</div><div class="sloc">7</div><div class="hits">7</div><div class="misses">0</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">* MemoizedRangeFn</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source">* (c) 2013 Bill, BunKat LLC.</td></tr><tr><td class="line">4</td><td class="hits"></td><td class="source">*</td></tr><tr><td class="line">5</td><td class="hits"></td><td class="source">* Wraps later.schedule().nextRange to provide memoization of results. Calculating</td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source">* valid occurrences can be expensive and so we want to reduce the amount of times</td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source">* we calculate them as much as possible. Also cleans up undefined values so that</td></tr><tr><td class="line">8</td><td class="hits"></td><td class="source">* we don't have to deal with them later.</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source">*</td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source">* Schedule is freely distributable under the MIT license.</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source">* For all details and documentation:</td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source">* http://github.com/bunkat/schedule</td></tr><tr><td class="line">13</td><td class="hits"></td><td class="source">*/</td></tr><tr><td class="line">14</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">15</td><td class="hits">1</td><td class="source">schedule.memoizedRangeFn = function(fn) {</td></tr><tr class="hit"><td class="line">16</td><td class="hits">254</td><td class="source"> var cache = {}; // local store for memoization results</td></tr><tr><td class="line">17</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">18</td><td class="hits">254</td><td class="source"> return function(start) {</td></tr><tr class="hit"><td class="line">19</td><td class="hits">566</td><td class="source"> if(!cache[start]) {</td></tr><tr class="hit"><td class="line">20</td><td class="hits">550</td><td class="source"> var result = fn(1, start);</td></tr><tr class="hit"><td class="line">21</td><td class="hits">550</td><td class="source"> cache[start] = [</td></tr><tr><td class="line">22</td><td class="hits"></td><td class="source"> result[0] ? result[0].getTime() : 4102444800000,// Jan 1, 2100</td></tr><tr><td class="line">23</td><td class="hits"></td><td class="source"> result[1] ? result[1].getTime() : 4102444800000 // Jan 1, 2100</td></tr><tr><td class="line">24</td><td class="hits"></td><td class="source"> ];</td></tr><tr><td class="line">25</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">26</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">27</td><td class="hits">566</td><td class="source"> return cache[start];</td></tr><tr><td class="line">28</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">29</td><td class="hits"></td><td class="source">};</td></tr></tbody></table></div></div></div></body></html>make[1]: Leaving directory `/home/bill/dev/schedule'