├── .travis.yml ├── Readme.md ├── lib ├── test │ ├── index.js │ └── test.js └── transducers.js ├── package.json └── src ├── test ├── index.js └── test.js └── transducers.js /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | - "0.12" 5 | before_install: 6 | - npm install -g npm@~1.4.6 7 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Transducers [![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Gitter][gitter-image]][gitter-url] 2 | ========= 3 | 4 | [![Browser support](https://ci.testling.com/Gozala/transducers.png)](http://ci.testling.com/Gozala/transducers) 5 | 6 | Library provides composable algorithmic transformations that are independent 7 | from the context of their input and output sources and specify only the essence 8 | of the transformation. In other words transducers are not coupled with a data 9 | they are operating & there for can operate on built-in JS types like arrays, 10 | strings, numbers, iterators as well as they could on custom types like [Immutable.js][] 11 | data structures, [RxJS][] Observables, [CSP Channels][] or whatever else you 12 | may decide to use them for. 13 | 14 | 15 | Following resources provide an excelent introduction to Transducers idea that this 16 | this library imlements. 17 | 18 | * ["Transducers are coming" announce blog post](http://blog.cognitect.com/blog/2014/8/6/transducers-are-coming) 19 | * [Rich Hickey's Transducers StrangeLoop presentation](https://www.youtube.com/watch?v=6mTbuzafcII) 20 | 21 | ## API 22 | 23 | ### transducers 24 | 25 | #### map(f) 26 | 27 | Applies `f` onto each item of the input data structure. 28 | 29 | ```js 30 | const {map} = require("transducers") 31 | const inc = map(x => x + 1) 32 | 33 | inc([2, 3, 4]) // => [3, 4, 5] 34 | ``` 35 | 36 | 37 | #### filter(p) 38 | 39 | Keeps only items from input on which `p(item)` returned logical `true`. 40 | 41 | ```js 42 | const {filter} = require("transducers") 43 | const isEven = x => !(x % 2) 44 | 45 | filter(isEven)([1, 2, 3, 4]) // => [2, 4] 46 | ``` 47 | 48 | #### remove(p) 49 | 50 | Removes items from input on with `p(item)` returned logical `true`. 51 | 52 | ```js 53 | const {remove} = require("transducers") 54 | const isEven = x => !(x % 2) 55 | 56 | remove(isEven)([1, 2, 3, 4]) // => [1, 3] 57 | ``` 58 | 59 | #### drop(n) 60 | 61 | Drops first `n` number of items from the input. 62 | 63 | ```js 64 | const {drop} = require("transducers") 65 | 66 | drop(2)([1, 2, 3, 4]) // => [3, 4] 67 | ``` 68 | 69 | #### dropWhile(p) 70 | 71 | Drops items from the input while `p(item)` is logical `true`. Note that once 72 | `p(item)` returns logical `false` `p` is no longer applied to items. 73 | 74 | ```js 75 | const {dropWhile} = require("transdures") 76 | 77 | dropWhile(x => x < 5)([1, 3, 7, 4, 9]) // => [7, 4, 9] 78 | ``` 79 | 80 | #### dropRepeats 81 | 82 | Drops duplicate items form the input (equality compared with ===). 83 | 84 | ```js 85 | const {dropRepeats} = require("transducers") 86 | 87 | dropRepeats([1, 2, 2, 2, 3, 3, 4]) // => [1, 2, 3, 4] 88 | ``` 89 | 90 | #### take(n) 91 | 92 | Takes first `n` number of items from the input. 93 | 94 | ```js 95 | const {take} = require("transducers") 96 | 97 | take(3)([1, 2, 3, 4, 5]) // => [1, 2, 3] 98 | ``` 99 | 100 | #### takeWhile(p) 101 | 102 | Takes items as long as `p(item)` returns logical `true`. Note than once 103 | `p(item)` returns logical `false` `p` is no longer applied to items. 104 | 105 | ```js 106 | const {takeWhile} = require("transducers") 107 | 108 | takeWhile(x => x < 5)([1, 4, 6, 5, 3]) // => [1, 4] 109 | ``` 110 | 111 | #### partition(n) 112 | 113 | Collects inputs into arrays of size `n`. In case there are not enough padding 114 | items, last partition will have less than `n` items. 115 | 116 | ```js 117 | const {partition} = require("transducers") 118 | 119 | partition(3)([0, 1, 2, 3, 4, 5]) // => [[0, 1, 2], [3, 4, 5]] 120 | partition(3)([0, 1, 2, 3]) // => [[0, 1, 2], [3]] 121 | ``` 122 | 123 | #### cat 124 | 125 | Concatenates items of the input. Assumes that items are collections. 126 | 127 | ```js 128 | const {cat} = require("transducers") 129 | 130 | cat([[1, 2, 3], [4], [5, 6]]) // => [1, 2, 3, 4, 5, 6] 131 | ``` 132 | 133 | ### composition 134 | 135 | If `map` is passed a transducer produces composed transducer: 136 | 137 | ```js 138 | (filter(isEven)) 139 | (map(inc)) 140 | ([1, 4, 9, 10]) // => [5, 11] 141 | ``` 142 | 143 | #### mapcat 144 | 145 | In fact library does not expose `mapcat` as it's pretty much made obsolete 146 | by a composition API. 147 | 148 | ```js 149 | map(x => x.split("/"))(cat)(["path/to", "dir/file"]) // => ["path", "to", "dir", "file"] 150 | ``` 151 | 152 | ## Different implementation 153 | 154 | There are other two known implementations of [Transducers][] in JS: 155 | 156 | - [transducers-js] 157 | - [transducers.js] 158 | 159 | In fact this library initially started as an attempt to enhance API of 160 | [transducers.js][] and of a general idea, which also lead it to it's own 161 | path. 162 | 163 | The core difference from both of the libraries is in the way transducers 164 | are composed & applied to input. In that regard it actually has more in 165 | common with [fab.js][] than transducers. 166 | 167 | 168 | #### transducer application 169 | 170 | In above mentioned libraries transducer application happens through other 171 | functions like [into][], [reduce][] & [transduce][] & expectation is that 172 | data type constructors can take transducer to create transduced version 173 | of it. In contrast this library does not provide [into][] and considers both 174 | [reduce][] and [transduce][] to be to low level APIs. For most common cases 175 | you would want to transform a data structure of a type to different data 176 | structure of the same type. In this library transducer functions can just take 177 | that data structure as an argument and return transformed version: 178 | 179 | ```js 180 | const inc = x => x + 1 181 | map(inc)([1, 2, 3]) // => [2, 3, 4] 182 | map(char => char.toUpperCase())("hello") // => "HELLO" 183 | ```` 184 | 185 | ### transducers can be applied to primitives 186 | 187 | In this library transdures can also apply to primitives values like numbers 188 | just as well as they can to collections: 189 | 190 | ```js 191 | map(inc)(5) // => 6 192 | ``` 193 | 194 | any transformation over nil types like `null` and `undefined` is no op and 195 | return input back: 196 | 197 | ```js 198 | map(inc)(null) // => null 199 | map(_ => 5)(null) // => null 200 | ``` 201 | 202 | #### transducer composition 203 | 204 | Transducers in all of the libraries (including this one) can be composed with 205 | as a plain function composition that you know or at least have seen in [underscore.js][http://underscorejs.org/#compose]. 206 | Idea is simple composing `f()` and `g()` functions produces `f(g())`. 207 | 208 | ```js 209 | reduce(_.compose(x => x + 1, x => x * 2), 0, 2) // => 5 210 | ``` 211 | 212 | Although in case of transducers there is a surprising twist related to the implementation 213 | illustrated in the example below: 214 | 215 | ```js 216 | reduce(_.compose(map(x => x + 1), map(x => x * 2), [], [2]) // => [6] 217 | 218 | ``` 219 | 220 | Unlike right to left execution as in ordinary function composition execution order 221 | in transducers is from left to right instead. In order to avoid confusion & dependency 222 | on additional composition constructs this library takes inspiration from an API pioneered 223 | by [fab.js][] a while back: 224 | 225 | 226 | ```js 227 | (map(x => x + 1)) 228 | (map(x => x * 2)) 229 | ([2, 3]) // => [6, 8] 230 | ``` 231 | 232 | Execution is from top to bottom & no extra functions are need to compose them. 233 | 234 | **P.S.:** You still could use `_.compose` but in that case avoid using application like 235 | `_compose(f, g)([1, 2, 3])` as that won't do what you expect, given that input will be 236 | passed to `g` and then result to `f` instead of passing it to `f.g` composition. 237 | 238 | 239 | ## License 240 | 241 | [MIT License](http://en.wikipedia.org/wiki/MIT_License) 242 | 243 | [npm-url]: https://npmjs.org/package/transducers 244 | [npm-image]: https://img.shields.io/npm/v/transducers.svg?style=flat 245 | 246 | [travis-url]: https://travis-ci.org/Gozala/transducers 247 | [travis-image]: https://img.shields.io/travis/Gozala/transducers.svg?style=flat 248 | 249 | [gitter-url]: https://gitter.im/Gozala/transducers?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge 250 | [gitter-image]: https://badges.gitter.im/Join%20Chat.svg 251 | 252 | 253 | [clojure transducers]:http://blog.cognitect.com/blog/2014/8/6/transducers-are-coming 254 | [transducers.js]:http://jlongster.com/Transducers.js--A-JavaScript-Library-for-Transformation-of-Data 255 | [Immutable.js]:http://facebook.github.io/immutable-js/docs/#/Record 256 | [CSP Channels]:https://github.com/gozala/channel 257 | [RxJS]:https://github.com/Reactive-Extensions/RxJS 258 | [transducers-js]:https://github.com/cognitect-labs/transducers-js 259 | [transducers.js]:https://github.com/jlongster/transducers.js 260 | [fab.js]:https://www.youtube.com/watch?v=ViQ8kiLtDXc 261 | [into]:http://cognitect-labs.github.io/transducers-js/classes/transducers.html#methods_transducers.into 262 | [reduce]:http://cognitect-labs.github.io/transducers-js/classes/transducers.html#methods_transducers.reduce 263 | [transduce]:http://cognitect-labs.github.io/transducers-js/classes/transducers.html#methods_transducers.transduce 264 | -------------------------------------------------------------------------------- /lib/test/index.js: -------------------------------------------------------------------------------- 1 | (function (factory) { 2 | if (typeof define === "function" && define.amd) { 3 | define(["exports", "./test", "immutable", "../../"], factory); 4 | } else if (typeof exports !== "undefined") { 5 | factory(exports, require("./test"), require("immutable"), require("../../")); 6 | } 7 | })(function (exports, _test, _immutable, _) { 8 | "use strict"; 9 | 10 | var _slicedToArray = function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { var _arr = []; for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) { _arr.push(_step.value); if (i && _arr.length === i) break; } return _arr; } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; 11 | 12 | var _toConsumableArray = function (arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }; 13 | 14 | var test = _test["default"]; 15 | var Immutable = _immutable; 16 | var reduce = _.reduce; 17 | var transduce = _.transduce; 18 | var map = _.map; 19 | var filter = _.filter; 20 | var remove = _.remove; 21 | var cat = _.cat; 22 | var mapcat = _.mapcat; 23 | var partition = _.partition; 24 | var take = _.take; 25 | var takeWhile = _.takeWhile; 26 | var drop = _.drop; 27 | var dropWhile = _.dropWhile; 28 | var dropRepeats = _.dropRepeats; 29 | var init = _.init; 30 | var step = _.step; 31 | var result = _.result; 32 | 33 | // utility 34 | var inc = function (x) { 35 | return x + 1; 36 | }; 37 | var upperCase = function (char) { 38 | return char.toUpperCase(); 39 | }; 40 | var lowerCase = function (char) { 41 | return char.toLowerCase(); 42 | }; 43 | var add = function (x) { 44 | return function (y) { 45 | return x + y; 46 | }; 47 | }; 48 | var multiply = function (x) { 49 | return function (y) { 50 | return x * y; 51 | }; 52 | }; 53 | var stringify = function (json) { 54 | return JSON.stringify(json); 55 | }; 56 | var isEven = function (x) { 57 | return !(x % 2); 58 | }; 59 | var isLowerCase = function (char) { 60 | return char.toLowerCase() === char; 61 | }; 62 | var lessThan = function (x) { 63 | return function (y) { 64 | return y < x; 65 | }; 66 | }; 67 | var constant = function (x) { 68 | return function (_) { 69 | return x; 70 | }; 71 | }; 72 | var identity = function (x) { 73 | return x; 74 | }; 75 | 76 | var True = constant(true); 77 | var False = constant(false); 78 | 79 | if (!Array.from) { 80 | Array.from = function (iterator) { 81 | var array = []; 82 | while (true) { 83 | var _iterator$next = iterator.next(); 84 | 85 | var value = _iterator$next.value; 86 | var done = _iterator$next.done; 87 | 88 | if (done) { 89 | return array; 90 | } else { 91 | array.push(value); 92 | } 93 | } 94 | }; 95 | } 96 | 97 | test("map", function (assert) { 98 | var incer = map(inc); 99 | 100 | assert.deepEqual(incer([1, 2, 3, 4]), [2, 3, 4, 5], "array elements get mapped"); 101 | 102 | assert.deepEqual(incer(0), 1, "function is applied to number"); 103 | 104 | assert.deepEqual(incer(null), null, "map over null is no op"); 105 | 106 | assert.deepEqual(incer(void 0), void 0, "map over void is void"); 107 | 108 | assert.equal(map(upperCase)("Hello"), "HELLO", "strings can be mapped over"); 109 | 110 | var iterator = Immutable.Iterable({ x: 1, y: 2 }); 111 | 112 | assert.deepEqual([].concat(_toConsumableArray(incer(iterator.values()))), [2, 3], "iterable makes lazy transformation"); 113 | 114 | assert.deepEqual([].concat(_toConsumableArray(map(upperCase)(iterator.keys()))), ["X", "Y"], "iterable makes lazy transformation"); 115 | 116 | assert.deepEqual(map(identity)([[1, 2], [3, 4]]), [[1, 2], [3, 4]], "map does not expands"); 117 | }); 118 | 119 | test("filter", function (assert) { 120 | var evens = filter(isEven); 121 | 122 | assert.deepEqual(evens([1, 2, 3, 4]), [2, 4], "array elements got filtered"); 123 | 124 | assert.deepEqual(evens([1, 3, 5, 7]), [], "filtered out all elements"); 125 | 126 | assert.deepEqual(evens(7), 0, "filtered out odd number to empty number"); 127 | 128 | assert.deepEqual(evens(6), 6, "number was kept as it was even"); 129 | 130 | assert.deepEqual(filter(True)(null), null, "null remains null regardless of operation"); 131 | 132 | assert.deepEqual(filter(False)(void 0), void 0, "void remains void regardless of operation"); 133 | 134 | assert.deepEqual(filter(isLowerCase)("Hello World"), "ello orld", "filters out upper case letters"); 135 | 136 | var iterator = Immutable.Iterable({ x: 1, Y: 2, z: 3 }); 137 | 138 | assert.deepEqual([].concat(_toConsumableArray(evens(iterator.values()))), [2], "filter value iterators"); 139 | 140 | assert.deepEqual([].concat(_toConsumableArray(filter(isLowerCase)(iterator.keys()))), ["x", "z"], "filter key iterators"); 141 | }); 142 | 143 | test("remove", function (assert) { 144 | var odds = remove(isEven); 145 | var upperCaseChars = remove(isLowerCase); 146 | 147 | assert.deepEqual(odds([1, 2, 3, 4]), [1, 3], "evens were removed"); 148 | 149 | assert.deepEqual(remove(True)(null), null, "transducing null return null"); 150 | 151 | assert.deepEqual(remove(False)(null), null, "transducing null return null"); 152 | 153 | assert.deepEqual(remove(True)(void 0), void 0, "transducing void return void"); 154 | 155 | assert.deepEqual(remove(False)(void 0), void 0, "transducing void return void"); 156 | 157 | assert.deepEqual(remove(function (x) { 158 | return x > 0; 159 | })(7), 0, "removing matching number returns 0"); 160 | 161 | assert.deepEqual(remove(function (x) { 162 | return x < 0; 163 | })(7), 7, "removing unmatched number returns number"); 164 | 165 | assert.deepEqual(upperCaseChars("Hello World"), "HW", "removes lower case chars"); 166 | 167 | assert.deepEqual(upperCaseChars("what?"), "", "removes all chars"); 168 | 169 | var iterator = Immutable.Iterable({ x: 1, Y: 2, z: 3 }); 170 | 171 | assert.deepEqual([].concat(_toConsumableArray(odds(iterator.values()))), [1, 3], "removes from iterator"); 172 | }); 173 | 174 | test("drop", function (assert) { 175 | assert.deepEqual(drop(2)([1, 2, 3, 4, 5]), [3, 4, 5], "dropped two items"); 176 | 177 | assert.deepEqual(drop(9)([1, 2, 3, 4]), [], "dropes all items"); 178 | 179 | assert.deepEqual(drop(7)([]), [], "nothing to drop"); 180 | 181 | assert.deepEqual(drop(0)([1, 2, 3, 4]), [1, 2, 3, 4], "no need to drop"); 182 | 183 | assert.deepEqual(drop(-7)([1, 2, 3]), [1, 2, 3], "no need to drop"); 184 | 185 | assert.deepEqual(drop(0)(1), 1, "number was not dropped"); 186 | assert.deepEqual(drop(5)(8), 0, "number was reset to 0"); 187 | 188 | assert.deepEqual(drop(3)("hello"), "lo", "three characters were dropped"); 189 | 190 | assert.deepEqual(drop(9)("hello"), "", "dropped all chars"); 191 | 192 | assert.deepEqual(drop(8)(""), "", "nothing to drop"); 193 | 194 | assert.deepEqual(drop(9)(null), null); 195 | 196 | assert.deepEqual(drop(0)(null), null); 197 | 198 | assert.deepEqual(drop(8)(void 0), void 0); 199 | 200 | assert.deepEqual(drop(0)(void 0), void 0); 201 | 202 | var iterator = Immutable.Iterable({ x: 1, y: 2 }); 203 | 204 | assert.deepEqual([].concat(_toConsumableArray(drop(0)(iterator.values()))), [1, 2], "0 drops"); 205 | 206 | assert.deepEqual([].concat(_toConsumableArray(drop(1)(iterator.values()))), [2], "dropped first"); 207 | 208 | assert.deepEqual([].concat(_toConsumableArray(drop(8)(iterator.values()))), [], "dropped all"); 209 | }); 210 | 211 | test("dropWhile", function (assert) { 212 | assert.deepEqual(dropWhile(lessThan(9))([1, 8, 12, 9, 45]), [12, 9, 45]); 213 | 214 | assert.deepEqual(dropWhile(lessThan(9))([10, 9, 8, 7]), [10, 9, 8, 7]); 215 | 216 | assert.deepEqual(dropWhile(lessThan(9))([1, 2, 3]), []); 217 | 218 | assert.deepEqual(dropWhile(lessThan(9))([]), []); 219 | 220 | assert.deepEqual(dropWhile(False)(5), 5); 221 | assert.deepEqual(dropWhile(True)(5), 0); 222 | 223 | assert.deepEqual(dropWhile(True)(null), null); 224 | assert.deepEqual(dropWhile(False)(null), null); 225 | 226 | assert.deepEqual(dropWhile(True)(void 0), void 0); 227 | assert.deepEqual(takeWhile(False)(void 0), void 0); 228 | 229 | assert.deepEqual(dropWhile(isLowerCase)("never mind You"), "You"); 230 | assert.deepEqual(dropWhile(isLowerCase)("Hi there"), "Hi there"); 231 | assert.deepEqual(dropWhile(True)(""), ""); 232 | assert.deepEqual(dropWhile(False)(""), ""); 233 | 234 | var iterator = Immutable.Iterable({ x: 0, y: 5, z: 10 }); 235 | 236 | assert.deepEqual([].concat(_toConsumableArray(dropWhile(lessThan(7))(iterator.values()))), [10]); 237 | 238 | assert.deepEqual([].concat(_toConsumableArray(dropWhile(lessThan(0))(iterator.values()))), [0, 5, 10]); 239 | 240 | assert.deepEqual([].concat(_toConsumableArray(dropWhile(lessThan(99))(iterator.values()))), []); 241 | }); 242 | 243 | test("dropRepeats", function (assert) { 244 | assert.deepEqual(dropRepeats([1, 2, 3, 3, 4, 3]), [1, 2, 3, 4, 3], "removed repeated elements"); 245 | 246 | assert.deepEqual(dropRepeats([1, 1, 1, 1, 1]), [1], "keeps just one"); 247 | 248 | assert.deepEqual(dropRepeats(1), 1, "number has no repeats"); 249 | 250 | assert.deepEqual(dropRepeats(null), null, "null transfromed is null"); 251 | 252 | assert.deepEqual(dropRepeats(void 0), void 0, "void transfromed is void"); 253 | 254 | assert.deepEqual(dropRepeats("what"), "what", "nothing to drop"); 255 | 256 | assert.deepEqual(dropRepeats("hello"), "helo", "dropes repeated chars"); 257 | 258 | var iterator = Immutable.Iterable({ x: 1, Y: 2, z: 2 }); 259 | 260 | assert.deepEqual([].concat(_toConsumableArray(dropRepeats(iterator.values()))), [1, 2], "removes repeats form iterator"); 261 | }); 262 | 263 | test("take", function (assert) { 264 | assert.deepEqual(take(2)([1, 2, 3, 4, 5]), [1, 2], "took two"); 265 | 266 | assert.deepEqual(take(9)([1, 2, 3, 4]), [1, 2, 3, 4], "took all"); 267 | 268 | assert.deepEqual(take(7)([]), [], "nothing to take"); 269 | 270 | assert.deepEqual(take(0)([1, 2, 3, 4]), [], "took 0"); 271 | 272 | assert.deepEqual(take(-7)([1, 2, 3]), [], "took none"); 273 | 274 | assert.deepEqual(take(0)(1), 0); 275 | assert.deepEqual(take(5)(8), 8); 276 | 277 | assert.deepEqual(take(3)("hello"), "hel"); 278 | 279 | assert.deepEqual(take(9)("hello"), "hello"); 280 | 281 | assert.deepEqual(take(8)(""), ""); 282 | 283 | assert.deepEqual(take(9)(null), null); 284 | 285 | assert.deepEqual(take(0)(null), null); 286 | 287 | assert.deepEqual(take(8)(void 0), void 0); 288 | 289 | assert.deepEqual(drop(0)(void 0), void 0); 290 | 291 | var iterator = Immutable.Iterable({ x: 1, y: 2 }); 292 | 293 | assert.deepEqual([].concat(_toConsumableArray(take(9)(iterator.values()))), [1, 2]); 294 | 295 | assert.deepEqual([].concat(_toConsumableArray(take(1)(iterator.values()))), [1], "took first"); 296 | 297 | assert.deepEqual([].concat(_toConsumableArray(take(0)(iterator.values()))), [], "took none"); 298 | }); 299 | 300 | test("takeWhile", function (assert) { 301 | var digits = takeWhile(lessThan(10)); 302 | 303 | assert.deepEqual(digits([1, 8, 12, 9, 45]), [1, 8], "takes only digits"); 304 | 305 | assert.deepEqual(digits([10, 9, 8, 7]), [], "takes none"); 306 | 307 | assert.deepEqual(digits(5), 5, "take matching number"); 308 | 309 | assert.deepEqual(digits(97), 0, "returns 0 on unmatched number"); 310 | 311 | assert.deepEqual(takeWhile(True)(null), null, "return null"); 312 | 313 | assert.deepEqual(takeWhile(False)(null), null, "returns null"); 314 | 315 | assert.deepEqual(takeWhile(True)(void 0), void 0, "return void"); 316 | 317 | assert.deepEqual(takeWhile(False)(void 0), void 0, "return void"); 318 | 319 | assert.deepEqual(takeWhile(isLowerCase)("never mind You"), "never mind ", "takes until upper case"); 320 | 321 | assert.deepEqual(takeWhile(isLowerCase)("Hi there"), "", "blank string"); 322 | 323 | var iterator = Immutable.Iterable({ x: 0, y: 5, z: 10 }); 324 | 325 | assert.deepEqual([].concat(_toConsumableArray(takeWhile(lessThan(7))(iterator.values()))), [0, 5], "removes repeats form iterator"); 326 | }); 327 | 328 | test("partition", function (assert) { 329 | assert.deepEqual(partition(2)([1, 2, 3, 4, 5, 6, 7, 8]), [[1, 2], [3, 4], [5, 6], [7, 8]]); 330 | 331 | assert.deepEqual(partition(3)([1, 2, 3, 4, 5, 6, 7, 8]), [[1, 2, 3], [4, 5, 6], [7, 8]]); 332 | 333 | assert.deepEqual(partition(4)([1, 2]), [[1, 2]]); 334 | 335 | assert.deepEqual(partition(3)([]), []); 336 | 337 | assert.deepEqual(partition(3)(9), 9); 338 | assert.deepEqual(partition(2)("hello"), "hello"); 339 | 340 | assert.deepEqual(partition(2)(null), null); 341 | assert.deepEqual(partition(2)(void 0), void 0); 342 | 343 | var iterator = Immutable.Iterable({ x: 0, y: 5, z: 10 }); 344 | 345 | assert.deepEqual([].concat(_toConsumableArray(partition(2)(iterator.values()))), [[0, 5], [10]]); 346 | }); 347 | 348 | // TODO:! 349 | test("partitionBy", function (assert) {}); 350 | 351 | test("cat", function (assert) { 352 | assert.deepEqual(cat([[1, 2], [3], [4, 5]]), [1, 2, 3, 4, 5]); 353 | 354 | assert.deepEqual(cat([]), []); 355 | assert.deepEqual(cat([1, 2, 3]), [1, 2, 3]); 356 | assert.deepEqual(cat(null), null); 357 | assert.deepEqual(cat(void 0), void 0); 358 | assert.deepEqual(cat(4), 4); 359 | assert.deepEqual(cat("hello"), "hello"); 360 | 361 | var valueIter = Immutable.Iterable([0, 5, 10]).values(); 362 | 363 | assert.deepEqual([].concat(_toConsumableArray(cat(valueIter))), [0, 5, 10]); 364 | 365 | var arrayIter = Immutable.Iterable([[1, 2], [3], [4, 5, 6]]).values(); 366 | assert.deepEqual([].concat(_toConsumableArray(cat(arrayIter))), [1, 2, 3, 4, 5, 6]); 367 | }); 368 | 369 | test("mapcat", function (assert) { 370 | assert.deepEqual(map(function (x) { 371 | return x.split("/"); 372 | })(cat)(["path/to", "dir/file"]), ["path", "to", "dir", "file"]); 373 | }); 374 | 375 | test("composition", function (assert) { 376 | var incer = map(inc); 377 | var add2 = incer(incer); 378 | 379 | assert.equal(typeof add2, "function", "passing transducer to transducer composes a new one"); 380 | 381 | assert.deepEqual(add2([1, 2, 3, 4]), [3, 4, 5, 6], "array elements get mapped"); 382 | 383 | assert.deepEqual(add2(0), 2, "function is applied to number"); 384 | 385 | assert.deepEqual(add2(null), null, "map over null is no op"); 386 | 387 | assert.deepEqual(add2(void 0), void 0, "map over void is void"); 388 | 389 | assert.deepEqual(filter(isEven)(map(inc))([1, 4, 9, 10]), [5, 11]); 390 | }); 391 | 392 | test("trasduce", function (assert) { 393 | var evens = filter(isEven); 394 | assert.equal(transduce(evens, function (x, y) { 395 | return y === void 0 ? x : x + y; 396 | }, 2, [1, 2, 3, 4]), 8, "transduced array with custom reducer"); 397 | 398 | assert.equal(transduce(evens, function (x, y) { 399 | return x === void 0 ? 0 : y === void 0 ? x : x + y; 400 | }, [1, 2, 3, 4]), 6, "transduced without initial value"); 401 | 402 | var iterator = Immutable.Iterable({ x: 1, Y: 2, z: 3, w: 4 }); 403 | assert.equal(transduce(evens, function (x, y) { 404 | return y === void 0 ? x : x + y; 405 | }, 5, iterator.values()), 11, "transduce iterator with custom reducer"); 406 | }); 407 | 408 | test("immutable list", function (assert) { 409 | var incer = map(inc); 410 | var list = Immutable.List.of(1, 2, 3, 4); 411 | var t1 = incer(list); 412 | 413 | assert.notOk(t1 instanceof Immutable.List, "result is not a list"); 414 | 415 | assert.deepEqual([].concat(_toConsumableArray(t1)), [2, 3, 4, 5], "result is an iterator"); 416 | 417 | Immutable.List.prototype[init.symbol] = function () { 418 | return Immutable.List().asMutable(); 419 | }; 420 | 421 | Immutable.List.prototype[result.symbol] = function (list) { 422 | return list.asImmutable(); 423 | }; 424 | 425 | Immutable.List.prototype[step.symbol] = function (list, item) { 426 | return list.push(item); 427 | }; 428 | 429 | var t2 = incer(list); 430 | 431 | assert.ok(t2 instanceof Immutable.List, "result is a list"); 432 | 433 | assert.ok(t2.equals(Immutable.List.of(2, 3, 4, 5)), "transformed list was returned"); 434 | 435 | var t3 = filter(isEven)(incer)(incer)(incer)(list); 436 | 437 | assert.ok(t3.equals(Immutable.List.of(5, 7)), "composed transform works fine"); 438 | }); 439 | 440 | test("immutable map", function (assert) { 441 | var f = map(function (_ref) { 442 | var _ref2 = _slicedToArray(_ref, 2); 443 | 444 | var key = _ref2[0]; 445 | var value = _ref2[1]; 446 | return [key.toUpperCase(), value * value]; 447 | }); 448 | 449 | var m1 = Immutable.Map({ x: 1, y: 2 }); 450 | 451 | var t1 = f(m1); 452 | 453 | assert.notOk(t1 instanceof Immutable.Map, "result is not a map"); 454 | 455 | assert.deepEqual([].concat(_toConsumableArray(t1)), [["X", 1], ["Y", 4]], "result is transformed iterator"); 456 | 457 | Immutable.Map.prototype[init.symbol] = function () { 458 | return Immutable.Map().asMutable(); 459 | }; 460 | 461 | Immutable.Map.prototype[result.symbol] = function (map) { 462 | return map.asImmutable(); 463 | }; 464 | 465 | Immutable.Map.prototype[step.symbol] = function (map, _ref) { 466 | var _ref2 = _slicedToArray(_ref, 2); 467 | 468 | var key = _ref2[0]; 469 | var value = _ref2[1]; 470 | return map.set(key, value); 471 | }; 472 | 473 | var t2 = f(m1); 474 | 475 | assert.ok(t2 instanceof Immutable.Map, "result is instanceof Map"); 476 | 477 | assert.ok(t2.equals(Immutable.Map({ X: 1, Y: 4 })), "map was transformed"); 478 | }); 479 | }); 480 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0L2luZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7cUJBQU8sSUFBSTtxQkFDQyxTQUFTO3FCQUNiLE1BQU0sS0FBTixNQUFNO3FCQUFFLFNBQVMsS0FBVCxTQUFTO3FCQUFFLEdBQUcsS0FBSCxHQUFHO3FCQUFFLE1BQU0sS0FBTixNQUFNO3FCQUFFLE1BQU0sS0FBTixNQUFNO3FCQUFFLEdBQUcsS0FBSCxHQUFHO3FCQUMzQyxNQUFNLEtBQU4sTUFBTTtxQkFBRSxTQUFTLEtBQVQsU0FBUztxQkFBRSxJQUFJLEtBQUosSUFBSTtxQkFBRSxTQUFTLEtBQVQsU0FBUztxQkFDbEMsSUFBSSxLQUFKLElBQUk7cUJBQUUsU0FBUyxLQUFULFNBQVM7cUJBQUUsV0FBVyxLQUFYLFdBQVc7cUJBRTVCLElBQUksS0FBSixJQUFJO3FCQUFFLElBQUksS0FBSixJQUFJO3FCQUFFLE1BQU0sS0FBTixNQUFNOzs7QUFHMUIscUJBQU0sR0FBRyxHQUFHLFVBQUEsQ0FBQzt5Q0FBSSxDQUFDLEdBQUcsQ0FBQztrQkFBQSxDQUFBO0FBQ3RCLHFCQUFNLFNBQVMsR0FBRyxVQUFBLElBQUk7eUNBQUksSUFBSSxDQUFDLFdBQVcsRUFBRTtrQkFBQSxDQUFBO0FBQzVDLHFCQUFNLFNBQVMsR0FBRyxVQUFBLElBQUk7eUNBQUksSUFBSSxDQUFDLFdBQVcsRUFBRTtrQkFBQSxDQUFBO0FBQzVDLHFCQUFNLEdBQUcsR0FBRyxVQUFBLENBQUM7eUNBQUksVUFBQSxDQUFDOzBEQUFJLENBQUMsR0FBRyxDQUFDO21DQUFBO2tCQUFBLENBQUE7QUFDM0IscUJBQU0sUUFBUSxHQUFHLFVBQUEsQ0FBQzt5Q0FBSSxVQUFBLENBQUM7MERBQUksQ0FBQyxHQUFHLENBQUM7bUNBQUE7a0JBQUEsQ0FBQTtBQUNoQyxxQkFBTSxTQUFTLEdBQUcsVUFBQSxJQUFJO3lDQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDO2tCQUFBLENBQUE7QUFDOUMscUJBQU0sTUFBTSxHQUFHLFVBQUEsQ0FBQzt5Q0FBSSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUEsQUFBQztrQkFBQSxDQUFBO0FBQzVCLHFCQUFNLFdBQVcsR0FBRyxVQUFBLElBQUk7eUNBQUksSUFBSSxDQUFDLFdBQVcsRUFBRSxLQUFLLElBQUk7a0JBQUEsQ0FBQTtBQUN2RCxxQkFBTSxRQUFRLEdBQUcsVUFBQSxDQUFDO3lDQUFJLFVBQUEsQ0FBQzswREFBSSxDQUFDLEdBQUcsQ0FBQzttQ0FBQTtrQkFBQSxDQUFBO0FBQ2hDLHFCQUFNLFFBQVEsR0FBRyxVQUFBLENBQUM7eUNBQUksVUFBQSxDQUFDOzBEQUFJLENBQUM7bUNBQUE7a0JBQUEsQ0FBQTtBQUM1QixxQkFBTSxRQUFRLEdBQUcsVUFBQSxDQUFDO3lDQUFJLENBQUM7a0JBQUEsQ0FBQTs7QUFFdkIscUJBQU0sSUFBSSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQTtBQUMzQixxQkFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFBOztBQUU3QixxQkFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUU7QUFDZix1Q0FBSyxDQUFDLElBQUksR0FBRyxVQUFBLFFBQVEsRUFBSTtBQUN2Qix1REFBTSxLQUFLLEdBQUcsRUFBRSxDQUFBO0FBQ2hCLDBEQUFPLElBQUksRUFBRTt5RkFDVyxRQUFRLENBQUMsSUFBSSxFQUFFOzt3RUFBOUIsS0FBSyxrQkFBTCxLQUFLO3dFQUFFLElBQUksa0JBQUosSUFBSTs7QUFDbEIsd0VBQUksSUFBSSxFQUFFO0FBQ1IsNEZBQU8sS0FBSyxDQUFBO3FFQUNiLE1BQU07QUFDTCwwRkFBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQTtxRUFDbEI7b0RBQ0Y7bUNBQ0YsQ0FBQTtrQkFDRjs7QUFFRCxxQkFBSSxDQUFDLEtBQUssRUFBRSxVQUFBLE1BQU0sRUFBSTtBQUNwQixzQ0FBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFBOztBQUV0Qix3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUNuQixDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUNaLDJCQUEyQixDQUFDLENBQUE7O0FBRTdDLHdDQUFNLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQ1gsK0JBQStCLENBQUMsQ0FBQTs7QUFFakQsd0NBQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFDakIsd0JBQXdCLENBQUMsQ0FBQTs7QUFFMUMsd0NBQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxBQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQUFBQyxFQUN2Qix1QkFBdUIsQ0FBQyxDQUFBOztBQUV6Qyx3Q0FBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQ3ZCLE9BQU8sRUFDUCw0QkFBNEIsQ0FBQyxDQUFBOztBQUUxQyxzQ0FBTSxRQUFRLEdBQUcsU0FBUyxDQUFDLFFBQVEsQ0FBQyxFQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBQyxDQUFDLENBQUE7O0FBRWpELHdDQUFNLENBQUMsU0FBUyw4QkFBSyxLQUFLLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQzVCLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUNOLG9DQUFvQyxDQUFDLENBQUE7O0FBRXRELHdDQUFNLENBQUMsU0FBUyw4QkFBSyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDLElBQ25DLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUNWLG9DQUFvQyxDQUFDLENBQUE7O0FBRXRELHdDQUFNLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFDL0IsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUNoQixzQkFBc0IsQ0FBQyxDQUFBO2tCQUN6QyxDQUFDLENBQUE7O0FBRUYscUJBQUksQ0FBQyxRQUFRLEVBQUUsVUFBQSxNQUFNLEVBQUk7QUFDdkIsc0NBQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQTs7QUFFNUIsd0NBQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFDM0IsNkJBQTZCLENBQUMsQ0FBQTs7QUFFL0Msd0NBQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQ3ZCLDJCQUEyQixDQUFDLENBQUE7O0FBRTdDLHdDQUFNLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQ1gseUNBQXlDLENBQUMsQ0FBQTs7QUFFM0Qsd0NBQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFDWCxnQ0FBZ0MsQ0FBQyxDQUFBOztBQUVsRCx3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxFQUN4QiwyQ0FBMkMsQ0FBQyxDQUFBOztBQUU3RCx3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLEFBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxBQUFDLEVBQy9CLDJDQUEyQyxDQUFDLENBQUE7O0FBRTdELHdDQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQyxhQUFhLENBQUMsRUFBRSxXQUFXLEVBQy9DLGdDQUFnQyxDQUFDLENBQUE7O0FBRWxELHNDQUFNLFFBQVEsR0FBRyxTQUFTLENBQUMsUUFBUSxDQUFDLEVBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUMsQ0FBQyxDQUFBOztBQUV2RCx3Q0FBTSxDQUFDLFNBQVMsOEJBQUssS0FBSyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUM1QixDQUFDLENBQUMsQ0FBQyxFQUNILHdCQUF3QixDQUFDLENBQUE7O0FBRTFDLHdDQUFNLENBQUMsU0FBUyw4QkFBSyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDLElBQ3hDLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUNWLHNCQUFzQixDQUFDLENBQUE7a0JBQ3pDLENBQUMsQ0FBQTs7QUFJRixxQkFBSSxDQUFDLFFBQVEsRUFBRSxVQUFBLE1BQU0sRUFBSTtBQUN2QixzQ0FBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFBO0FBQzNCLHNDQUFNLGNBQWMsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUE7O0FBRTFDLHdDQUFNLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQ2xCLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUNOLG9CQUFvQixDQUFDLENBQUE7O0FBRXRDLHdDQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFDbEIsSUFBSSxFQUNKLDhCQUE4QixDQUFDLENBQUE7O0FBRWhELHdDQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFDbkIsSUFBSSxFQUNKLDhCQUE4QixDQUFDLENBQUE7O0FBRWhELHdDQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxLQUFLLENBQUMsQUFBQyxDQUFDLEVBQ3JCLEtBQUssQ0FBQyxBQUFDLEVBQ1AsOEJBQThCLENBQUMsQ0FBQTs7QUFFaEQsd0NBQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssQ0FBQyxBQUFDLENBQUMsRUFDdEIsS0FBSyxDQUFDLEFBQUMsRUFDUCw4QkFBOEIsQ0FBQyxDQUFBOztBQUVoRCx3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsVUFBQSxDQUFDOzBEQUFJLENBQUMsR0FBRyxDQUFDO21DQUFBLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFDckIsQ0FBQyxFQUNELG9DQUFvQyxDQUFDLENBQUE7O0FBRXRELHdDQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxVQUFBLENBQUM7MERBQUksQ0FBQyxHQUFHLENBQUM7bUNBQUEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUNyQixDQUFDLEVBQ0QsMENBQTBDLENBQUMsQ0FBQTs7QUFFNUQsd0NBQU0sQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLGFBQWEsQ0FBQyxFQUM3QixJQUFJLEVBQ0osMEJBQTBCLENBQUMsQ0FBQTs7QUFFNUMsd0NBQU0sQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxFQUN2QixFQUFFLEVBQ0YsbUJBQW1CLENBQUMsQ0FBQTs7QUFFckMsc0NBQU0sUUFBUSxHQUFHLFNBQVMsQ0FBQyxRQUFRLENBQUMsRUFBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBQyxDQUFDLENBQUE7O0FBRXZELHdDQUFNLENBQUMsU0FBUyw4QkFBSyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQzNCLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUNOLHVCQUF1QixDQUFDLENBQUE7a0JBQzFDLENBQUMsQ0FBQTs7QUFFRixxQkFBSSxDQUFDLE1BQU0sRUFBRSxVQUFBLE1BQU0sRUFBSTtBQUNyQix3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFDeEIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUNULG1CQUFtQixDQUFDLENBQUE7O0FBRXJDLHdDQUFNLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQ3JCLEVBQUUsRUFDRixrQkFBa0IsQ0FBQyxDQUFBOztBQUVwQyx3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQ1gsRUFBRSxFQUNGLGlCQUFpQixDQUFDLENBQUE7O0FBRW5DLHdDQUFNLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQ3JCLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQ1osaUJBQWlCLENBQUMsQ0FBQTs7QUFFbkMsd0NBQU0sQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQ25CLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFDVCxpQkFBaUIsQ0FBQyxDQUFBOztBQUVuQyx3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQ1YsQ0FBQyxFQUNELHdCQUF3QixDQUFDLENBQUE7QUFDMUMsd0NBQU0sQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUNWLENBQUMsRUFDRCx1QkFBdUIsQ0FBQyxDQUFBOztBQUV6Qyx3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQ2hCLElBQUksRUFDSiwrQkFBK0IsQ0FBQyxDQUFBOztBQUVqRCx3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQ2hCLEVBQUUsRUFDRixtQkFBbUIsQ0FBQyxDQUFBOztBQUVyQyx3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQ1gsRUFBRSxFQUNGLGlCQUFpQixDQUFDLENBQUE7O0FBRW5DLHdDQUFNLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFDYixJQUFJLENBQUMsQ0FBQTs7QUFFdEIsd0NBQU0sQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUNiLElBQUksQ0FBQyxDQUFBOztBQUV0Qix3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEFBQUMsQ0FBQyxFQUNoQixLQUFLLENBQUMsQUFBQyxDQUFDLENBQUE7O0FBRXpCLHdDQUFNLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQUFBQyxDQUFDLEVBQ2hCLEtBQUssQ0FBQyxBQUFDLENBQUMsQ0FBQTs7QUFHekIsc0NBQU0sUUFBUSxHQUFHLFNBQVMsQ0FBQyxRQUFRLENBQUMsRUFBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUMsQ0FBQyxDQUFBOztBQUVqRCx3Q0FBTSxDQUFDLFNBQVMsOEJBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUM5QixDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFDTixTQUFTLENBQUMsQ0FBQTs7QUFFM0Isd0NBQU0sQ0FBQyxTQUFTLDhCQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUMsSUFDOUIsQ0FBQyxDQUFDLENBQUMsRUFDSCxlQUFlLENBQUMsQ0FBQTs7QUFFakMsd0NBQU0sQ0FBQyxTQUFTLDhCQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUMsSUFDOUIsRUFBRSxFQUNGLGFBQWEsQ0FBQyxDQUFBO2tCQUNoQyxDQUFDLENBQUE7O0FBRUYscUJBQUksQ0FBQyxXQUFXLEVBQUUsVUFBQSxNQUFNLEVBQUk7QUFDMUIsd0NBQU0sQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQ3pDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFBOztBQUU3Qix3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUNyQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUE7O0FBRS9CLHdDQUFNLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFDakMsRUFBRSxDQUFDLENBQUE7O0FBRXBCLHdDQUFNLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFDMUIsRUFBRSxDQUFDLENBQUE7O0FBRXBCLHdDQUFNLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQTtBQUN4Qyx3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUE7O0FBR3ZDLHdDQUFNLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQTtBQUM3Qyx3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUE7O0FBRzlDLHdDQUFNLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxLQUFLLENBQUMsQUFBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLEFBQUMsQ0FBQyxDQUFBO0FBQ25ELHdDQUFNLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsQUFBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLEFBQUMsQ0FBQyxDQUFBOztBQUVwRCx3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLENBQUMsZ0JBQWdCLENBQUMsRUFDeEMsS0FBSyxDQUFDLENBQUE7QUFDdkIsd0NBQU0sQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxFQUNsQyxVQUFVLENBQUMsQ0FBQTtBQUM1Qix3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUE7QUFDekMsd0NBQU0sQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFBOztBQUUxQyxzQ0FBTSxRQUFRLEdBQUcsU0FBUyxDQUFDLFFBQVEsQ0FBQyxFQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFDLENBQUMsQ0FBQTs7QUFFeEQsd0NBQU0sQ0FBQyxTQUFTLDhCQUFLLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUMsSUFDN0MsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFBOztBQUV0Qix3Q0FBTSxDQUFDLFNBQVMsOEJBQUssU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUM3QyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQTs7QUFFNUIsd0NBQU0sQ0FBQyxTQUFTLDhCQUFLLFNBQVMsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUMsSUFDOUMsRUFBRSxDQUFDLENBQUE7a0JBQ3JCLENBQUMsQ0FBQTs7QUFFRixxQkFBSSxDQUFDLGFBQWEsRUFBRSxVQUFBLE1BQU0sRUFBSTtBQUM1Qix3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQy9CLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUNmLDJCQUEyQixDQUFDLENBQUE7O0FBRTdDLHdDQUFNLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFD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QUUzQyx3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUE7O0FBRWpDLHdDQUFNLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQTs7QUFFckMsd0NBQU0sQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFBOztBQUVyQyx3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEFBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxBQUFDLENBQUMsQ0FBQTs7QUFFM0Msd0NBQU0sQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxBQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQUFBQyxDQUFDLENBQUE7O0FBRzNDLHNDQUFNLFFBQVEsR0FBRyxTQUFTLENBQUMsUUFBUSxDQUFDLEVBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFDLENBQUMsQ0FBQTs7QUFFakQsd0NBQU0sQ0FBQyxTQUFTLDhCQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUMsSUFDOUIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQTs7QUFFeEIsd0NBQU0sQ0FBQyxTQUFTLDhCQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUMsSUFDOUIsQ0FBQyxDQUFDLENBQUMsRUFDSCxZQUFZLENBQUMsQ0FBQTs7QUFFOUIsd0NBQU0sQ0FBQyxTQUFTLDhCQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUMsSUFDOUIsRUFBRSxFQUNGLFdBQVcsQ0FBQyxDQUFB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Q0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUN0QyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBOztBQUVoRCx3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQTs7QUFFL0Msd0NBQU0sQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFBOztBQUV0Qyx3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUE7QUFDcEMsd0NBQU0sQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFBOztBQUVoRCx3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUE7QUFDMUMsd0NBQU0sQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxBQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQUFBQyxDQUFDLENBQUE7O0FBRWhELHNDQUFNLFFBQVEsR0FBRyxTQUFTLENBQUMsUUFBUSxDQUFDLEVBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUMsQ0FBQyxDQUFBOztBQUV4RCx3Q0FBTSxDQUFDLFNBQVMsOEJBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUNuQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFBO2tCQUNqQyxDQUFDLENBQUE7OztBQUdGLHFCQUFJLENBQUMsYUFBYSxFQUFFLFVBQUEsTUFBTSxFQUFJLEVBQzdCLENBQUMsQ0FBQTs7QUFFRixxQkFBSSxDQUFDLEtBQUssRUFBRSxVQUFBLE1BQU0sRUFBSTtBQUNwQix3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFDMUIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQTs7QUFFakMsd0NBQU0sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFBO0FBQzdCLHdDQUFNLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQTtBQUMzQyx3Q0FBTSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUE7QUFDakMsd0NBQU0sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxBQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQUFBQyxDQUFDLENBQUE7QUFDdkMsd0NBQU0sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FB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Q0FBQyxNQUFNLENBQUMsR0FBRzswREFDckMsU0FBUyxDQUFDLEdBQUcsRUFBRSxDQUFDLFNBQVMsRUFBRTttQ0FBQSxDQUFBOztBQUU3QiwyQ0FBUyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLFVBQUMsR0FBRzswREFDM0MsR0FBRyxDQUFDLFdBQVcsRUFBRTttQ0FBQSxDQUFBOztBQUVuQiwyQ0FBUyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLFVBQUMsR0FBRzs7O3VEQUFHLEdBQUc7dURBQUUsS0FBSzswREFDdEQsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDO21DQUFBLENBQUE7O0FBR3JCLHNDQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUE7O0FBR2hCLHdDQUFNLENBQUMsRUFBRSxDQUFDLEVBQUUsWUFBWSxTQUFTLENBQUMsR0FBRyxFQUMzQiwwQkFBMEIsQ0FBQyxDQUFBOztBQUdyQyx3Q0FBTSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsRUFBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUMsQ0FBQyxDQUFDLEVBQ3RDLHFCQUFxQixDQUFDLENBQUE7a0JBQ2pDLENBQUMsQ0FBQSIsImZpbGUiOiJzcmMvdGVzdC9pbmRleC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0ZXN0IGZyb20gXCIuL3Rlc3RcIlxuaW1wb3J0ICogYXMgSW1tdXRhYmxlIGZyb20gXCJpbW11dGFibGVcIlxuaW1wb3J0IHtyZWR1Y2UsIHRyYW5zZHVjZSwgbWFwLCBmaWx0ZXIsIHJlbW92ZSwgY2F0LFxuICAgICAgICBtYXBjYXQsIHBhcnRpdGlvbiwgdGFrZSwgdGFrZVdoaWxlLFxuICAgICAgICBkcm9wLCBkcm9wV2hpbGUsIGRyb3BSZXBlYXRzLFxuXG4gICAgICAgIGluaXQsIHN0ZXAsIHJlc3VsdH0gZnJvbSBcIi4uLy4uL1wiXG5cbi8vIHV0aWxpdHlcbmNvbnN0IGluYyA9IHggPT4geCArIDFcbmNvbnN0IHVwcGVyQ2FzZSA9IGNoYXIgPT4gY2hhci50b1VwcGVyQ2FzZSgpXG5jb25zdCBsb3dlckNhc2UgPSBjaGFyID0+IGNoYXIudG9Mb3dlckNhc2UoKVxuY29uc3QgYWRkID0geCA9PiB5ID0+IHggKyB5XG5jb25zdCBtdWx0aXBseSA9IHggPT4geSA9PiB4ICogeVxuY29uc3Qgc3RyaW5naWZ5ID0ganNvbiA9PiBKU09OLnN0cmluZ2lmeShqc29uKVxuY29uc3QgaXNFdmVuID0geCA9PiAhKHggJSAyKVxuY29uc3QgaXNMb3dlckNhc2UgPSBjaGFyID0+IGNoYXIudG9Mb3dlckNhc2UoKSA9PT0gY2hhclxuY29uc3QgbGVzc1RoYW4gPSB4ID0+IHkgPT4geSA8IHhcbmNvbnN0IGNvbnN0YW50ID0geCA9PiBfID0+IHhcbmNvbnN0IGlkZW50aXR5ID0geCA9PiB4XG5cbmNvbnN0IFRydWUgPSBjb25zdGFudCh0cnVlKVxuY29uc3QgRmFsc2UgPSBjb25zdGFudChmYWxzZSlcblxuaWYgKCFBcnJheS5mcm9tKSB7XG4gIEFycmF5LmZyb20gPSBpdGVyYXRvciA9PiB7XG4gICAgY29uc3QgYXJyYXkgPSBbXVxuICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICBjb25zdCB7dmFsdWUsIGRvbmV9ID0gaXRlcmF0b3IubmV4dCgpXG4gICAgICBpZiAoZG9uZSkge1xuICAgICAgICByZXR1cm4gYXJyYXlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFycmF5LnB1c2godmFsdWUpXG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbnRlc3QoXCJtYXBcIiwgYXNzZXJ0ID0+IHtcbiAgY29uc3QgaW5jZXIgPSBtYXAoaW5jKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwoaW5jZXIoWzEsIDIsIDMsIDRdKSxcbiAgICAgICAgICAgICAgICAgICBbMiwgMywgNCwgNV0sXG4gICAgICAgICAgICAgICAgICAgXCJhcnJheSBlbGVtZW50cyBnZXQgbWFwcGVkXCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChpbmNlcigwKSwgMSxcbiAgICAgICAgICAgICAgICAgICBcImZ1bmN0aW9uIGlzIGFwcGxpZWQgdG8gbnVtYmVyXCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChpbmNlcihudWxsKSwgbnVsbCxcbiAgICAgICAgICAgICAgICAgICBcIm1hcCBvdmVyIG51bGwgaXMgbm8gb3BcIilcblxuICBhc3NlcnQuZGVlcEVxdWFsKGluY2VyKHZvaWQoMCkpLCB2b2lkKDApLFxuICAgICAgICAgICAgICAgICAgIFwibWFwIG92ZXIgdm9pZCBpcyB2b2lkXCIpXG5cbiAgYXNzZXJ0LmVxdWFsKG1hcCh1cHBlckNhc2UpKFwiSGVsbG9cIiksXG4gICAgICAgICAgICAgICBcIkhFTExPXCIsXG4gICAgICAgICAgICAgICBcInN0cmluZ3MgY2FuIGJlIG1hcHBlZCBvdmVyXCIpXG5cbiAgY29uc3QgaXRlcmF0b3IgPSBJbW11dGFibGUuSXRlcmFibGUoe3g6IDEsIHk6IDJ9KVxuXG4gIGFzc2VydC5kZWVwRXF1YWwoWy4uLmluY2VyKGl0ZXJhdG9yLnZhbHVlcygpKV0sXG4gICAgICAgICAgICAgICAgICAgWzIsIDNdLFxuICAgICAgICAgICAgICAgICAgIFwiaXRlcmFibGUgbWFrZXMgbGF6eSB0cmFuc2Zvcm1hdGlvblwiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwoWy4uLm1hcCh1cHBlckNhc2UpKGl0ZXJhdG9yLmtleXMoKSldLFxuICAgICAgICAgICAgICAgICAgIFtcIlhcIiwgXCJZXCJdLFxuICAgICAgICAgICAgICAgICAgIFwiaXRlcmFibGUgbWFrZXMgbGF6eSB0cmFuc2Zvcm1hdGlvblwiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwobWFwKGlkZW50aXR5KShbWzEsIDJdLCBbMywgNF1dKSxcbiAgICAgICAgICAgICAgICAgICBbWzEsIDJdLCBbMywgNF1dLFxuICAgICAgICAgICAgICAgICAgIFwibWFwIGRvZXMgbm90IGV4cGFuZHNcIilcbn0pXG5cbnRlc3QoXCJmaWx0ZXJcIiwgYXNzZXJ0ID0+IHtcbiAgY29uc3QgZXZlbnMgPSBmaWx0ZXIoaXNFdmVuKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwoZXZlbnMoWzEsIDIsIDMsIDRdKSwgWzIsIDRdLFxuICAgICAgICAgICAgICAgICAgIFwiYXJyYXkgZWxlbWVudHMgZ290IGZpbHRlcmVkXCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChldmVucyhbMSwgMywgNSwgN10pLCBbXSxcbiAgICAgICAgICAgICAgICAgICBcImZpbHRlcmVkIG91dCBhbGwgZWxlbWVudHNcIilcblxuICBhc3NlcnQuZGVlcEVxdWFsKGV2ZW5zKDcpLCAwLFxuICAgICAgICAgICAgICAgICAgIFwiZmlsdGVyZWQgb3V0IG9kZCBudW1iZXIgdG8gZW1wdHkgbnVtYmVyXCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChldmVucyg2KSwgNixcbiAgICAgICAgICAgICAgICAgICBcIm51bWJlciB3YXMga2VwdCBhcyBpdCB3YXMgZXZlblwiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwoZmlsdGVyKFRydWUpKG51bGwpLCBudWxsLFxuICAgICAgICAgICAgICAgICAgIFwibnVsbCByZW1haW5zIG51bGwgcmVnYXJkbGVzcyBvZiBvcGVyYXRpb25cIilcblxuICBhc3NlcnQuZGVlcEVxdWFsKGZpbHRlcihGYWxzZSkodm9pZCgwKSksIHZvaWQoMCksXG4gICAgICAgICAgICAgICAgICAgXCJ2b2lkIHJlbWFpbnMgdm9pZCByZWdhcmRsZXNzIG9mIG9wZXJhdGlvblwiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwoZmlsdGVyKGlzTG93ZXJDYXNlKShcIkhlbGxvIFdvcmxkXCIpLCBcImVsbG8gb3JsZFwiLFxuICAgICAgICAgICAgICAgICAgIFwiZmlsdGVycyBvdXQgdXBwZXIgY2FzZSBsZXR0ZXJzXCIpXG5cbiAgY29uc3QgaXRlcmF0b3IgPSBJbW11dGFibGUuSXRlcmFibGUoe3g6IDEsIFk6IDIsIHo6IDN9KVxuXG4gIGFzc2VydC5kZWVwRXF1YWwoWy4uLmV2ZW5zKGl0ZXJhdG9yLnZhbHVlcygpKV0sXG4gICAgICAgICAgICAgICAgICAgWzJdLFxuICAgICAgICAgICAgICAgICAgIFwiZmlsdGVyIHZhbHVlIGl0ZXJhdG9yc1wiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwoWy4uLmZpbHRlcihpc0xvd2VyQ2FzZSkoaXRlcmF0b3Iua2V5cygpKV0sXG4gICAgICAgICAgICAgICAgICAgW1wieFwiLCBcInpcIl0sXG4gICAgICAgICAgICAgICAgICAgXCJmaWx0ZXIga2V5IGl0ZXJhdG9yc1wiKVxufSlcblxuXG5cbnRlc3QoXCJyZW1vdmVcIiwgYXNzZXJ0ID0+IHtcbiAgY29uc3Qgb2RkcyA9IHJlbW92ZShpc0V2ZW4pXG4gIGNvbnN0IHVwcGVyQ2FzZUNoYXJzID0gcmVtb3ZlKGlzTG93ZXJDYXNlKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwob2RkcyhbMSwgMiwgMywgNF0pLFxuICAgICAgICAgICAgICAgICAgIFsxLCAzXSxcbiAgICAgICAgICAgICAgICAgICBcImV2ZW5zIHdlcmUgcmVtb3ZlZFwiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwocmVtb3ZlKFRydWUpKG51bGwpLFxuICAgICAgICAgICAgICAgICAgIG51bGwsXG4gICAgICAgICAgICAgICAgICAgXCJ0cmFuc2R1Y2luZyBudWxsIHJldHVybiBudWxsXCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChyZW1vdmUoRmFsc2UpKG51bGwpLFxuICAgICAgICAgICAgICAgICAgIG51bGwsXG4gICAgICAgICAgICAgICAgICAgXCJ0cmFuc2R1Y2luZyBudWxsIHJldHVybiBudWxsXCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChyZW1vdmUoVHJ1ZSkodm9pZCgwKSksXG4gICAgICAgICAgICAgICAgICAgdm9pZCgwKSxcbiAgICAgICAgICAgICAgICAgICBcInRyYW5zZHVjaW5nIHZvaWQgcmV0dXJuIHZvaWRcIilcblxuICBhc3NlcnQuZGVlcEVxdWFsKHJlbW92ZShGYWxzZSkodm9pZCgwKSksXG4gICAgICAgICAgICAgICAgICAgdm9pZCgwKSxcbiAgICAgICAgICAgICAgICAgICBcInRyYW5zZHVjaW5nIHZvaWQgcmV0dXJuIHZvaWRcIilcblxuICBhc3NlcnQuZGVlcEVxdWFsKHJlbW92ZSh4ID0+IHggPiAwKSg3KSxcbiAgICAgICAgICAgICAgICAgICAwLFxuICAgICAgICAgICAgICAgICAgIFwicmVtb3ZpbmcgbWF0Y2hpbmcgbnVtYmVyIHJldHVybnMgMFwiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwocmVtb3ZlKHggPT4geCA8IDApKDcpLFxuICAgICAgICAgICAgICAgICAgIDcsXG4gICAgICAgICAgICAgICAgICAgXCJyZW1vdmluZyB1bm1hdGNoZWQgbnVtYmVyIHJldHVybnMgbnVtYmVyXCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbCh1cHBlckNhc2VDaGFycyhcIkhlbGxvIFdvcmxkXCIpLFxuICAgICAgICAgICAgICAgICAgIFwiSFdcIixcbiAgICAgICAgICAgICAgICAgICBcInJlbW92ZXMgbG93ZXIgY2FzZSBjaGFyc1wiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwodXBwZXJDYXNlQ2hhcnMoXCJ3aGF0P1wiKSxcbiAgICAgICAgICAgICAgICAgICBcIlwiLFxuICAgICAgICAgICAgICAgICAgIFwicmVtb3ZlcyBhbGwgY2hhcnNcIilcblxuICBjb25zdCBpdGVyYXRvciA9IEltbXV0YWJsZS5JdGVyYWJsZSh7eDogMSwgWTogMiwgejogM30pXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChbLi4ub2RkcyhpdGVyYXRvci52YWx1ZXMoKSldLFxuICAgICAgICAgICAgICAgICAgIFsxLCAzXSxcbiAgICAgICAgICAgICAgICAgICBcInJlbW92ZXMgZnJvbSBpdGVyYXRvclwiKVxufSlcblxudGVzdChcImRyb3BcIiwgYXNzZXJ0ID0+IHtcbiAgYXNzZXJ0LmRlZXBFcXVhbChkcm9wKDIpKFsxLCAyLCAzLCA0LCA1XSksXG4gICAgICAgICAgICAgICAgICAgWzMsIDQsIDVdLFxuICAgICAgICAgICAgICAgICAgIFwiZHJvcHBlZCB0d28gaXRlbXNcIilcblxuICBhc3NlcnQuZGVlcEVxdWFsKGRyb3AoOSkoWzEsIDIsIDMsIDRdKSxcbiAgICAgICAgICAgICAgICAgICBbXSxcbiAgICAgICAgICAgICAgICAgICBcImRyb3BlcyBhbGwgaXRlbXNcIilcblxuICBhc3NlcnQuZGVlcEVxdWFsKGRyb3AoNykoW10pLFxuICAgICAgICAgICAgICAgICAgIFtdLFxuICAgICAgICAgICAgICAgICAgIFwibm90aGluZyB0byBkcm9wXCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChkcm9wKDApKFsxLCAyLCAzLCA0XSksXG4gICAgICAgICAgICAgICAgICAgWzEsIDIsIDMsIDRdLFxuICAgICAgICAgICAgICAgICAgIFwibm8gbmVlZCB0byBkcm9wXCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChkcm9wKC03KShbMSwgMiwgM10pLFxuICAgICAgICAgICAgICAgICAgIFsxLCAyLCAzXSxcbiAgICAgICAgICAgICAgICAgICBcIm5vIG5lZWQgdG8gZHJvcFwiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwoZHJvcCgwKSgxKSxcbiAgICAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgICAgIFwibnVtYmVyIHdhcyBub3QgZHJvcHBlZFwiKVxuICBhc3NlcnQuZGVlcEVxdWFsKGRyb3AoNSkoOCksXG4gICAgICAgICAgICAgICAgICAgMCxcbiAgICAgICAgICAgICAgICAgICBcIm51bWJlciB3YXMgcmVzZXQgdG8gMFwiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwoZHJvcCgzKShcImhlbGxvXCIpLFxuICAgICAgICAgICAgICAgICAgIFwibG9cIixcbiAgICAgICAgICAgICAgICAgICBcInRocmVlIGNoYXJhY3RlcnMgd2VyZSBkcm9wcGVkXCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChkcm9wKDkpKFwiaGVsbG9cIiksXG4gICAgICAgICAgICAgICAgICAgXCJcIixcbiAgICAgICAgICAgICAgICAgICBcImRyb3BwZWQgYWxsIGNoYXJzXCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChkcm9wKDgpKFwiXCIpLFxuICAgICAgICAgICAgICAgICAgIFwiXCIsXG4gICAgICAgICAgICAgICAgICAgXCJub3RoaW5nIHRvIGRyb3BcIilcblxuICBhc3NlcnQuZGVlcEVxdWFsKGRyb3AoOSkobnVsbCksXG4gICAgICAgICAgICAgICAgICAgbnVsbClcblxuICBhc3NlcnQuZGVlcEVxdWFsKGRyb3AoMCkobnVsbCksXG4gICAgICAgICAgICAgICAgICAgbnVsbClcblxuICBhc3NlcnQuZGVlcEVxdWFsKGRyb3AoOCkodm9pZCgwKSksXG4gICAgICAgICAgICAgICAgICAgdm9pZCgwKSlcblxuICBhc3NlcnQuZGVlcEVxdWFsKGRyb3AoMCkodm9pZCgwKSksXG4gICAgICAgICAgICAgICAgICAgdm9pZCgwKSlcblxuXG4gIGNvbnN0IGl0ZXJhdG9yID0gSW1tdXRhYmxlLkl0ZXJhYmxlKHt4OiAxLCB5OiAyfSlcblxuICBhc3NlcnQuZGVlcEVxdWFsKFsuLi5kcm9wKDApKGl0ZXJhdG9yLnZhbHVlcygpKV0sXG4gICAgICAgICAgICAgICAgICAgWzEsIDJdLFxuICAgICAgICAgICAgICAgICAgIFwiMCBkcm9wc1wiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwoWy4uLmRyb3AoMSkoaXRlcmF0b3IudmFsdWVzKCkpXSxcbiAgICAgICAgICAgICAgICAgICBbMl0sXG4gICAgICAgICAgICAgICAgICAgXCJkcm9wcGVkIGZpcnN0XCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChbLi4uZHJvcCg4KShpdGVyYXRvci52YWx1ZXMoKSldLFxuICAgICAgICAgICAgICAgICAgIFtdLFxuICAgICAgICAgICAgICAgICAgIFwiZHJvcHBlZCBhbGxcIilcbn0pXG5cbnRlc3QoXCJkcm9wV2hpbGVcIiwgYXNzZXJ0ID0+IHtcbiAgYXNzZXJ0LmRlZXBFcXVhbChkcm9wV2hpbGUobGVzc1RoYW4oOSkpKFsxLCA4LCAxMiwgOSwgNDVdKSxcbiAgICAgICAgICAgICAgICAgICBbMTIsIDksIDQ1XSlcblxuICBhc3NlcnQuZGVlcEVxdWFsKGRyb3BXaGlsZShsZXNzVGhhbig5KSkoWzEwLCA5LCA4LCA3XSksXG4gICAgICAgICAgICAgICAgICAgWzEwLCA5LCA4LCA3XSlcblxuICBhc3NlcnQuZGVlcEVxdWFsKGRyb3BXaGlsZShsZXNzVGhhbig5KSkoWzEsIDIsIDNdKSxcbiAgICAgICAgICAgICAgICAgICBbXSlcblxuICBhc3NlcnQuZGVlcEVxdWFsKGRyb3BXaGlsZShsZXNzVGhhbig5KSkoW10pLFxuICAgICAgICAgICAgICAgICAgIFtdKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwoZHJvcFdoaWxlKEZhbHNlKSg1KSwgNSlcbiAgYXNzZXJ0LmRlZXBFcXVhbChkcm9wV2hpbGUoVHJ1ZSkoNSksIDApXG5cblxuICBhc3NlcnQuZGVlcEVxdWFsKGRyb3BXaGlsZShUcnVlKShudWxsKSwgbnVsbClcbiAgYXNzZXJ0LmRlZXBFcXVhbChkcm9wV2hpbGUoRmFsc2UpKG51bGwpLCBudWxsKVxuXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChkcm9wV2hpbGUoVHJ1ZSkodm9pZCgwKSksIHZvaWQoMCkpXG4gIGFzc2VydC5kZWVwRXF1YWwodGFrZVdoaWxlKEZhbHNlKSh2b2lkKDApKSwgdm9pZCgwKSlcblxuICBhc3NlcnQuZGVlcEVxdWFsKGRyb3BXaGlsZShpc0xvd2VyQ2FzZSkoXCJuZXZlciBtaW5kIFlvdVwiKSxcbiAgICAgICAgICAgICAgICAgICBcIllvdVwiKVxuICBhc3NlcnQuZGVlcEVxdWFsKGRyb3BXaGlsZShpc0xvd2VyQ2FzZSkoXCJIaSB0aGVyZVwiKSxcbiAgICAgICAgICAgICAgICAgICBcIkhpIHRoZXJlXCIpXG4gIGFzc2VydC5kZWVwRXF1YWwoZHJvcFdoaWxlKFRydWUpKFwiXCIpLCBcIlwiKVxuICBhc3NlcnQuZGVlcEVxdWFsKGRyb3BXaGlsZShGYWxzZSkoXCJcIiksIFwiXCIpXG5cbiAgY29uc3QgaXRlcmF0b3IgPSBJbW11dGFibGUuSXRlcmFibGUoe3g6IDAsIHk6IDUsIHo6IDEwfSlcblxuICBhc3NlcnQuZGVlcEVxdWFsKFsuLi5kcm9wV2hpbGUobGVzc1RoYW4oNykpKGl0ZXJhdG9yLnZhbHVlcygpKV0sXG4gICAgICAgICAgICAgICAgICAgWzEwXSlcblxuICBhc3NlcnQuZGVlcEVxdWFsKFsuLi5kcm9wV2hpbGUobGVzc1RoYW4oMCkpKGl0ZXJhdG9yLnZhbHVlcygpKV0sXG4gICAgICAgICAgICAgICAgICAgWzAsIDUsIDEwXSlcblxuICBhc3NlcnQuZGVlcEVxdWFsKFsuLi5kcm9wV2hpbGUobGVzc1RoYW4oOTkpKShpdGVyYXRvci52YWx1ZXMoKSldLFxuICAgICAgICAgICAgICAgICAgIFtdKVxufSlcblxudGVzdChcImRyb3BSZXBlYXRzXCIsIGFzc2VydCA9PiB7XG4gIGFzc2VydC5kZWVwRXF1YWwoZHJvcFJlcGVhdHMoWzEsIDIsIDMsIDMsIDQsIDNdKSxcbiAgICAgICAgICAgICAgICAgICBbMSwgMiwgMywgNCwgM10sXG4gICAgICAgICAgICAgICAgICAgXCJyZW1vdmVkIHJlcGVhdGVkIGVsZW1lbnRzXCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChkcm9wUmVwZWF0cyhbMSwgMSwgMSwgMSwgMV0pLFxuICAgICAgICAgICAgICAgICAgIFsxXSxcbiAgICAgICAgICAgICAgICAgICBcImtlZXBzIGp1c3Qgb25lXCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChkcm9wUmVwZWF0cygxKSxcbiAgICAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgICAgIFwibnVtYmVyIGhhcyBubyByZXBlYXRzXCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChkcm9wUmVwZWF0cyhudWxsKSxcbiAgICAgICAgICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAgICAgICAgIFwibnVsbCB0cmFuc2Zyb21lZCBpcyBudWxsXCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChkcm9wUmVwZWF0cyh2b2lkKDApKSxcbiAgICAgICAgICAgICAgICAgICB2b2lkKDApLFxuICAgICAgICAgICAgICAgICAgIFwidm9pZCB0cmFuc2Zyb21lZCBpcyB2b2lkXCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChkcm9wUmVwZWF0cyhcIndoYXRcIiksXG4gICAgICAgICAgICAgICAgICAgXCJ3aGF0XCIsXG4gICAgICAgICAgICAgICAgICAgXCJub3RoaW5nIHRvIGRyb3BcIilcblxuICBhc3NlcnQuZGVlcEVxdWFsKGRyb3BSZXBlYXRzKFwiaGVsbG9cIiksXG4gICAgICAgICAgICAgICAgICAgXCJoZWxvXCIsXG4gICAgICAgICAgICAgICAgICAgXCJkcm9wZXMgcmVwZWF0ZWQgY2hhcnNcIilcblxuICBjb25zdCBpdGVyYXRvciA9IEltbXV0YWJsZS5JdGVyYWJsZSh7eDogMSwgWTogMiwgejogMn0pXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChbLi4uZHJvcFJlcGVhdHMoaXRlcmF0b3IudmFsdWVzKCkpXSxcbiAgICAgICAgICAgICAgICAgICBbMSwgMl0sXG4gICAgICAgICAgICAgICAgICAgXCJyZW1vdmVzIHJlcGVhdHMgZm9ybSBpdGVyYXRvclwiKVxufSlcblxudGVzdChcInRha2VcIiwgYXNzZXJ0ID0+IHtcbiAgYXNzZXJ0LmRlZXBFcXVhbCh0YWtlKDIpKFsxLCAyLCAzLCA0LCA1XSksXG4gICAgICAgICAgICAgICAgICAgWzEsIDJdLFxuICAgICAgICAgICAgICAgICAgIFwidG9vayB0d29cIilcblxuICBhc3NlcnQuZGVlcEVxdWFsKHRha2UoOSkoWzEsIDIsIDMsIDRdKSxcbiAgICAgICAgICAgICAgICAgICBbMSwgMiwgMywgNF0sXG4gICAgICAgICAgICAgICAgICAgXCJ0b29rIGFsbFwiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwodGFrZSg3KShbXSksXG4gICAgICAgICAgICAgICAgICAgW10sXG4gICAgICAgICAgICAgICAgICAgXCJub3RoaW5nIHRvIHRha2VcIilcblxuICBhc3NlcnQuZGVlcEVxdWFsKHRha2UoMCkoWzEsIDIsIDMsIDRdKSxcbiAgICAgICAgICAgICAgICAgICBbXSxcbiAgICAgICAgICAgICAgICAgICBcInRvb2sgMFwiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwodGFrZSgtNykoWzEsIDIsIDNdKSxcbiAgICAgICAgICAgICAgICAgICBbXSxcbiAgICAgICAgICAgICAgICAgICBcInRvb2sgbm9uZVwiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwodGFrZSgwKSgxKSwgMClcbiAgYXNzZXJ0LmRlZXBFcXVhbCh0YWtlKDUpKDgpLCA4KVxuXG4gIGFzc2VydC5kZWVwRXF1YWwodGFrZSgzKShcImhlbGxvXCIpLCBcImhlbFwiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwodGFrZSg5KShcImhlbGxvXCIpLCBcImhlbGxvXCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbCh0YWtlKDgpKFwiXCIpLCBcIlwiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwodGFrZSg5KShudWxsKSwgbnVsbClcblxuICBhc3NlcnQuZGVlcEVxdWFsKHRha2UoMCkobnVsbCksIG51bGwpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbCh0YWtlKDgpKHZvaWQoMCkpLCB2b2lkKDApKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwoZHJvcCgwKSh2b2lkKDApKSwgdm9pZCgwKSlcblxuXG4gIGNvbnN0IGl0ZXJhdG9yID0gSW1tdXRhYmxlLkl0ZXJhYmxlKHt4OiAxLCB5OiAyfSlcblxuICBhc3NlcnQuZGVlcEVxdWFsKFsuLi50YWtlKDkpKGl0ZXJhdG9yLnZhbHVlcygpKV0sXG4gICAgICAgICAgICAgICAgICAgWzEsIDJdKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwoWy4uLnRha2UoMSkoaXRlcmF0b3IudmFsdWVzKCkpXSxcbiAgICAgICAgICAgICAgICAgICBbMV0sXG4gICAgICAgICAgICAgICAgICAgXCJ0b29rIGZpcnN0XCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChbLi4udGFrZSgwKShpdGVyYXRvci52YWx1ZXMoKSldLFxuICAgICAgICAgICAgICAgICAgIFtdLFxuICAgICAgICAgICAgICAgICAgIFwidG9vayBub25lXCIpXG59KVxuXG50ZXN0KFwidGFrZVdoaWxlXCIsIGFzc2VydCA9PiB7XG4gIGNvbnN0IGRpZ2l0cyA9IHRha2VXaGlsZShsZXNzVGhhbigxMCkpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChkaWdpdHMoWzEsIDgsIDEyLCA5LCA0NV0pLFxuICAgICAgICAgICAgICAgICAgIFsxLCA4XSxcbiAgICAgICAgICAgICAgICAgICBcInRha2VzIG9ubHkgZGlnaXRzXCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChkaWdpdHMoWzEwLCA5LCA4LCA3XSksXG4gICAgICAgICAgICAgICAgICAgW10sXG4gICAgICAgICAgICAgICAgICAgXCJ0YWtlcyBub25lXCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChkaWdpdHMoNSksXG4gICAgICAgICAgICAgICAgICAgNSxcbiAgICAgICAgICAgICAgICAgICBcInRha2UgbWF0Y2hpbmcgbnVtYmVyXCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChkaWdpdHMoOTcpLFxuICAgICAgICAgICAgICAgICAgIDAsXG4gICAgICAgICAgICAgICAgICAgXCJyZXR1cm5zIDAgb24gdW5tYXRjaGVkIG51bWJlclwiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwodGFrZVdoaWxlKFRydWUpKG51bGwpLFxuICAgICAgICAgICAgICAgICAgIG51bGwsXG4gICAgICAgICAgICAgICAgICAgXCJyZXR1cm4gbnVsbFwiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwodGFrZVdoaWxlKEZhbHNlKShudWxsKSxcbiAgICAgICAgICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAgICAgICAgIFwicmV0dXJucyBudWxsXCIpXG5cblxuICBhc3NlcnQuZGVlcEVxdWFsKHRha2VXaGlsZShUcnVlKSh2b2lkKDApKSxcbiAgICAgICAgICAgICAgICAgICB2b2lkKDApLFxuICAgICAgICAgICAgICAgICAgIFwicmV0dXJuIHZvaWRcIilcblxuICBhc3NlcnQuZGVlcEVxdWFsKHRha2VXaGlsZShGYWxzZSkodm9pZCgwKSksXG4gICAgICAgICAgICAgICAgICAgdm9pZCgwKSxcbiAgICAgICAgICAgICAgICAgICBcInJldHVybiB2b2lkXCIpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbCh0YWtlV2hpbGUoaXNMb3dlckNhc2UpKFwibmV2ZXIgbWluZCBZb3VcIiksXG4gICAgICAgICAgICAgICAgICAgXCJuZXZlciBtaW5kIFwiLFxuICAgICAgICAgICAgICAgICAgIFwidGFrZXMgdW50aWwgdXBwZXIgY2FzZVwiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwodGFrZVdoaWxlKGlzTG93ZXJDYXNlKShcIkhpIHRoZXJlXCIpLFxuICAgICAgICAgICAgICAgICAgIFwiXCIsXG4gICAgICAgICAgICAgICAgICAgXCJibGFuayBzdHJpbmdcIilcblxuICBjb25zdCBpdGVyYXRvciA9IEltbXV0YWJsZS5JdGVyYWJsZSh7eDogMCwgeTogNSwgejogMTB9KVxuXG4gIGFzc2VydC5kZWVwRXF1YWwoWy4uLnRha2VXaGlsZShsZXNzVGhhbig3KSkoaXRlcmF0b3IudmFsdWVzKCkpXSxcbiAgICAgICAgICAgICAgICAgICBbMCwgNV0sXG4gICAgICAgICAgICAgICAgICAgXCJyZW1vdmVzIHJlcGVhdHMgZm9ybSBpdGVyYXRvclwiKVxufSlcblxudGVzdChcInBhcnRpdGlvblwiLCBhc3NlcnQgPT4ge1xuICBhc3NlcnQuZGVlcEVxdWFsKHBhcnRpdGlvbigyKShbMSwgMiwgMywgNCwgNSwgNiwgNywgOF0pLFxuICAgICAgICAgICAgICAgICAgIFtbMSwgMl0sIFszLCA0XSwgWzUsIDZdLCBbNywgOF1dKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwocGFydGl0aW9uKDMpKFsxLCAyLCAzLCA0LCA1LCA2LCA3LCA4XSksXG4gICAgICAgICAgICAgICAgICAgW1sxLCAyLCAzXSwgWzQsIDUsIDZdLCBbNywgOF1dKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwocGFydGl0aW9uKDQpKFsxLCAyXSksW1sxLCAyXV0pXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChwYXJ0aXRpb24oMykoW10pLCBbXSlcblxuICBhc3NlcnQuZGVlcEVxdWFsKHBhcnRpdGlvbigzKSg5KSwgOSlcbiAgYXNzZXJ0LmRlZXBFcXVhbChwYXJ0aXRpb24oMikoXCJoZWxsb1wiKSwgXCJoZWxsb1wiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwocGFydGl0aW9uKDIpKG51bGwpLCBudWxsKVxuICBhc3NlcnQuZGVlcEVxdWFsKHBhcnRpdGlvbigyKSh2b2lkKDApKSwgdm9pZCgwKSlcblxuICBjb25zdCBpdGVyYXRvciA9IEltbXV0YWJsZS5JdGVyYWJsZSh7eDogMCwgeTogNSwgejogMTB9KVxuXG4gIGFzc2VydC5kZWVwRXF1YWwoWy4uLnBhcnRpdGlvbigyKShpdGVyYXRvci52YWx1ZXMoKSldLFxuICAgICAgICAgICAgICAgICAgIFtbMCwgNV0sIFsxMF1dKVxufSlcblxuLy8gVE9ETzohXG50ZXN0KFwicGFydGl0aW9uQnlcIiwgYXNzZXJ0ID0+IHtcbn0pXG5cbnRlc3QoXCJjYXRcIiwgYXNzZXJ0ID0+IHtcbiAgYXNzZXJ0LmRlZXBFcXVhbChjYXQoW1sxLCAyXSwgWzNdLCBbNCwgNV1dKSxcbiAgICAgICAgICAgICAgICAgICBbMSwgMiwgMywgNCwgNV0pXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChjYXQoW10pLCBbXSlcbiAgYXNzZXJ0LmRlZXBFcXVhbChjYXQoWzEsIDIsIDNdKSwgWzEsIDIsIDNdKVxuICBhc3NlcnQuZGVlcEVxdWFsKGNhdChudWxsKSwgbnVsbClcbiAgYXNzZXJ0LmRlZXBFcXVhbChjYXQodm9pZCgwKSksIHZvaWQoMCkpXG4gIGFzc2VydC5kZWVwRXF1YWwoY2F0KDQpLCA0KVxuICBhc3NlcnQuZGVlcEVxdWFsKGNhdChcImhlbGxvXCIpLCBcImhlbGxvXCIpXG5cbiAgY29uc3QgdmFsdWVJdGVyID0gSW1tdXRhYmxlLkl0ZXJhYmxlKFswLCA1LCAxMF0pLnZhbHVlcygpXG5cbiAgYXNzZXJ0LmRlZXBFcXVhbChbLi4uY2F0KHZhbHVlSXRlcildLFxuICAgICAgICAgICAgICAgICAgIFswLCA1LCAxMF0pXG5cbiAgY29uc3QgYXJyYXlJdGVyID0gSW1tdXRhYmxlLkl0ZXJhYmxlKFtbMSwgMl0sIFszXSwgWzQsIDUsIDZdXSkudmFsdWVzKClcbiAgYXNzZXJ0LmRlZXBFcXVhbChbLi4uY2F0KGFycmF5SXRlcildLFxuICAgICAgICAgICAgICAgICAgIFsxLCAyLCAzLCA0LCA1LCA2XSlcbn0pXG5cbnRlc3QoXCJtYXBjYXRcIiwgYXNzZXJ0ID0+IHtcbiAgYXNzZXJ0LmRlZXBFcXVhbCgobWFwKHggPT4geC5zcGxpdChcIi9cIikpKVxuICAgICAgICAgICAgICAgICAgIChjYXQpXG4gICAgICAgICAgICAgICAgICAgKFtcInBhdGgvdG9cIiwgXCJkaXIvZmlsZVwiXSksXG4gICAgICAgICAgICAgICAgICAgW1wicGF0aFwiLCBcInRvXCIsIFwiZGlyXCIsIFwiZmlsZVwiXSlcbn0pXG5cbnRlc3QoXCJjb21wb3NpdGlvblwiLCBhc3NlcnQgPT4ge1xuICBjb25zdCBpbmNlciA9IG1hcChpbmMpXG4gIGNvbnN0IGFkZDIgPSBpbmNlcihpbmNlcilcblxuICBhc3NlcnQuZXF1YWwodHlwZW9mKGFkZDIpLCBcImZ1bmN0aW9uXCIsXG4gICAgICAgICAgICAgICBcInBhc3NpbmcgdHJhbnNkdWNlciB0byB0cmFuc2R1Y2VyIGNvbXBvc2VzIGEgbmV3IG9uZVwiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwoYWRkMihbMSwgMiwgMywgNF0pLFxuICAgICAgICAgICAgICAgICAgIFszLCA0LCA1LCA2XSxcbiAgICAgICAgICAgICAgICAgICBcImFycmF5IGVsZW1lbnRzIGdldCBtYXBwZWRcIilcblxuICBhc3NlcnQuZGVlcEVxdWFsKGFkZDIoMCksIDIsXG4gICAgICAgICAgICAgICAgICAgXCJmdW5jdGlvbiBpcyBhcHBsaWVkIHRvIG51bWJlclwiKVxuXG4gIGFzc2VydC5kZWVwRXF1YWwoYWRkMihudWxsKSwgbnVsbCxcbiAgICAgICAgICAgICAgICAgICBcIm1hcCBvdmVyIG51bGwgaXMgbm8gb3BcIilcblxuICBhc3NlcnQuZGVlcEVxdWFsKGFkZDIodm9pZCgwKSksIHZvaWQoMCksXG4gICAgICAgICAgICAgICAgICAgXCJtYXAgb3ZlciB2b2lkIGlzIHZvaWRcIilcblxuICBhc3NlcnQuZGVlcEVxdWFsKChmaWx0ZXIoaXNFdmVuKSlcbiAgICAgICAgICAgICAgICAgICAobWFwKGluYykpXG4gICAgICAgICAgICAgICAgICAgKFsxLCA0LCA5LCAxMF0pLFxuICAgICAgICAgICAgICAgICAgIFs1LCAxMV0pXG59KVxuXG5cbnRlc3QoXCJ0cmFzZHVjZVwiLCBhc3NlcnQgPT4ge1xuICBjb25zdCBldmVucyA9IGZpbHRlcihpc0V2ZW4pXG4gIGFzc2VydC5lcXVhbCh0cmFuc2R1Y2UoZXZlbnMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgKHgsIHkpID0+IHkgPT09IHZvaWQoMCkgPyB4IDogeCArIHksXG4gICAgICAgICAgICAgICAgICAgICAgICAgMixcbiAgICAgICAgICAgICAgICAgICAgICAgICBbMSwgMiwgMywgNF0pLFxuICAgICAgICAgICAgICAgOCxcbiAgICAgICAgICAgICAgIFwidHJhbnNkdWNlZCBhcnJheSB3aXRoIGN1c3RvbSByZWR1Y2VyXCIpXG5cbiAgYXNzZXJ0LmVxdWFsKHRyYW5zZHVjZShldmVucyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAoeCwgeSkgPT4geCA9PT0gdm9pZCgwKSA/IDAgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID09PSB2b2lkKDApID8geCA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggKyB5LFxuICAgICAgICAgICAgICAgICAgICAgICAgIFsxLCAyLCAzLCA0XSksXG4gICAgICAgICAgICAgICA2LFxuICAgICAgICAgICAgICAgXCJ0cmFuc2R1Y2VkIHdpdGhvdXQgaW5pdGlhbCB2YWx1ZVwiKVxuXG5cbiAgY29uc3QgaXRlcmF0b3IgPSBJbW11dGFibGUuSXRlcmFibGUoe3g6IDEsIFk6IDIsIHo6IDMsIHc6IDR9KVxuICBhc3NlcnQuZXF1YWwodHJhbnNkdWNlKGV2ZW5zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICh4LCB5KSA9PiB5ID09PSB2b2lkKDApID8geCA6IHggKyB5LFxuICAgICAgICAgICAgICAgICAgICAgICAgIDUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgaXRlcmF0b3IudmFsdWVzKCkpLFxuICAgICAgICAgICAgICAgMTEsXG4gICAgICAgICAgICAgIFwidHJhbnNkdWNlIGl0ZXJhdG9yIHdpdGggY3VzdG9tIHJlZHVjZXJcIilcbn0pXG5cblxudGVzdChcImltbXV0YWJsZSBsaXN0XCIsIGFzc2VydCA9PiB7XG4gIGNvbnN0IGluY2VyID0gbWFwKGluYylcbiAgY29uc3QgbGlzdCA9IEltbXV0YWJsZS5MaXN0Lm9mKDEsIDIsIDMsIDQpXG4gIGNvbnN0IHQxID0gaW5jZXIobGlzdClcblxuICBhc3NlcnQubm90T2sodDEgaW5zdGFuY2VvZiBJbW11dGFibGUuTGlzdCxcbiAgICAgICAgICAgICAgIFwicmVzdWx0IGlzIG5vdCBhIGxpc3RcIilcblxuICBhc3NlcnQuZGVlcEVxdWFsKFsuLi50MV0sXG4gICAgICAgICAgICAgICAgICAgWzIsIDMsIDQsIDVdLFxuICAgICAgICAgICAgICAgICAgIFwicmVzdWx0IGlzIGFuIGl0ZXJhdG9yXCIpXG5cbiAgSW1tdXRhYmxlLkxpc3QucHJvdG90eXBlW2luaXQuc3ltYm9sXSA9ICgpID0+XG4gICAgSW1tdXRhYmxlLkxpc3QoKS5hc011dGFibGUoKVxuXG4gIEltbXV0YWJsZS5MaXN0LnByb3RvdHlwZVtyZXN1bHQuc3ltYm9sXSA9IChsaXN0KSA9PlxuICAgIGxpc3QuYXNJbW11dGFibGUoKVxuXG4gIEltbXV0YWJsZS5MaXN0LnByb3RvdHlwZVtzdGVwLnN5bWJvbF0gPSAobGlzdCwgaXRlbSkgPT5cbiAgICBsaXN0LnB1c2goaXRlbSlcblxuXG4gIGNvbnN0IHQyID0gaW5jZXIobGlzdClcblxuXG4gIGFzc2VydC5vayh0MiBpbnN0YW5jZW9mIEltbXV0YWJsZS5MaXN0LFxuICAgICAgICAgICAgXCJyZXN1bHQgaXMgYSBsaXN0XCIpXG5cblxuICBhc3NlcnQub2sodDIuZXF1YWxzKEltbXV0YWJsZS5MaXN0Lm9mKDIsIDMsIDQsIDUpKSxcbiAgICAgICAgICAgIFwidHJhbnNmb3JtZWQgbGlzdCB3YXMgcmV0dXJuZWRcIilcblxuICBjb25zdCB0MyA9IChmaWx0ZXIoaXNFdmVuKSlcbiAgICAgICAgICAgICAoaW5jZXIpXG4gICAgICAgICAgICAgKGluY2VyKVxuICAgICAgICAgICAgIChpbmNlcilcbiAgICAgICAgICAgICAobGlzdClcblxuICBhc3NlcnQub2sodDMuZXF1YWxzKEltbXV0YWJsZS5MaXN0Lm9mKDUsIDcpKSxcbiAgICAgICAgICAgIFwiY29tcG9zZWQgdHJhbnNmb3JtIHdvcmtzIGZpbmVcIilcblxufSlcblxuXG5cblxudGVzdChcImltbXV0YWJsZSBtYXBcIiwgYXNzZXJ0ID0+IHtcbiAgY29uc3QgZiA9IG1hcCgoW2tleSwgdmFsdWVdKSA9PiBba2V5LnRvVXBwZXJDYXNlKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlICogdmFsdWVdKVxuXG4gIGNvbnN0IG0xID0gSW1tdXRhYmxlLk1hcCh7eDogMSwgeTogMn0pXG5cbiAgY29uc3QgdDEgPSBmKG0xKVxuXG4gIGFzc2VydC5ub3RPayh0MSBpbnN0YW5jZW9mIEltbXV0YWJsZS5NYXAsXG4gICAgICAgICAgICAgICBcInJlc3VsdCBpcyBub3QgYSBtYXBcIilcblxuICBhc3NlcnQuZGVlcEVxdWFsKFsuLi50MV0sXG4gICAgICAgICAgICAgICAgICAgW1tcIlhcIiwgMV0sIFtcIllcIiwgNF1dLFxuICAgICAgICAgICAgICAgICAgIFwicmVzdWx0IGlzIHRyYW5zZm9ybWVkIGl0ZXJhdG9yXCIpXG5cbiAgSW1tdXRhYmxlLk1hcC5wcm90b3R5cGVbaW5pdC5zeW1ib2xdID0gKCkgPT5cbiAgICBJbW11dGFibGUuTWFwKCkuYXNNdXRhYmxlKClcblxuICBJbW11dGFibGUuTWFwLnByb3RvdHlwZVtyZXN1bHQuc3ltYm9sXSA9IChtYXApID0+XG4gICAgbWFwLmFzSW1tdXRhYmxlKClcblxuICBJbW11dGFibGUuTWFwLnByb3RvdHlwZVtzdGVwLnN5bWJvbF0gPSAobWFwLCBba2V5LCB2YWx1ZV0pID0+XG4gICAgbWFwLnNldChrZXksIHZhbHVlKVxuXG5cbiAgY29uc3QgdDIgPSBmKG0xKVxuXG5cbiAgYXNzZXJ0Lm9rKHQyIGluc3RhbmNlb2YgSW1tdXRhYmxlLk1hcCxcbiAgICAgICAgICAgIFwicmVzdWx0IGlzIGluc3RhbmNlb2YgTWFwXCIpXG5cblxuICBhc3NlcnQub2sodDIuZXF1YWxzKEltbXV0YWJsZS5NYXAoe1g6IDEsIFk6IDR9KSksXG4gICAgICAgICAgICBcIm1hcCB3YXMgdHJhbnNmb3JtZWRcIilcbn0pXG5cblxuIl19 -------------------------------------------------------------------------------- /lib/test/test.js: -------------------------------------------------------------------------------- 1 | (function (factory) { 2 | if (typeof define === "function" && define.amd) { 3 | define(["exports", "tape"], factory); 4 | } else if (typeof exports !== "undefined") { 5 | factory(exports, require("tape")); 6 | } 7 | })(function (exports, _tape) { 8 | "use strict"; 9 | 10 | var tape = _tape; 11 | 12 | exports["default"] = function (description, unit) { 13 | return tape.test(description, function (test) { 14 | var result = unit(test); 15 | if (result && result.then) { 16 | result.then(function (_) { 17 | return test.end(); 18 | }, function (error) { 19 | return test.end(error || true); 20 | }); 21 | } else { 22 | test.end(); 23 | } 24 | }); 25 | }; 26 | }); 27 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0L3Rlc3QuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O01BQVksSUFBSTs7dUJBRUQsVUFBQyxXQUFXLEVBQUUsSUFBSTtXQUFLLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLFVBQUEsSUFBSSxFQUFJO0FBQ25FLFVBQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQTtBQUN6QixVQUFJLE1BQU0sSUFBSSxNQUFNLENBQUMsSUFBSSxFQUFFO0FBQ3pCLGNBQU0sQ0FBQyxJQUFJLENBQUMsVUFBQSxDQUFDO2lCQUFJLElBQUksQ0FBQyxHQUFHLEVBQUU7U0FBQSxFQUFFLFVBQUEsS0FBSztpQkFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUM7U0FBQSxDQUFDLENBQUE7T0FDL0QsTUFBTTtBQUNMLFlBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQTtPQUNYO0tBQ0YsQ0FBQztHQUFBIiwiZmlsZSI6InNyYy90ZXN0L3Rlc3QuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyB0YXBlIGZyb20gXCJ0YXBlXCJcblxuZXhwb3J0IGRlZmF1bHQgKGRlc2NyaXB0aW9uLCB1bml0KSA9PiB0YXBlLnRlc3QoZGVzY3JpcHRpb24sIHRlc3QgPT4ge1xuICBjb25zdCByZXN1bHQgPSB1bml0KHRlc3QpXG4gIGlmIChyZXN1bHQgJiYgcmVzdWx0LnRoZW4pIHtcbiAgICByZXN1bHQudGhlbihfID0+IHRlc3QuZW5kKCksIGVycm9yID0+IHRlc3QuZW5kKGVycm9yIHx8IHRydWUpKVxuICB9IGVsc2Uge1xuICAgIHRlc3QuZW5kKClcbiAgfVxufSlcbiJdfQ== -------------------------------------------------------------------------------- /lib/transducers.js: -------------------------------------------------------------------------------- 1 | (function (factory) { 2 | if (typeof define === "function" && define.amd) { 3 | define(["exports"], factory); 4 | } else if (typeof exports !== "undefined") { 5 | factory(exports); 6 | } 7 | })(function (exports) { 8 | "use strict"; 9 | 10 | var _slicedToArray = function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { var _arr = []; for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) { _arr.push(_step.value); if (i && _arr.length === i) break; } return _arr; } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; 11 | 12 | var _toConsumableArray = function (arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }; 13 | 14 | var _applyConstructor = function (Constructor, args) { var instance = Object.create(Constructor.prototype); var result = Constructor.apply(instance, args); return result != null && (typeof result == "object" || typeof result == "function") ? result : instance; }; 15 | 16 | var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; 17 | 18 | var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; 19 | 20 | var _createComputedClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var prop = props[i]; prop.configurable = true; if (prop.value) prop.writable = true; Object.defineProperty(target, prop.key, prop); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 21 | 22 | var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; 23 | 24 | var isSymbolDefined = typeof Symbol !== "undefined"; 25 | var symbol = isSymbolDefined && Symbol["for"] || function (hint) { 26 | return "@@" + hint; 27 | }; 28 | 29 | var $iterator = isSymbolDefined && Symbol.iterator || symbol("iterator"); 30 | 31 | var methodOf = function (target, id) { 32 | var method = target && target[id]; 33 | if (!method) { 34 | var type = typeof target; 35 | method = target === null ? NullType.prototype[id] : target === void 0 ? UndefinedType.prototype[id] : type === "string" ? StringType.prototype[id] : type === "number" ? NumberType.prototype[id] : type === "boolean" ? BooleanType.prototype[id] : type === "symbol" ? SymbolType.prototype[id] : isArray(target) ? ArrayType.prototype[id] : isIterator(target) ? IteratorType.prototype[id] : isRegExp(target) ? RegExpType.prototype[id] : type === "function" ? FunctionType.prototype[id] : type === "object" ? ObjectType.prototype[id] : DefaultType.prototype[id]; 36 | } 37 | return method; 38 | }; 39 | 40 | exports.methodOf = methodOf; 41 | var dispatcher = function (name) { 42 | var index = arguments[1] === undefined ? 0 : arguments[1]; 43 | 44 | var id = symbol(name); 45 | var dispatch = function (a, b, c, d, e) { 46 | var target = index === 0 ? a : index === 1 ? b : index === 2 ? c : index === 3 ? d : e; 47 | var method = methodOf(target, id); 48 | 49 | if (!method) { 50 | throw TypeError("target does not implements " + id + " method"); 51 | } 52 | 53 | return method.call(target, a, b, c, d, e); 54 | }; 55 | dispatch.symbol = id; 56 | return dispatch; 57 | }; 58 | 59 | var init = dispatcher("transducer/init"); 60 | exports.init = init; 61 | var $init = init.symbol; 62 | 63 | var result = dispatcher("transducer/result"); 64 | exports.result = result; 65 | var $result = result.symbol; 66 | 67 | var step = dispatcher("transducer/step"); 68 | exports.step = step; 69 | var $step = step.symbol; 70 | 71 | var reduce = dispatcher("transducer/reduce", 2); 72 | exports.reduce = reduce; 73 | var $reduce = reduce.symbol; 74 | 75 | var reduced = function (value) { 76 | return new Reduced(value); 77 | }; 78 | exports.reduced = reduced; 79 | var $reduced = reduced.symbol = symbol("transducer/reduced"); 80 | 81 | var value = function (reduced) { 82 | return reduced[$value]; 83 | }; 84 | exports.value = value; 85 | var $value = value.symbol = symbol("transducer/value"); 86 | 87 | var transformer = function (transform) { 88 | transform[$transformer] = true; 89 | return transformer; 90 | }; 91 | exports.transformer = transformer; 92 | var $transformer = transformer.symbol = symbol("transducer/transformer"); 93 | 94 | var prototype = Object.prototype; 95 | 96 | // Returns `true` if given `x` is a JS array. 97 | var isArray = Array.isArray || function (x) { 98 | return prototype.toString.call(x) === "[object Array]"; 99 | }; 100 | 101 | exports.isArray = isArray; 102 | // Returns `true` if given `x` is a regular expression. 103 | var isRegExp = function (x) { 104 | return prototype.toString.call(x) === "[object RegExp]"; 105 | }; 106 | 107 | exports.isRegExp = isRegExp; 108 | // Returns `true` if given `x` is a JS iterator. 109 | var isIterator = function (x) { 110 | return x && x[$iterator]; 111 | }; 112 | 113 | exports.isIterator = isIterator; 114 | // Returns true if `x` is boxed value & signifies that 115 | // reduction is complete. 116 | var isReduced = function (x) { 117 | return x instanceof Reduced || x && x[$reduced]; 118 | }; 119 | 120 | exports.isReduced = isReduced; 121 | var isReducible = function (x) { 122 | return x && methodOf(x, $reduce); 123 | }; 124 | 125 | exports.isReducible = isReducible; 126 | var isReducer = function (x) { 127 | return x instanceof Reducer || methodOf(x, $step); 128 | }; 129 | 130 | exports.isReducer = isReducer; 131 | var isTransformer = function (x) { 132 | return x && x[$transformer]; 133 | }; 134 | 135 | exports.isTransformer = isTransformer; 136 | // Class is used to box result of reduction step in order 137 | // to signal chained transducer that reduction has completed. 138 | 139 | var Reduced = exports.Reduced = function Reduced(value) { 140 | _classCallCheck(this, Reduced); 141 | 142 | this[$reduced] = true; 143 | this[$value] = value; 144 | 145 | // Compatibility with other libs: 146 | // https://github.com/cognitect-labs/transducers-js 147 | // https://github.com/jlongster/transducers.js 148 | this.__transducers_reduced__ = true; 149 | this.value = value; 150 | }; 151 | 152 | Reduced.symbol = $reduced; 153 | 154 | var Reducer = exports.Reducer = (function () { 155 | function Reducer(_ref) { 156 | var init = _ref.init; 157 | var step = _ref.step; 158 | var result = _ref.result; 159 | 160 | _classCallCheck(this, Reducer); 161 | 162 | this[$init] = init || this[$init]; 163 | this[$step] = step || this[$step]; 164 | this[$result] = result || this[$result]; 165 | } 166 | 167 | _createComputedClass(Reducer, [{ 168 | key: $init, 169 | value: function () { 170 | throw TypeError("Reducer must implement [Symbol.for(\"transducer/init\")]"); 171 | } 172 | }, { 173 | key: $step, 174 | value: function (result, input) { 175 | throw TypeError("Reducer must implement [Symbol.for(\"transducer/step\")]"); 176 | } 177 | }, { 178 | key: $result, 179 | value: function (result) { 180 | throw TypeError("Reducer must implement [Symbol.for(\"transducer/result\")]"); 181 | } 182 | }]); 183 | 184 | return Reducer; 185 | })(); 186 | 187 | var Producer = exports.Producer = (function (_Reducer) { 188 | function Producer(source) { 189 | _classCallCheck(this, Producer); 190 | 191 | this[$init] = methodOf(source, $init); 192 | this[$step] = methodOf(source, $step); 193 | this[$result] = methodOf(source, $result); 194 | } 195 | 196 | _inherits(Producer, _Reducer); 197 | 198 | return Producer; 199 | })(Reducer); 200 | 201 | var Stepper = exports.Stepper = (function (_Reducer2) { 202 | function Stepper(f) { 203 | _classCallCheck(this, Stepper); 204 | 205 | this[$step] = f; 206 | } 207 | 208 | _inherits(Stepper, _Reducer2); 209 | 210 | _createComputedClass(Stepper, [{ 211 | key: $init, 212 | value: function () { 213 | return this[$step](); 214 | } 215 | }, { 216 | key: $result, 217 | value: function (result) { 218 | return result; 219 | } 220 | }]); 221 | 222 | return Stepper; 223 | })(Reducer); 224 | 225 | var Transducer = exports.Transducer = (function (_Reducer3) { 226 | function Transducer(reducer) { 227 | for (var _len = arguments.length, params = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 228 | params[_key - 1] = arguments[_key]; 229 | } 230 | 231 | _classCallCheck(this, Transducer); 232 | 233 | this.reducer = reducer; 234 | this.setup.apply(this, params); 235 | } 236 | 237 | _inherits(Transducer, _Reducer3); 238 | 239 | _createComputedClass(Transducer, [{ 240 | key: "setup", 241 | value: function setup() {} 242 | }, { 243 | key: $init, 244 | value: function () { 245 | return this.reducer[$init](); 246 | } 247 | }, { 248 | key: $step, 249 | value: function (result, input) { 250 | return this.advance(result, input); 251 | } 252 | }, { 253 | key: "advance", 254 | value: function advance(result, input) { 255 | return this.reducer[$step](result, input); 256 | } 257 | }, { 258 | key: $result, 259 | value: function (result) { 260 | return this.reducer[$result](result); 261 | } 262 | }]); 263 | 264 | return Transducer; 265 | })(Reducer); 266 | 267 | var Composite = exports.Composite = (function (_Transducer) { 268 | function Composite(source, transformer, TransducerType) { 269 | for (var _len = arguments.length, params = Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) { 270 | params[_key - 3] = arguments[_key]; 271 | } 272 | 273 | _classCallCheck(this, Composite); 274 | 275 | this.reducer = _applyConstructor(TransducerType, [transformer(source)].concat(params)); 276 | } 277 | 278 | _inherits(Composite, _Transducer); 279 | 280 | return Composite; 281 | })(Transducer); 282 | 283 | // Creates a transformer function that is a thunk for `TransducerType` and it's parameters. 284 | // Once returned transformer is inovked it's going to do one of the following things: 285 | // - If argument is an instance of a `Reducer` it's going to create an instance of Transducer 286 | // with a given argument at the bottom of the chain. 287 | // - If argument is another transformer it's going to return composed transformer. 288 | // - If argument is a reducible data structure with defined reducer it's going to return 289 | // transducer application over it. 290 | var Transform = function (TransducerType) { 291 | for (var _len = arguments.length, params = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 292 | params[_key - 1] = arguments[_key]; 293 | } 294 | 295 | var transform = function (source) { 296 | if (source instanceof Reducer) { 297 | return _applyConstructor(TransducerType, [source].concat(params)); 298 | } else if (source && source[$transformer]) { 299 | return Transform.apply(undefined, [Composite, source, TransducerType].concat(params)); 300 | } else if (isReducer(source)) { 301 | var transducer = _applyConstructor(TransducerType, [new Producer(source)].concat(params)); 302 | var initial = transducer[$init](); 303 | var _result = reduce(transducer, initial, source); 304 | return transducer[$result](_result); 305 | } else { 306 | throw TypeError("Unsupported argument type was passed to a transformer"); 307 | } 308 | }; 309 | // Should use `transformer` instead but for debugging it's kind 310 | // of handy to attach `TransducerType` and it `params` so we keep 311 | // this for now. 312 | transform[$transformer] = true; 313 | transform.Transducer = TransducerType; 314 | transform.params = params; 315 | return transform; 316 | }; 317 | exports.Transform = Transform; 318 | Transform.symbol = $transformer; 319 | 320 | // Like `Transform` but allows passing parameters in the separate call. 321 | var Transformer = function (TransducerType) { 322 | return function () { 323 | for (var _len = arguments.length, params = Array(_len), _key = 0; _key < _len; _key++) { 324 | params[_key] = arguments[_key]; 325 | } 326 | 327 | return Transform.apply(undefined, [TransducerType].concat(params)); 328 | }; 329 | }; 330 | 331 | exports.Transformer = Transformer; 332 | // Transducers. 333 | 334 | var Map = (function (_Transducer2) { 335 | function Map() { 336 | _classCallCheck(this, Map); 337 | 338 | if (_Transducer2 != null) { 339 | _Transducer2.apply(this, arguments); 340 | } 341 | } 342 | 343 | _inherits(Map, _Transducer2); 344 | 345 | _createComputedClass(Map, [{ 346 | key: "setup", 347 | value: function setup(f) { 348 | this.f = f; 349 | } 350 | }, { 351 | key: $step, 352 | value: function (state, input) { 353 | return this.advance(state, this.f(input)); 354 | } 355 | }]); 356 | 357 | return Map; 358 | })(Transducer); 359 | 360 | var map = Transformer(Map); 361 | 362 | exports.map = map; 363 | 364 | var Filter = (function (_Transducer3) { 365 | function Filter() { 366 | _classCallCheck(this, Filter); 367 | 368 | if (_Transducer3 != null) { 369 | _Transducer3.apply(this, arguments); 370 | } 371 | } 372 | 373 | _inherits(Filter, _Transducer3); 374 | 375 | _createComputedClass(Filter, [{ 376 | key: "setup", 377 | value: function setup(p) { 378 | this.p = p; 379 | } 380 | }, { 381 | key: $step, 382 | value: function (state, input) { 383 | if (this.p(input)) { 384 | return this.advance(state, input); 385 | } 386 | return state; 387 | } 388 | }]); 389 | 390 | return Filter; 391 | })(Transducer); 392 | 393 | var filter = Transformer(Filter); 394 | exports.filter = filter; 395 | var remove = function (p) { 396 | return filter(function (x) { 397 | return !p(x); 398 | }); 399 | }; 400 | 401 | exports.remove = remove; 402 | 403 | var DropRepeats = (function (_Transducer4) { 404 | function DropRepeats() { 405 | _classCallCheck(this, DropRepeats); 406 | 407 | if (_Transducer4 != null) { 408 | _Transducer4.apply(this, arguments); 409 | } 410 | } 411 | 412 | _inherits(DropRepeats, _Transducer4); 413 | 414 | _createComputedClass(DropRepeats, [{ 415 | key: $step, 416 | value: function (state, input) { 417 | if (input !== this.last) { 418 | this.last = input; 419 | return this.advance(state, input); 420 | } 421 | return state; 422 | } 423 | }]); 424 | 425 | return DropRepeats; 426 | })(Transducer); 427 | 428 | var dropRepeats = Transform(DropRepeats); 429 | 430 | exports.dropRepeats = dropRepeats; 431 | 432 | var TakeWhile = (function (_Transducer5) { 433 | function TakeWhile() { 434 | _classCallCheck(this, TakeWhile); 435 | 436 | if (_Transducer5 != null) { 437 | _Transducer5.apply(this, arguments); 438 | } 439 | } 440 | 441 | _inherits(TakeWhile, _Transducer5); 442 | 443 | _createComputedClass(TakeWhile, [{ 444 | key: "setup", 445 | value: function setup(p) { 446 | this.p = p; 447 | } 448 | }, { 449 | key: $step, 450 | value: function (state, input) { 451 | if (this.p(input)) { 452 | return this.advance(state, input); 453 | } 454 | return new Reduced(state); 455 | } 456 | }]); 457 | 458 | return TakeWhile; 459 | })(Transducer); 460 | 461 | var takeWhile = Transformer(TakeWhile); 462 | 463 | exports.takeWhile = takeWhile; 464 | 465 | var Take = (function (_Transducer6) { 466 | function Take() { 467 | _classCallCheck(this, Take); 468 | 469 | if (_Transducer6 != null) { 470 | _Transducer6.apply(this, arguments); 471 | } 472 | } 473 | 474 | _inherits(Take, _Transducer6); 475 | 476 | _createComputedClass(Take, [{ 477 | key: "setup", 478 | value: function setup(n) { 479 | this.n = n; 480 | } 481 | }, { 482 | key: $step, 483 | value: function (state, input) { 484 | if (this.n > 0) { 485 | this.n = this.n - 1; 486 | state = this.advance(state, input); 487 | if (this.n === 0 && !isReduced(state)) { 488 | state = new Reduced(state); 489 | } 490 | } 491 | return state; 492 | } 493 | }]); 494 | 495 | return Take; 496 | })(Transducer); 497 | 498 | var take = Transformer(Take); 499 | 500 | exports.take = take; 501 | 502 | var Drop = (function (_Transducer7) { 503 | function Drop() { 504 | _classCallCheck(this, Drop); 505 | 506 | if (_Transducer7 != null) { 507 | _Transducer7.apply(this, arguments); 508 | } 509 | } 510 | 511 | _inherits(Drop, _Transducer7); 512 | 513 | _createComputedClass(Drop, [{ 514 | key: "setup", 515 | value: function setup(n) { 516 | this.n = n; 517 | } 518 | }, { 519 | key: $step, 520 | value: function (state, input) { 521 | this.n = this.n - 1; 522 | return this.n >= 0 ? state : this.advance(state, input); 523 | } 524 | }]); 525 | 526 | return Drop; 527 | })(Transducer); 528 | 529 | var drop = Transformer(Drop); 530 | 531 | exports.drop = drop; 532 | 533 | var DropWhile = (function (_Transducer8) { 534 | function DropWhile() { 535 | _classCallCheck(this, DropWhile); 536 | 537 | if (_Transducer8 != null) { 538 | _Transducer8.apply(this, arguments); 539 | } 540 | } 541 | 542 | _inherits(DropWhile, _Transducer8); 543 | 544 | _createComputedClass(DropWhile, [{ 545 | key: "setup", 546 | value: function setup(p) { 547 | this.p = p; 548 | this.dropping = true; 549 | } 550 | }, { 551 | key: $step, 552 | value: function (state, input) { 553 | this.dropping = this.dropping && this.p(input); 554 | return this.dropping ? state : this.advance(state, input); 555 | } 556 | }]); 557 | 558 | return DropWhile; 559 | })(Transducer); 560 | 561 | var dropWhile = Transformer(DropWhile); 562 | 563 | exports.dropWhile = dropWhile; 564 | 565 | var Partition = (function (_Transducer9) { 566 | function Partition() { 567 | _classCallCheck(this, Partition); 568 | 569 | if (_Transducer9 != null) { 570 | _Transducer9.apply(this, arguments); 571 | } 572 | } 573 | 574 | _inherits(Partition, _Transducer9); 575 | 576 | _createComputedClass(Partition, [{ 577 | key: "setup", 578 | value: function setup(n) { 579 | this.n = n; 580 | this.i = 0; 581 | this.part = new Array(n); 582 | } 583 | }, { 584 | key: $result, 585 | value: function (state) { 586 | if (this.i > 0) { 587 | state = this.advance(state, this.part.slice(0, this.i)); 588 | state = isReduced(state) ? state[$value] : state; 589 | } 590 | return _get(Object.getPrototypeOf(Partition.prototype), $result, this).call(this, state); 591 | } 592 | }, { 593 | key: $step, 594 | value: function (state, input) { 595 | this.part[this.i] = input; 596 | this.i = this.i + 1; 597 | if (this.i == this.n) { 598 | this.i = 0; 599 | return this.advance(state, this.part.slice(0)); 600 | } 601 | return state; 602 | } 603 | }]); 604 | 605 | return Partition; 606 | })(Transducer); 607 | 608 | var partition = Transformer(Partition); 609 | 610 | exports.partition = partition; 611 | 612 | var Forwarder = (function (_Transducer10) { 613 | function Forwarder() { 614 | _classCallCheck(this, Forwarder); 615 | 616 | if (_Transducer10 != null) { 617 | _Transducer10.apply(this, arguments); 618 | } 619 | } 620 | 621 | _inherits(Forwarder, _Transducer10); 622 | 623 | _createComputedClass(Forwarder, [{ 624 | key: $step, 625 | value: function (state, input) { 626 | var result = this.advance(state, input); 627 | return isReduced(result) ? result[$value] : result; 628 | } 629 | }]); 630 | 631 | return Forwarder; 632 | })(Transducer); 633 | 634 | var Cat = (function (_Transducer11) { 635 | function Cat() { 636 | _classCallCheck(this, Cat); 637 | 638 | if (_Transducer11 != null) { 639 | _Transducer11.apply(this, arguments); 640 | } 641 | } 642 | 643 | _inherits(Cat, _Transducer11); 644 | 645 | _createComputedClass(Cat, [{ 646 | key: "setup", 647 | value: function setup() { 648 | this.forwarder = new Forwarder(this.reducer); 649 | } 650 | }, { 651 | key: $step, 652 | value: function (state, input) { 653 | return reduce(this.forwarder, state, input); 654 | } 655 | }]); 656 | 657 | return Cat; 658 | })(Transducer); 659 | 660 | var cat = Transform(Cat); 661 | 662 | exports.cat = cat; 663 | var transduce = function (transformer, reducer, initial, source) { 664 | reducer = reducer instanceof Reducer ? reducer : isReducer(reducer) ? new Producer(reducer) : typeof reducer === "function" ? new Stepper(reducer) : null; 665 | 666 | if (!reducer) { 667 | throw TypeError("Invalid reducer was passed"); 668 | } 669 | 670 | var transducer = transformer(reducer); 671 | 672 | if (source === void 0 && initial !== void 0) { 673 | var _ref = [initial, transducer[$init]()]; 674 | 675 | var _ref2 = _slicedToArray(_ref, 2); 676 | 677 | source = _ref2[0]; 678 | initial = _ref2[1]; 679 | } 680 | 681 | var result = reduce(transducer, initial, source); 682 | return transducer[$result](result); 683 | }; 684 | 685 | exports.transduce = transduce; 686 | // Interface implementations for built-in types so we don't have 687 | // to patch built-ins. 688 | 689 | // Defaltu type is the bottom type all types including null undefined 690 | // and object are going to inherit from it. 691 | 692 | var DefaultType = exports.DefaultType = (function () { 693 | function DefaultType() { 694 | _classCallCheck(this, DefaultType); 695 | } 696 | 697 | _createComputedClass(DefaultType, [{ 698 | key: init.symbol, 699 | value: function () { 700 | return new this.constructor(); 701 | } 702 | }, { 703 | key: result.symbol, 704 | value: function (result) { 705 | return result; 706 | } 707 | }]); 708 | 709 | return DefaultType; 710 | })(); 711 | 712 | // We don not make objects transducible. 713 | 714 | var ObjectType = exports.ObjectType = (function (_DefaultType) { 715 | function ObjectType() { 716 | _classCallCheck(this, ObjectType); 717 | 718 | if (_DefaultType != null) { 719 | _DefaultType.apply(this, arguments); 720 | } 721 | } 722 | 723 | _inherits(ObjectType, _DefaultType); 724 | 725 | return ObjectType; 726 | })(DefaultType); 727 | 728 | // We do not make functions transducible. 729 | 730 | var FunctionType = exports.FunctionType = (function (_DefaultType2) { 731 | function FunctionType() { 732 | _classCallCheck(this, FunctionType); 733 | 734 | if (_DefaultType2 != null) { 735 | _DefaultType2.apply(this, arguments); 736 | } 737 | } 738 | 739 | _inherits(FunctionType, _DefaultType2); 740 | 741 | return FunctionType; 742 | })(DefaultType); 743 | 744 | // All primitives gonig to inherit from AtomitType which 745 | // provides `reduce` implementation that's gonig to invoke 746 | // reducer just once with a value of the data type itself. 747 | 748 | var AtomicType = exports.AtomicType = (function (_DefaultType3) { 749 | function AtomicType() { 750 | _classCallCheck(this, AtomicType); 751 | 752 | if (_DefaultType3 != null) { 753 | _DefaultType3.apply(this, arguments); 754 | } 755 | } 756 | 757 | _inherits(AtomicType, _DefaultType3); 758 | 759 | _createComputedClass(AtomicType, [{ 760 | key: reduce.symbol, 761 | value: function (reducer, initial, value) { 762 | var result = reducer[$step](initial, value); 763 | return isReduced(result) ? result[$value] : result; 764 | } 765 | }]); 766 | 767 | return AtomicType; 768 | })(DefaultType); 769 | 770 | // Any transform over `null` is just `null`. 771 | 772 | var NullType = exports.NullType = (function (_AtomicType) { 773 | function NullType() { 774 | _classCallCheck(this, NullType); 775 | 776 | if (_AtomicType != null) { 777 | _AtomicType.apply(this, arguments); 778 | } 779 | } 780 | 781 | _inherits(NullType, _AtomicType); 782 | 783 | _createComputedClass(NullType, [{ 784 | key: init.symbol, 785 | value: function () { 786 | return null; 787 | } 788 | }, { 789 | key: step.symbol, 790 | value: function (result, input) { 791 | return null; 792 | } 793 | }]); 794 | 795 | return NullType; 796 | })(AtomicType); 797 | 798 | // Any transform over `undefined` is just `undefined` 799 | 800 | var UndefinedType = exports.UndefinedType = (function (_AtomicType2) { 801 | function UndefinedType() { 802 | _classCallCheck(this, UndefinedType); 803 | 804 | if (_AtomicType2 != null) { 805 | _AtomicType2.apply(this, arguments); 806 | } 807 | } 808 | 809 | _inherits(UndefinedType, _AtomicType2); 810 | 811 | _createComputedClass(UndefinedType, [{ 812 | key: init.symbol, 813 | value: function () { 814 | return void 0; 815 | } 816 | }, { 817 | key: step.symbol, 818 | value: function (result, input) { 819 | return void 0; 820 | } 821 | }]); 822 | 823 | return UndefinedType; 824 | })(AtomicType); 825 | 826 | var NumberType = exports.NumberType = (function (_AtomicType3) { 827 | function NumberType() { 828 | _classCallCheck(this, NumberType); 829 | 830 | if (_AtomicType3 != null) { 831 | _AtomicType3.apply(this, arguments); 832 | } 833 | } 834 | 835 | _inherits(NumberType, _AtomicType3); 836 | 837 | _createComputedClass(NumberType, [{ 838 | key: init.symbol, 839 | 840 | // Base number is `0`. 841 | value: function () { 842 | return 0; 843 | } 844 | }, { 845 | key: step.symbol, 846 | value: function (number, input) { 847 | // If input is an array of numbers add each one, otherwise 848 | // just add numbers. 849 | return isArray(input) ? input.reduce(NumberType.add, number) : number + input; 850 | } 851 | }], [{ 852 | key: "add", 853 | value: function add(x, y) { 854 | return x + y; 855 | } 856 | }]); 857 | 858 | return NumberType; 859 | })(AtomicType); 860 | 861 | var BooleanType = exports.BooleanType = (function (_AtomicType4) { 862 | function BooleanType() { 863 | _classCallCheck(this, BooleanType); 864 | 865 | if (_AtomicType4 != null) { 866 | _AtomicType4.apply(this, arguments); 867 | } 868 | } 869 | 870 | _inherits(BooleanType, _AtomicType4); 871 | 872 | return BooleanType; 873 | })(AtomicType); 874 | 875 | var SymbolType = exports.SymbolType = (function (_AtomicType5) { 876 | function SymbolType() { 877 | _classCallCheck(this, SymbolType); 878 | 879 | if (_AtomicType5 != null) { 880 | _AtomicType5.apply(this, arguments); 881 | } 882 | } 883 | 884 | _inherits(SymbolType, _AtomicType5); 885 | 886 | return SymbolType; 887 | })(AtomicType); 888 | 889 | // Generic type to share `reduce` implementation between 890 | // array string or anything that have `length` and access by 891 | // index. 892 | 893 | var IndexedType = exports.IndexedType = (function (_DefaultType4) { 894 | function IndexedType() { 895 | _classCallCheck(this, IndexedType); 896 | 897 | if (_DefaultType4 != null) { 898 | _DefaultType4.apply(this, arguments); 899 | } 900 | } 901 | 902 | _inherits(IndexedType, _DefaultType4); 903 | 904 | _createComputedClass(IndexedType, [{ 905 | key: reduce.symbol, 906 | value: function (reducer, initial, indexed) { 907 | var index = 0; 908 | var state = initial; 909 | var count = indexed.length; 910 | while (index < count) { 911 | state = reducer[$step](state, indexed[index]); 912 | if (isReduced(state)) { 913 | return state[$value]; 914 | } 915 | index = index + 1; 916 | } 917 | return state; 918 | } 919 | }]); 920 | 921 | return IndexedType; 922 | })(DefaultType); 923 | 924 | var StringType = exports.StringType = (function (_IndexedType) { 925 | function StringType() { 926 | _classCallCheck(this, StringType); 927 | 928 | if (_IndexedType != null) { 929 | _IndexedType.apply(this, arguments); 930 | } 931 | } 932 | 933 | _inherits(StringType, _IndexedType); 934 | 935 | _createComputedClass(StringType, [{ 936 | key: init.symbol, 937 | 938 | // Base string is empty string. 939 | value: function () { 940 | return ""; 941 | } 942 | }, { 943 | key: step.symbol, 944 | 945 | // If input is an array concat them onto result otherwise just 946 | // concat to strings. 947 | value: function (result, input) { 948 | return isArray(input) ? result.concat.apply(result, _toConsumableArray(input)) : result + input; 949 | } 950 | }]); 951 | 952 | return StringType; 953 | })(IndexedType); 954 | 955 | var ArrayType = exports.ArrayType = (function (_IndexedType2) { 956 | function ArrayType() { 957 | _classCallCheck(this, ArrayType); 958 | 959 | if (_IndexedType2 != null) { 960 | _IndexedType2.apply(this, arguments); 961 | } 962 | } 963 | 964 | _inherits(ArrayType, _IndexedType2); 965 | 966 | _createComputedClass(ArrayType, [{ 967 | key: init.symbol, 968 | value: function () { 969 | return []; 970 | } 971 | }, { 972 | key: step.symbol, 973 | value: function (array, value) { 974 | array.push(value); 975 | return array; 976 | } 977 | }]); 978 | 979 | return ArrayType; 980 | })(IndexedType); 981 | 982 | // Iteractors are kind of special in a sence that they produce 983 | 984 | var IteratorType = exports.IteratorType = (function (_ObjectType) { 985 | function IteratorType() { 986 | _classCallCheck(this, IteratorType); 987 | 988 | if (_ObjectType != null) { 989 | _ObjectType.apply(this, arguments); 990 | } 991 | } 992 | 993 | _inherits(IteratorType, _ObjectType); 994 | 995 | _createComputedClass(IteratorType, [{ 996 | key: init.symbol, 997 | value: function () { 998 | return IteratorLazyTransform; 999 | } 1000 | }, { 1001 | key: step.symbol, 1002 | value: function (result, input) { 1003 | return result[step.symbol](result, input); 1004 | } 1005 | }, { 1006 | key: reduce.symbol, 1007 | value: function (transducer, initial, source) { 1008 | var iterator = source[$iterator](); 1009 | // If it is transformation from iterator to iterator, then initial value is 1010 | // going to be `IteratorLazyTransform` as (returned by [init.symbol] method above) 1011 | // In such case we just create an instance of `IteratorLazyTransform` and return it 1012 | // backe actual transformation will happen on demand by `IteratorLazyTransform`. 1013 | if (initial === IteratorLazyTransform) { 1014 | return new IteratorLazyTransform(iterator, transducer); 1015 | } 1016 | 1017 | // Otherwise each value will be forwraded to the transducer until done 1018 | // iteration or until reduced result is returned. 1019 | var result = initial; 1020 | while (true) { 1021 | var _iterator$next = iterator.next(); 1022 | 1023 | var done = _iterator$next.done; 1024 | var _value = _iterator$next.value; 1025 | 1026 | if (done) { 1027 | return result; 1028 | } 1029 | 1030 | result = transducer[$step](result, _value); 1031 | 1032 | if (isReduced(result)) { 1033 | return result[$value]; 1034 | } 1035 | } 1036 | } 1037 | }]); 1038 | 1039 | return IteratorType; 1040 | })(ObjectType); 1041 | 1042 | var IteratorLazyTransform = exports.IteratorLazyTransform = (function (_IteratorType) { 1043 | function IteratorLazyTransform(source, transducer) { 1044 | _classCallCheck(this, IteratorLazyTransform); 1045 | 1046 | // Each transformation step `this.transducer.step` may produce 0, 1 or more 1047 | // steps in return. In order to accomodate extra values internal buffer is 1048 | // going to be used. 1049 | this[$buffer] = []; 1050 | 1051 | this.source = source; 1052 | this.transducer = transducer; 1053 | this.isDrained = false; 1054 | this.done = false; 1055 | } 1056 | 1057 | _inherits(IteratorLazyTransform, _IteratorType); 1058 | 1059 | _createComputedClass(IteratorLazyTransform, [{ 1060 | key: step.symbol, 1061 | value: function (target, value) { 1062 | target[$buffer].push(value); 1063 | return target; 1064 | } 1065 | }, { 1066 | key: $iterator, 1067 | value: function () { 1068 | return this; 1069 | } 1070 | }, { 1071 | key: "next", 1072 | value: function next() { 1073 | // Pull from the source until something is pushed into a buffer or 1074 | // or until source is drained. `this.transducer` maybe filtering so 1075 | // step may not push anything to a buffer, or it could be mapcatting 1076 | // in which case several values will be pushed. It also maybe that 1077 | // transducer is accumulating ond on result more values will be pushed 1078 | // (like partition). 1079 | while (this[$buffer].length === 0 && !this.isDrained) { 1080 | var _source$next = this.source.next(); 1081 | 1082 | var done = _source$next.done; 1083 | var _value = _source$next.value; 1084 | 1085 | // If source iterator is drained invoke result on transducer to let 1086 | // it cleanup or push whatever it aggregated. 1087 | if (done) { 1088 | this.transducer[$result](this); 1089 | this.isDrained = done; 1090 | } 1091 | // Otherwise keep calling step, if result is reduced then mark this 1092 | // iterator drained to stop pulling. 1093 | else { 1094 | var _result = this.transducer[$step](this, _value); 1095 | this.isDrained = isReduced(_result); 1096 | } 1097 | } 1098 | 1099 | // At this poin we either get something in a buffer or source was exhausted 1100 | // or both. If something is in a buffer just return from it. If buffer is 1101 | // empty then source is drained as well so we mark this done and finish. 1102 | if (this[$buffer].length > 0) { 1103 | this.value = this[$buffer].shift(); 1104 | } else { 1105 | this.value = undefined; 1106 | this.done = this.isDrained; 1107 | } 1108 | 1109 | return this; 1110 | } 1111 | }]); 1112 | 1113 | return IteratorLazyTransform; 1114 | })(IteratorType); 1115 | 1116 | var $buffer = symbol("IteratorLazyTransform/buffer"); 1117 | IteratorLazyTransform.buffer = $buffer; 1118 | }); 1119 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy90cmFuc2R1Y2Vycy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLE1BQU0sZUFBZSxHQUFHLE9BQU8sTUFBTSxBQUFDLEtBQUssV0FBVyxDQUFDO0FBQ3ZELE1BQU0sTUFBTSxHQUFHLEFBQUMsZUFBZSxJQUFJLE1BQU0sT0FBSSxJQUFLLFVBQUEsSUFBSTtrQkFBUyxJQUFJO0dBQUUsQ0FBQTs7QUFFckUsTUFBTSxTQUFTLEdBQUcsZUFBZSxJQUFJLE1BQU0sQ0FBQyxRQUFRLElBQUksTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFBOztBQUluRSxNQUFNLFFBQVEsR0FBRyxVQUFDLE1BQU0sRUFBRSxFQUFFLEVBQUs7QUFDdEMsUUFBSSxNQUFNLEdBQUcsTUFBTSxJQUFJLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQTtBQUNqQyxRQUFJLENBQUMsTUFBTSxFQUFFO0FBQ1gsVUFBTSxJQUFJLEdBQUcsT0FBTyxNQUFNLEFBQUMsQ0FBQTtBQUMzQixZQUFNLEdBQUcsTUFBTSxLQUFLLElBQUksR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxHQUNqRCxNQUFNLEtBQUssS0FBSyxDQUFDLEFBQUMsR0FBRyxhQUFhLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxHQUNoRCxJQUFJLEtBQUssUUFBUSxHQUFHLFVBQVUsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLEdBQzVDLElBQUksS0FBSyxRQUFRLEdBQUcsVUFBVSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsR0FDNUMsSUFBSSxLQUFLLFNBQVMsR0FBRyxXQUFXLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxHQUM5QyxJQUFJLEtBQUssUUFBUSxHQUFHLFVBQVUsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLEdBQzVDLE9BQU8sQ0FBQyxNQUFNLENBQUMsR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxHQUN6QyxVQUFVLENBQUMsTUFBTSxDQUFDLEdBQUcsWUFBWSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsR0FDL0MsUUFBUSxDQUFDLE1BQU0sQ0FBQyxHQUFHLFVBQVUsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLEdBQzNDLElBQUksS0FBSyxVQUFVLEdBQUcsWUFBWSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsR0FDaEQsSUFBSSxLQUFLLFFBQVEsR0FBRyxVQUFVLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxHQUM1QyxXQUFXLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFBO0tBQzFCO0FBQ0QsV0FBTyxNQUFNLENBQUE7R0FDZCxDQUFBOztVQWxCWSxRQUFRLEdBQVIsUUFBUTtBQW9CckIsTUFBTSxVQUFVLEdBQUcsVUFBQyxJQUFJLEVBQWM7UUFBWixLQUFLLGdDQUFDLENBQUM7O0FBQy9CLFFBQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQTtBQUN2QixRQUFNLFFBQVEsR0FBRyxVQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUs7QUFDbEMsVUFBTSxNQUFNLEdBQUcsS0FBSyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQ2YsS0FBSyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQ2YsS0FBSyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQ2YsS0FBSyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQ2YsQ0FBQyxDQUFDO0FBQ2pCLFVBQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUE7O0FBRW5DLFVBQUksQ0FBQyxNQUFNLEVBQUU7QUFDWCxjQUFNLFNBQVMsaUNBQStCLEVBQUUsYUFBVSxDQUFBO09BQzNEOztBQUVELGFBQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFBO0tBQzFDLENBQUE7QUFDRCxZQUFRLENBQUMsTUFBTSxHQUFHLEVBQUUsQ0FBQTtBQUNwQixXQUFPLFFBQVEsQ0FBQTtHQUNoQixDQUFBOztBQUVNLE1BQU0sSUFBSSxHQUFHLFVBQVUsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFBO1VBQXBDLElBQUksR0FBSixJQUFJO0FBQ2pCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUE7O0FBRWxCLE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFBO1VBQXhDLE1BQU0sR0FBTixNQUFNO0FBQ25CLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUE7O0FBRXRCLE1BQU0sSUFBSSxHQUFHLFVBQVUsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFBO1VBQXBDLElBQUksR0FBSixJQUFJO0FBQ2pCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUE7O0FBRWxCLE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLENBQUMsQ0FBQTtVQUEzQyxNQUFNLEdBQU4sTUFBTTtBQUNuQixNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFBOztBQUV0QixNQUFNLE9BQU8sR0FBRyxVQUFBLEtBQUs7V0FBSSxJQUFJLE9BQU8sQ0FBQyxLQUFLLENBQUM7R0FBQSxDQUFBO1VBQXJDLE9BQU8sR0FBUCxPQUFPO0FBQ3BCLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLG9CQUFvQixDQUFDLENBQUE7O0FBRXZELE1BQU0sS0FBSyxHQUFHLFVBQUEsT0FBTztXQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUM7R0FBQSxDQUFBO1VBQWxDLEtBQUssR0FBTCxLQUFLO0FBQ2xCLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLGtCQUFrQixDQUFDLENBQUE7O0FBRWpELE1BQU0sV0FBVyxHQUFHLFVBQUEsU0FBUyxFQUFJO0FBQ3RDLGFBQVMsQ0FBQyxZQUFZLENBQUMsR0FBRyxJQUFJLENBQUE7QUFDOUIsV0FBTyxXQUFXLENBQUE7R0FDbkIsQ0FBQTtVQUhZLFdBQVcsR0FBWCxXQUFXO0FBSXhCLE1BQU0sWUFBWSxHQUFHLFdBQVcsQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLHdCQUF3QixDQUFDLENBQUE7O0FBRTFFLE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUE7OztBQUczQixNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsT0FBTyxJQUNsQyxVQUFBLENBQUM7V0FBSSxTQUFTLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxnQkFBZ0I7R0FBQSxDQUFBOztVQUR6QyxPQUFPLEdBQVAsT0FBTzs7QUFJYixNQUFNLFFBQVEsR0FBRyxVQUFBLENBQUM7V0FDdkIsU0FBUyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssaUJBQWlCO0dBQUEsQ0FBQTs7VUFEckMsUUFBUSxHQUFSLFFBQVE7O0FBSWQsTUFBTSxVQUFVLEdBQUcsVUFBQSxDQUFDO1dBQ3pCLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxDQUFDO0dBQUEsQ0FBQTs7VUFETixVQUFVLEdBQVYsVUFBVTs7O0FBS2hCLE1BQU0sU0FBUyxHQUFHLFVBQUEsQ0FBQztXQUN4QixDQUFDLFlBQVksT0FBTyxJQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUSxDQUFDLEFBQUM7R0FBQSxDQUFBOztVQUQvQixTQUFTLEdBQVQsU0FBUztBQUdmLE1BQU0sV0FBVyxHQUFHLFVBQUEsQ0FBQztXQUMxQixDQUFDLElBQUksUUFBUSxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUM7R0FBQSxDQUFBOztVQURkLFdBQVcsR0FBWCxXQUFXO0FBR2pCLE1BQU0sU0FBUyxHQUFHLFVBQUEsQ0FBQztXQUN4QixDQUFDLFlBQVksT0FBTyxJQUFJLFFBQVEsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDO0dBQUEsQ0FBQTs7VUFEL0IsU0FBUyxHQUFULFNBQVM7QUFHZixNQUFNLGFBQWEsR0FBRyxVQUFBLENBQUM7V0FDNUIsQ0FBQyxJQUFJLENBQUMsQ0FBQyxZQUFZLENBQUM7R0FBQSxDQUFBOztVQURULGFBQWEsR0FBYixhQUFhOzs7O01BS2IsT0FBTyxXQUFQLE9BQU8sR0FDUCxTQURBLE9BQU8sQ0FDTixLQUFLLEVBQUU7MEJBRFIsT0FBTzs7QUFFaEIsUUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLElBQUksQ0FBQTtBQUNyQixRQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsS0FBSyxDQUFBOzs7OztBQUtwQixRQUFJLENBQUMsdUJBQXVCLEdBQUcsSUFBSSxDQUFBO0FBQ25DLFFBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFBO0dBQ25COztBQUVILFNBQU8sQ0FBQyxNQUFNLEdBQUcsUUFBUSxDQUFBOztNQUdaLE9BQU8sV0FBUCxPQUFPO0FBQ1AsYUFEQSxPQUFPLE9BQ2dCO1VBQXJCLElBQUksUUFBSixJQUFJO1VBQUUsSUFBSSxRQUFKLElBQUk7VUFBRSxNQUFNLFFBQU4sTUFBTTs7NEJBRHBCLE9BQU87O0FBRWhCLFVBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxJQUFJLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFBO0FBQ2pDLFVBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxJQUFJLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFBO0FBQ2pDLFVBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxNQUFNLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFBO0tBQ3hDOzt5QkFMVSxPQUFPO1dBTWpCLEtBQUs7YUFBQyxZQUFHO0FBQ1IsY0FBTSxTQUFTLENBQUMsMERBQXdELENBQUMsQ0FBQTtPQUMxRTs7V0FDQSxLQUFLO2FBQUMsVUFBQyxNQUFNLEVBQUUsS0FBSyxFQUFFO0FBQ3JCLGNBQU0sU0FBUyxDQUFDLDBEQUF3RCxDQUFDLENBQUE7T0FDMUU7O1dBQ0EsT0FBTzthQUFDLFVBQUMsTUFBTSxFQUFFO0FBQ2hCLGNBQU0sU0FBUyxDQUFDLDREQUEwRCxDQUFDLENBQUE7T0FDNUU7OztXQWRVLE9BQU87OztNQWlCUCxRQUFRLFdBQVIsUUFBUTtBQUNSLGFBREEsUUFBUSxDQUNQLE1BQU0sRUFBRTs0QkFEVCxRQUFROztBQUVqQixVQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsUUFBUSxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQTtBQUNyQyxVQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsUUFBUSxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQTtBQUNyQyxVQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsUUFBUSxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQTtLQUMxQzs7Y0FMVSxRQUFROztXQUFSLFFBQVE7S0FBUyxPQUFPOztNQVF4QixPQUFPLFdBQVAsT0FBTztBQUNQLGFBREEsT0FBTyxDQUNOLENBQUMsRUFBRTs0QkFESixPQUFPOztBQUVoQixVQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFBO0tBQ2hCOztjQUhVLE9BQU87O3lCQUFQLE9BQU87V0FJakIsS0FBSzthQUFDLFlBQUc7QUFDUixlQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFBO09BQ3JCOztXQUNBLE9BQU87YUFBQyxVQUFDLE1BQU0sRUFBRTtBQUNoQixlQUFPLE1BQU0sQ0FBQTtPQUNkOzs7V0FUVSxPQUFPO0tBQVMsT0FBTzs7TUFZdkIsVUFBVSxXQUFWLFVBQVU7QUFDVixhQURBLFVBQVUsQ0FDVCxPQUFPLEVBQWE7d0NBQVIsTUFBTTtBQUFOLGNBQU07Ozs0QkFEbkIsVUFBVTs7QUFFbkIsVUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUE7QUFDdEIsVUFBSSxDQUFDLEtBQUssTUFBQSxDQUFWLElBQUksRUFBVSxNQUFNLENBQUMsQ0FBQTtLQUN0Qjs7Y0FKVSxVQUFVOzt5QkFBVixVQUFVOzthQUtoQixpQkFBRyxFQUNQOztXQUNBLEtBQUs7YUFBQyxZQUFHO0FBQ1IsZUFBTyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUE7T0FDN0I7O1dBQ0EsS0FBSzthQUFDLFVBQUMsTUFBTSxFQUFFLEtBQUssRUFBRTtBQUNyQixlQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFBO09BQ25DOzs7YUFDTSxpQkFBQyxNQUFNLEVBQUUsS0FBSyxFQUFFO0FBQ3JCLGVBQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUE7T0FDMUM7O1dBQ0EsT0FBTzthQUFDLFVBQUMsTUFBTSxFQUFFO0FBQ2hCLGVBQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQTtPQUNyQzs7O1dBbEJVLFVBQVU7S0FBUyxPQUFPOztNQXFCMUIsU0FBUyxXQUFULFNBQVM7QUFDVCxhQURBLFNBQVMsQ0FDUixNQUFNLEVBQUUsV0FBVyxFQUFFLGNBQWMsRUFBYTt3Q0FBUixNQUFNO0FBQU4sY0FBTTs7OzRCQUQvQyxTQUFTOztBQUVsQixVQUFJLENBQUMsT0FBTyxxQkFBTyxjQUFjLEdBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxTQUFLLE1BQU0sRUFBQyxDQUFBO0tBQ2xFOztjQUhVLFNBQVM7O1dBQVQsU0FBUztLQUFTLFVBQVU7Ozs7Ozs7OztBQWFsQyxNQUFNLFNBQVMsR0FBRyxVQUFDLGNBQWMsRUFBZ0I7c0NBQVgsTUFBTTtBQUFOLFlBQU07OztBQUNqRCxRQUFNLFNBQVMsR0FBRyxVQUFBLE1BQU0sRUFBSTtBQUMxQixVQUFJLE1BQU0sWUFBWSxPQUFPLEVBQUU7QUFDN0IsaUNBQVcsY0FBYyxHQUFDLE1BQU0sU0FBSyxNQUFNLEdBQUM7T0FDN0MsTUFBTSxJQUFJLE1BQU0sSUFBSSxNQUFNLENBQUMsWUFBWSxDQUFDLEVBQUU7QUFDekMsZUFBTyxTQUFTLG1CQUFDLFNBQVMsRUFBRSxNQUFNLEVBQUUsY0FBYyxTQUFLLE1BQU0sRUFBQyxDQUFBO09BQy9ELE1BQU0sSUFBSSxTQUFTLENBQUMsTUFBTSxDQUFDLEVBQUU7QUFDNUIsWUFBTSxVQUFVLHFCQUFPLGNBQWMsR0FBQyxJQUFJLFFBQVEsQ0FBQyxNQUFNLENBQUMsU0FBSyxNQUFNLEVBQUMsQ0FBQTtBQUN0RSxZQUFNLE9BQU8sR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQTtBQUNuQyxZQUFNLE9BQU0sR0FBRyxNQUFNLENBQUMsVUFBVSxFQUFFLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQTtBQUNsRCxlQUFPLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxPQUFNLENBQUMsQ0FBQTtPQUNuQyxNQUFNO0FBQ0wsY0FBTSxTQUFTLENBQUMsdURBQXVELENBQUMsQ0FBQTtPQUN6RTtLQUNGLENBQUE7Ozs7QUFJRCxhQUFTLENBQUMsWUFBWSxDQUFDLEdBQUcsSUFBSSxDQUFBO0FBQzlCLGFBQVMsQ0FBQyxVQUFVLEdBQUcsY0FBYyxDQUFBO0FBQ3JDLGFBQVMsQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFBO0FBQ3pCLFdBQU8sU0FBUyxDQUFBO0dBQ2pCLENBQUE7VUF0QlksU0FBUyxHQUFULFNBQVM7QUF1QnRCLFdBQVMsQ0FBQyxNQUFNLEdBQUcsWUFBWSxDQUFBOzs7QUFHeEIsTUFBTSxXQUFXLEdBQUcsVUFBQSxjQUFjO1dBQUk7d0NBQUksTUFBTTtBQUFOLGNBQU07OzthQUNyRCxTQUFTLG1CQUFDLGNBQWMsU0FBSyxNQUFNLEVBQUM7S0FBQTtHQUFBLENBQUE7O1VBRHpCLFdBQVcsR0FBWCxXQUFXOzs7TUFLbEIsR0FBRzthQUFILEdBQUc7NEJBQUgsR0FBRzs7Ozs7OztjQUFILEdBQUc7O3lCQUFILEdBQUc7O2FBQ0YsZUFBQyxDQUFDLEVBQUU7QUFDUCxZQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQTtPQUNYOztXQUNBLEtBQUs7YUFBQyxVQUFDLEtBQUssRUFBRSxLQUFLLEVBQUU7QUFDcEIsZUFBTyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUE7T0FDMUM7OztXQU5HLEdBQUc7S0FBUyxVQUFVOztBQVNyQixNQUFNLEdBQUcsR0FBRyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUE7O1VBQXRCLEdBQUcsR0FBSCxHQUFHOztNQUdWLE1BQU07YUFBTixNQUFNOzRCQUFOLE1BQU07Ozs7Ozs7Y0FBTixNQUFNOzt5QkFBTixNQUFNOzthQUNMLGVBQUMsQ0FBQyxFQUFFO0FBQ1AsWUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUE7T0FDWDs7V0FDQSxLQUFLO2FBQUMsVUFBQyxLQUFLLEVBQUUsS0FBSyxFQUFFO0FBQ3BCLFlBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsRUFBRTtBQUNqQixpQkFBTyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQTtTQUNsQztBQUNELGVBQU8sS0FBSyxDQUFBO09BQ2I7OztXQVRHLE1BQU07S0FBUyxVQUFVOztBQVl4QixNQUFNLE1BQU0sR0FBRyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUE7VUFBNUIsTUFBTSxHQUFOLE1BQU07QUFDWixNQUFNLE1BQU0sR0FBRyxVQUFBLENBQUM7V0FBSSxNQUFNLENBQUMsVUFBQSxDQUFDO2FBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0tBQUEsQ0FBQztHQUFBLENBQUE7O1VBQWhDLE1BQU0sR0FBTixNQUFNOztNQUViLFdBQVc7YUFBWCxXQUFXOzRCQUFYLFdBQVc7Ozs7Ozs7Y0FBWCxXQUFXOzt5QkFBWCxXQUFXO1dBQ2QsS0FBSzthQUFDLFVBQUMsS0FBSyxFQUFFLEtBQUssRUFBRTtBQUNwQixZQUFJLEtBQUssS0FBSyxJQUFJLENBQUMsSUFBSSxFQUFFO0FBQ3ZCLGNBQUksQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFBO0FBQ2pCLGlCQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFBO1NBQ2xDO0FBQ0QsZUFBTyxLQUFLLENBQUE7T0FDYjs7O1dBUEcsV0FBVztLQUFTLFVBQVU7O0FBVTdCLE1BQU0sV0FBVyxHQUFHLFNBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQTs7VUFBcEMsV0FBVyxHQUFYLFdBQVc7O01BR2xCLFNBQVM7YUFBVCxTQUFTOzRCQUFULFNBQVM7Ozs7Ozs7Y0FBVCxTQUFTOzt5QkFBVCxTQUFTOzthQUNSLGVBQUMsQ0FBQyxFQUFFO0FBQ1AsWUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUE7T0FDWDs7V0FDQSxLQUFLO2FBQUMsVUFBQyxLQUFLLEVBQUUsS0FBSyxFQUFFO0FBQ3BCLFlBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsRUFBRTtBQUNqQixpQkFBTyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQTtTQUNsQztBQUNELGVBQU8sSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUE7T0FDMUI7OztXQVRHLFNBQVM7S0FBUyxVQUFVOztBQVkzQixNQUFNLFNBQVMsR0FBRyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUE7O1VBQWxDLFNBQVMsR0FBVCxTQUFTOztNQUVoQixJQUFJO2FBQUosSUFBSTs0QkFBSixJQUFJOzs7Ozs7O2NBQUosSUFBSTs7eUJBQUosSUFBSTs7YUFDSCxlQUFDLENBQUMsRUFBRTtBQUNQLFlBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFBO09BQ1g7O1dBQ0EsS0FBSzthQUFDLFVBQUMsS0FBSyxFQUFFLEtBQUssRUFBRTtBQUNwQixZQUFJLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFO0FBQ2QsY0FBSSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQTtBQUNuQixlQUFLLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUE7QUFDbEMsY0FBSSxJQUFJLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRTtBQUNyQyxpQkFBSyxHQUFHLElBQUksT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFBO1dBQzNCO1NBQ0Y7QUFDRCxlQUFPLEtBQUssQ0FBQTtPQUNiOzs7V0FiRyxJQUFJO0tBQVMsVUFBVTs7QUFnQnRCLE1BQU0sSUFBSSxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQTs7VUFBeEIsSUFBSSxHQUFKLElBQUk7O01BRVgsSUFBSTthQUFKLElBQUk7NEJBQUosSUFBSTs7Ozs7OztjQUFKLElBQUk7O3lCQUFKLElBQUk7O2FBQ0gsZUFBQyxDQUFDLEVBQUU7QUFDUCxZQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQTtPQUNYOztXQUNBLEtBQUs7YUFBQyxVQUFDLEtBQUssRUFBRSxLQUFLLEVBQUU7QUFDcEIsWUFBSSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNwQixlQUFPLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLEtBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQTtPQUN4RDs7O1dBUEcsSUFBSTtLQUFTLFVBQVU7O0FBVXRCLE1BQU0sSUFBSSxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQTs7VUFBeEIsSUFBSSxHQUFKLElBQUk7O01BRVgsU0FBUzthQUFULFNBQVM7NEJBQVQsU0FBUzs7Ozs7OztjQUFULFNBQVM7O3lCQUFULFNBQVM7O2FBQ1IsZUFBQyxDQUFDLEVBQUU7QUFDUCxZQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQTtBQUNWLFlBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFBO09BQ3JCOztXQUNBLEtBQUs7YUFBQyxVQUFDLEtBQUssRUFBRSxLQUFLLEVBQUU7QUFDcEIsWUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUE7QUFDOUMsZUFBTyxJQUFJLENBQUMsUUFBUSxHQUFHLEtBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQTtPQUMxRDs7O1dBUkcsU0FBUztLQUFTLFVBQVU7O0FBVzNCLE1BQU0sU0FBUyxHQUFHLFdBQVcsQ0FBQyxTQUFTLENBQUMsQ0FBQTs7VUFBbEMsU0FBUyxHQUFULFNBQVM7O01BRWhCLFNBQVM7YUFBVCxTQUFTOzRCQUFULFNBQVM7Ozs7Ozs7Y0FBVCxTQUFTOzt5QkFBVCxTQUFTOzthQUNSLGVBQUMsQ0FBQyxFQUFFO0FBQ1AsWUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUE7QUFDVixZQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQTtBQUNWLFlBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUE7T0FDekI7O1dBQ0EsT0FBTzthQUFDLFVBQUMsS0FBSyxFQUFFO0FBQ2YsWUFBSSxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRTtBQUNkLGVBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7QUFDdkQsZUFBSyxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLEdBQUcsS0FBSyxDQUFBO1NBQ2pEO0FBQ0QsMENBWEUsU0FBUyxhQVdFLE9BQU8sbUJBQUUsS0FBSyxFQUFDO09BQzdCOztXQUNBLEtBQUs7YUFBQyxVQUFDLEtBQUssRUFBRSxLQUFLLEVBQUU7QUFDcEIsWUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFBO0FBQ3pCLFlBQUksQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUE7QUFDbkIsWUFBSSxJQUFJLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDLEVBQUU7QUFDcEIsY0FBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUE7QUFDVixpQkFBTyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBO1NBQy9DO0FBQ0QsZUFBTyxLQUFLLENBQUE7T0FDYjs7O1dBckJHLFNBQVM7S0FBUyxVQUFVOztBQXdCM0IsTUFBTSxTQUFTLEdBQUcsV0FBVyxDQUFDLFNBQVMsQ0FBQyxDQUFBOztVQUFsQyxTQUFTLEdBQVQsU0FBUzs7TUFFaEIsU0FBUzthQUFULFNBQVM7NEJBQVQsU0FBUzs7Ozs7OztjQUFULFNBQVM7O3lCQUFULFNBQVM7V0FDWixLQUFLO2FBQUMsVUFBQyxLQUFLLEVBQUUsS0FBSyxFQUFFO0FBQ3BCLFlBQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFBO0FBQ3pDLGVBQU8sU0FBUyxDQUFDLE1BQU0sQ0FBQyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxNQUFNLENBQUE7T0FDbkQ7OztXQUpHLFNBQVM7S0FBUyxVQUFVOztNQU81QixHQUFHO2FBQUgsR0FBRzs0QkFBSCxHQUFHOzs7Ozs7O2NBQUgsR0FBRzs7eUJBQUgsR0FBRzs7YUFDRixpQkFBRztBQUNOLFlBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxTQUFTLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFBO09BQzdDOztXQUNBLEtBQUs7YUFBQyxVQUFDLEtBQUssRUFBRSxLQUFLLEVBQUU7QUFDcEIsZUFBTyxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUE7T0FDNUM7OztXQU5HLEdBQUc7S0FBUyxVQUFVOztBQVNyQixNQUFNLEdBQUcsR0FBRyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUE7O1VBQXBCLEdBQUcsR0FBSCxHQUFHO0FBRVQsTUFBTSxTQUFTLEdBQUcsVUFBQyxXQUFXLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUs7QUFDbEUsV0FBTyxHQUFHLE9BQU8sWUFBWSxPQUFPLEdBQUcsT0FBTyxHQUNwQyxTQUFTLENBQUMsT0FBTyxDQUFDLEdBQUcsSUFBSSxRQUFRLENBQUMsT0FBTyxDQUFDLEdBQzFDLE9BQU8sT0FBTyxBQUFDLEtBQUssVUFBVSxHQUFHLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxHQUNyRCxJQUFJLENBQUE7O0FBRWQsUUFBSSxDQUFDLE9BQU8sRUFBRTtBQUNaLFlBQU0sU0FBUyw4QkFBOEIsQ0FBQTtLQUM5Qzs7QUFFRCxRQUFNLFVBQVUsR0FBRyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUE7O0FBRXZDLFFBQUksTUFBTSxLQUFLLEtBQUssQ0FBQyxBQUFDLElBQUksT0FBTyxLQUFLLEtBQUssQ0FBQyxBQUFDLEVBQUU7aUJBQ3pCLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDOzs7O0FBQWpELFlBQU07QUFBRSxhQUFPO0tBQ2pCOztBQUVELFFBQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxVQUFVLEVBQUUsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFBO0FBQ2xELFdBQU8sVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFBO0dBQ25DLENBQUE7O1VBbEJZLFNBQVMsR0FBVCxTQUFTOzs7Ozs7O01BeUJULFdBQVcsV0FBWCxXQUFXO2FBQVgsV0FBVzs0QkFBWCxXQUFXOzs7eUJBQVgsV0FBVztXQUNyQixJQUFJLENBQUMsTUFBTTthQUFDLFlBQUc7QUFDZCxlQUFPLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFBO09BQzlCOztXQUNBLE1BQU0sQ0FBQyxNQUFNO2FBQUMsVUFBQyxNQUFNLEVBQUU7QUFDdEIsZUFBTyxNQUFNLENBQUE7T0FDZDs7O1dBTlUsV0FBVzs7Ozs7TUFXWCxVQUFVLFdBQVYsVUFBVTthQUFWLFVBQVU7NEJBQVYsVUFBVTs7Ozs7OztjQUFWLFVBQVU7O1dBQVYsVUFBVTtLQUFTLFdBQVc7Ozs7TUFHOUIsWUFBWSxXQUFaLFlBQVk7YUFBWixZQUFZOzRCQUFaLFlBQVk7Ozs7Ozs7Y0FBWixZQUFZOztXQUFaLFlBQVk7S0FBUyxXQUFXOzs7Ozs7TUFNaEMsVUFBVSxXQUFWLFVBQVU7YUFBVixVQUFVOzRCQUFWLFVBQVU7Ozs7Ozs7Y0FBVixVQUFVOzt5QkFBVixVQUFVO1dBQ3BCLE1BQU0sQ0FBQyxNQUFNO2FBQUMsVUFBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRTtBQUN2QyxZQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFBO0FBQzdDLGVBQU8sU0FBUyxDQUFDLE1BQU0sQ0FBQyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxNQUFNLENBQUE7T0FDbkQ7OztXQUpVLFVBQVU7S0FBUyxXQUFXOzs7O01BUTlCLFFBQVEsV0FBUixRQUFRO2FBQVIsUUFBUTs0QkFBUixRQUFROzs7Ozs7O2NBQVIsUUFBUTs7eUJBQVIsUUFBUTtXQUNsQixJQUFJLENBQUMsTUFBTTthQUFDLFlBQUc7QUFDZCxlQUFPLElBQUksQ0FBQTtPQUNaOztXQUNBLElBQUksQ0FBQyxNQUFNO2FBQUMsVUFBQyxNQUFNLEVBQUUsS0FBSyxFQUFFO0FBQzNCLGVBQU8sSUFBSSxDQUFBO09BQ1o7OztXQU5VLFFBQVE7S0FBUyxVQUFVOzs7O01BVzNCLGFBQWEsV0FBYixhQUFhO2FBQWIsYUFBYTs0QkFBYixhQUFhOzs7Ozs7O2NBQWIsYUFBYTs7eUJBQWIsYUFBYTtXQUN2QixJQUFJLENBQUMsTUFBTTthQUFDLFlBQUc7QUFDZCxlQUFPLEtBQUssQ0FBQyxBQUFDLENBQUE7T0FDZjs7V0FDQSxJQUFJLENBQUMsTUFBTTthQUFDLFVBQUMsTUFBTSxFQUFFLEtBQUssRUFBRTtBQUMzQixlQUFPLEtBQUssQ0FBQyxBQUFDLENBQUE7T0FDZjs7O1dBTlUsYUFBYTtLQUFTLFVBQVU7O01BU2hDLFVBQVUsV0FBVixVQUFVO2FBQVYsVUFBVTs0QkFBVixVQUFVOzs7Ozs7O2NBQVYsVUFBVTs7eUJBQVYsVUFBVTtXQUtwQixJQUFJLENBQUMsTUFBTTs7O2FBQUMsWUFBRztBQUNkLGVBQU8sQ0FBQyxDQUFBO09BQ1Q7O1dBQ0EsSUFBSSxDQUFDLE1BQU07YUFBQyxVQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUU7OztBQUczQixlQUFPLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLEdBQzVELE1BQU0sR0FBRyxLQUFLLENBQUE7T0FDZjs7O2FBWlMsYUFBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFO0FBQ2YsZUFBTyxDQUFDLEdBQUcsQ0FBQyxDQUFBO09BQ2I7OztXQUhVLFVBQVU7S0FBUyxVQUFVOztNQWlCN0IsV0FBVyxXQUFYLFdBQVc7YUFBWCxXQUFXOzRCQUFYLFdBQVc7Ozs7Ozs7Y0FBWCxXQUFXOztXQUFYLFdBQVc7S0FBUyxVQUFVOztNQUU5QixVQUFVLFdBQVYsVUFBVTthQUFWLFVBQVU7NEJBQVYsVUFBVTs7Ozs7OztjQUFWLFVBQVU7O1dBQVYsVUFBVTtLQUFTLFVBQVU7Ozs7OztNQU03QixXQUFXLFdBQVgsV0FBVzthQUFYLFdBQVc7NEJBQVgsV0FBVzs7Ozs7OztjQUFYLFdBQVc7O3lCQUFYLFdBQVc7V0FDckIsTUFBTSxDQUFDLE1BQU07YUFBQyxVQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFO0FBQ3pDLFlBQUksS0FBSyxHQUFHLENBQUMsQ0FBQTtBQUNiLFlBQUksS0FBSyxHQUFHLE9BQU8sQ0FBQTtBQUNuQixZQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFBO0FBQzVCLGVBQU8sS0FBSyxHQUFHLEtBQUssRUFBRTtBQUNwQixlQUFLLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQTtBQUM3QyxjQUFJLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRTtBQUNwQixtQkFBTyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUE7V0FDckI7QUFDRCxlQUFLLEdBQUcsS0FBSyxHQUFHLENBQUMsQ0FBQTtTQUNsQjtBQUNELGVBQU8sS0FBSyxDQUFBO09BQ2I7OztXQWJVLFdBQVc7S0FBUyxXQUFXOztNQWdCL0IsVUFBVSxXQUFWLFVBQVU7YUFBVixVQUFVOzRCQUFWLFVBQVU7Ozs7Ozs7Y0FBVixVQUFVOzt5QkFBVixVQUFVO1dBRXBCLElBQUksQ0FBQyxNQUFNOzs7YUFBQyxZQUFHO0FBQ2QsZUFBTyxFQUFFLENBQUE7T0FDVjs7V0FHQSxJQUFJLENBQUMsTUFBTTs7OzthQUFDLFVBQUMsTUFBTSxFQUFFLEtBQUssRUFBRTtBQUMzQixlQUFPLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxNQUFNLENBQUMsTUFBTSxNQUFBLENBQWIsTUFBTSxxQkFBVyxLQUFLLEVBQUMsR0FBRyxNQUFNLEdBQUcsS0FBSyxDQUFBO09BQ2pFOzs7V0FUVSxVQUFVO0tBQVMsV0FBVzs7TUFhOUIsU0FBUyxXQUFULFNBQVM7YUFBVCxTQUFTOzRCQUFULFNBQVM7Ozs7Ozs7Y0FBVCxTQUFTOzt5QkFBVCxTQUFTO1dBQ25CLElBQUksQ0FBQyxNQUFNO2FBQUMsWUFBRztBQUNkLGVBQU8sRUFBRSxDQUFBO09BQ1Y7O1dBQ0EsSUFBSSxDQUFDLE1BQU07YUFBQyxVQUFDLEtBQUssRUFBRSxLQUFLLEVBQUU7QUFDMUIsYUFBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQTtBQUNqQixlQUFPLEtBQUssQ0FBQTtPQUNiOzs7V0FQVSxTQUFTO0tBQVMsV0FBVzs7OztNQVk3QixZQUFZLFdBQVosWUFBWTthQUFaLFlBQVk7NEJBQVosWUFBWTs7Ozs7OztjQUFaLFlBQVk7O3lCQUFaLFlBQVk7V0FDdEIsSUFBSSxDQUFDLE1BQU07YUFBQyxZQUFHO0FBQ2QsZUFBTyxxQkFBcUIsQ0FBQTtPQUM3Qjs7V0FDQSxJQUFJLENBQUMsTUFBTTthQUFDLFVBQUMsTUFBTSxFQUFFLEtBQUssRUFBRTtBQUMzQixlQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFBO09BQzFDOztXQUNBLE1BQU0sQ0FBQyxNQUFNO2FBQUMsVUFBQyxVQUFVLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRTtBQUMzQyxZQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQTs7Ozs7QUFLcEMsWUFBSSxPQUFPLEtBQUsscUJBQXFCLEVBQUU7QUFDckMsaUJBQU8sSUFBSSxxQkFBcUIsQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUE7U0FDdkQ7Ozs7QUFJRCxZQUFJLE1BQU0sR0FBRyxPQUFPLENBQUE7QUFDcEIsZUFBTSxJQUFJLEVBQUU7K0JBQ1ksUUFBUSxDQUFDLElBQUksRUFBRTs7Y0FBOUIsSUFBSSxrQkFBSixJQUFJO2NBQUUsTUFBSyxrQkFBTCxLQUFLOztBQUNsQixjQUFJLElBQUksRUFBRTtBQUNSLG1CQUFPLE1BQU0sQ0FBQTtXQUNkOztBQUVELGdCQUFNLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sRUFBRSxNQUFLLENBQUMsQ0FBQTs7QUFFekMsY0FBSSxTQUFTLENBQUMsTUFBTSxDQUFDLEVBQUU7QUFDckIsbUJBQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFBO1dBQ3RCO1NBQ0Y7T0FDRjs7O1dBaENVLFlBQVk7S0FBUyxVQUFVOztNQW1DL0IscUJBQXFCLFdBQXJCLHFCQUFxQjtBQUNyQixhQURBLHFCQUFxQixDQUNwQixNQUFNLEVBQUUsVUFBVSxFQUFFOzRCQURyQixxQkFBcUI7Ozs7O0FBSzlCLFVBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUE7O0FBRWxCLFVBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFBO0FBQ3BCLFVBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFBO0FBQzVCLFVBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFBO0FBQ3RCLFVBQUksQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFBO0tBQ2xCOztjQVhVLHFCQUFxQjs7eUJBQXJCLHFCQUFxQjtXQVkvQixJQUFJLENBQUMsTUFBTTthQUFDLFVBQUMsTUFBTSxFQUFFLEtBQUssRUFBRTtBQUMzQixjQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFBO0FBQzNCLGVBQU8sTUFBTSxDQUFBO09BQ2Q7O1dBQ0EsU0FBUzthQUFDLFlBQUc7QUFDWixlQUFPLElBQUksQ0FBQTtPQUNaOzs7YUFDRyxnQkFBRzs7Ozs7OztBQU9MLGVBQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFOzZCQUM5QixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRTs7Y0FBakMsSUFBSSxnQkFBSixJQUFJO2NBQUUsTUFBSyxnQkFBTCxLQUFLOzs7O0FBR2xCLGNBQUksSUFBSSxFQUFFO0FBQ1IsZ0JBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUE7QUFDOUIsZ0JBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFBO1dBQ3RCOzs7ZUFHSTtBQUNILGdCQUFNLE9BQU0sR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksRUFBRSxNQUFLLENBQUMsQ0FBQTtBQUNsRCxnQkFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUMsT0FBTSxDQUFDLENBQUE7V0FDbkM7U0FDRjs7Ozs7QUFLRCxZQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO0FBQzVCLGNBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFBO1NBQ25DLE1BQU07QUFDTCxjQUFJLENBQUMsS0FBSyxHQUFHLFNBQVMsQ0FBQTtBQUN0QixjQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUE7U0FDM0I7O0FBRUQsZUFBTyxJQUFJLENBQUE7T0FDWjs7O1dBckRVLHFCQUFxQjtLQUFTLFlBQVk7O0FBdUR2RCxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsOEJBQThCLENBQUMsQ0FBQTtBQUN0RCx1QkFBcUIsQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFBIiwiZmlsZSI6InNyYy90cmFuc2R1Y2Vycy5qcyIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IGlzU3ltYm9sRGVmaW5lZCA9IHR5cGVvZihTeW1ib2wpICE9PSAndW5kZWZpbmVkJztcbmNvbnN0IHN5bWJvbCA9IChpc1N5bWJvbERlZmluZWQgJiYgU3ltYm9sLmZvcikgfHwgaGludCA9PiBgQEAke2hpbnR9YFxuXG5jb25zdCAkaXRlcmF0b3IgPSBpc1N5bWJvbERlZmluZWQgJiYgU3ltYm9sLml0ZXJhdG9yIHx8IHN5bWJvbCgnaXRlcmF0b3InKVxuXG5cblxuZXhwb3J0IGNvbnN0IG1ldGhvZE9mID0gKHRhcmdldCwgaWQpID0+IHtcbiAgbGV0IG1ldGhvZCA9IHRhcmdldCAmJiB0YXJnZXRbaWRdXG4gIGlmICghbWV0aG9kKSB7XG4gICAgY29uc3QgdHlwZSA9IHR5cGVvZih0YXJnZXQpXG4gICAgbWV0aG9kID0gdGFyZ2V0ID09PSBudWxsID8gTnVsbFR5cGUucHJvdG90eXBlW2lkXSA6XG4gICAgdGFyZ2V0ID09PSB2b2lkKDApID8gVW5kZWZpbmVkVHlwZS5wcm90b3R5cGVbaWRdIDpcbiAgICB0eXBlID09PSAnc3RyaW5nJyA/IFN0cmluZ1R5cGUucHJvdG90eXBlW2lkXSA6XG4gICAgdHlwZSA9PT0gJ251bWJlcicgPyBOdW1iZXJUeXBlLnByb3RvdHlwZVtpZF0gOlxuICAgIHR5cGUgPT09ICdib29sZWFuJyA/IEJvb2xlYW5UeXBlLnByb3RvdHlwZVtpZF0gOlxuICAgIHR5cGUgPT09ICdzeW1ib2wnID8gU3ltYm9sVHlwZS5wcm90b3R5cGVbaWRdIDpcbiAgICBpc0FycmF5KHRhcmdldCkgPyBBcnJheVR5cGUucHJvdG90eXBlW2lkXSA6XG4gICAgaXNJdGVyYXRvcih0YXJnZXQpID8gSXRlcmF0b3JUeXBlLnByb3RvdHlwZVtpZF0gOlxuICAgIGlzUmVnRXhwKHRhcmdldCkgPyBSZWdFeHBUeXBlLnByb3RvdHlwZVtpZF0gOlxuICAgIHR5cGUgPT09ICdmdW5jdGlvbicgPyBGdW5jdGlvblR5cGUucHJvdG90eXBlW2lkXSA6XG4gICAgdHlwZSA9PT0gJ29iamVjdCcgPyBPYmplY3RUeXBlLnByb3RvdHlwZVtpZF0gOlxuICAgIERlZmF1bHRUeXBlLnByb3RvdHlwZVtpZF1cbiAgfVxuICByZXR1cm4gbWV0aG9kXG59XG5cbmNvbnN0IGRpc3BhdGNoZXIgPSAobmFtZSwgaW5kZXg9MCkgPT4ge1xuICBjb25zdCBpZCA9IHN5bWJvbChuYW1lKVxuICBjb25zdCBkaXNwYXRjaCA9IChhLCBiLCBjLCBkLCBlKSA9PiB7XG4gICAgY29uc3QgdGFyZ2V0ID0gaW5kZXggPT09IDAgPyBhIDpcbiAgICAgICAgICAgICAgICAgICBpbmRleCA9PT0gMSA/IGIgOlxuICAgICAgICAgICAgICAgICAgIGluZGV4ID09PSAyID8gYyA6XG4gICAgICAgICAgICAgICAgICAgaW5kZXggPT09IDMgPyBkIDpcbiAgICAgICAgICAgICAgICAgICBlO1xuICAgIGNvbnN0IG1ldGhvZCA9IG1ldGhvZE9mKHRhcmdldCwgaWQpXG5cbiAgICBpZiAoIW1ldGhvZCkge1xuICAgICAgdGhyb3cgVHlwZUVycm9yKGB0YXJnZXQgZG9lcyBub3QgaW1wbGVtZW50cyAke2lkfSBtZXRob2RgKVxuICAgIH1cblxuICAgIHJldHVybiBtZXRob2QuY2FsbCh0YXJnZXQsIGEsIGIsIGMsIGQsIGUpXG4gIH1cbiAgZGlzcGF0Y2guc3ltYm9sID0gaWRcbiAgcmV0dXJuIGRpc3BhdGNoXG59XG5cbmV4cG9ydCBjb25zdCBpbml0ID0gZGlzcGF0Y2hlcihcInRyYW5zZHVjZXIvaW5pdFwiKVxuY29uc3QgJGluaXQgPSBpbml0LnN5bWJvbFxuXG5leHBvcnQgY29uc3QgcmVzdWx0ID0gZGlzcGF0Y2hlcihcInRyYW5zZHVjZXIvcmVzdWx0XCIpXG5jb25zdCAkcmVzdWx0ID0gcmVzdWx0LnN5bWJvbFxuXG5leHBvcnQgY29uc3Qgc3RlcCA9IGRpc3BhdGNoZXIoXCJ0cmFuc2R1Y2VyL3N0ZXBcIilcbmNvbnN0ICRzdGVwID0gc3RlcC5zeW1ib2xcblxuZXhwb3J0IGNvbnN0IHJlZHVjZSA9IGRpc3BhdGNoZXIoXCJ0cmFuc2R1Y2VyL3JlZHVjZVwiLCAyKVxuY29uc3QgJHJlZHVjZSA9IHJlZHVjZS5zeW1ib2xcblxuZXhwb3J0IGNvbnN0IHJlZHVjZWQgPSB2YWx1ZSA9PiBuZXcgUmVkdWNlZCh2YWx1ZSlcbmNvbnN0ICRyZWR1Y2VkID0gcmVkdWNlZC5zeW1ib2wgPSBzeW1ib2woXCJ0cmFuc2R1Y2VyL3JlZHVjZWRcIilcblxuZXhwb3J0IGNvbnN0IHZhbHVlID0gcmVkdWNlZCA9PiByZWR1Y2VkWyR2YWx1ZV1cbmNvbnN0ICR2YWx1ZSA9IHZhbHVlLnN5bWJvbCA9IHN5bWJvbChcInRyYW5zZHVjZXIvdmFsdWVcIilcblxuZXhwb3J0IGNvbnN0IHRyYW5zZm9ybWVyID0gdHJhbnNmb3JtID0+IHtcbiAgdHJhbnNmb3JtWyR0cmFuc2Zvcm1lcl0gPSB0cnVlXG4gIHJldHVybiB0cmFuc2Zvcm1lclxufVxuY29uc3QgJHRyYW5zZm9ybWVyID0gdHJhbnNmb3JtZXIuc3ltYm9sID0gc3ltYm9sKFwidHJhbnNkdWNlci90cmFuc2Zvcm1lclwiKVxuXG5jb25zdCBwcm90b3R5cGUgPSBPYmplY3QucHJvdG90eXBlXG5cbi8vIFJldHVybnMgYHRydWVgIGlmIGdpdmVuIGB4YCBpcyBhIEpTIGFycmF5LlxuZXhwb3J0IGNvbnN0IGlzQXJyYXkgPSBBcnJheS5pc0FycmF5IHx8XG4gIHggPT4gcHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoeCkgPT09ICdbb2JqZWN0IEFycmF5XSdcblxuLy8gUmV0dXJucyBgdHJ1ZWAgaWYgZ2l2ZW4gYHhgIGlzIGEgcmVndWxhciBleHByZXNzaW9uLlxuZXhwb3J0IGNvbnN0IGlzUmVnRXhwID0geCA9PlxuICBwcm90b3R5cGUudG9TdHJpbmcuY2FsbCh4KSA9PT0gJ1tvYmplY3QgUmVnRXhwXSdcblxuLy8gUmV0dXJucyBgdHJ1ZWAgaWYgZ2l2ZW4gYHhgIGlzIGEgSlMgaXRlcmF0b3IuXG5leHBvcnQgY29uc3QgaXNJdGVyYXRvciA9IHggPT5cbiAgeCAmJiB4WyRpdGVyYXRvcl1cblxuLy8gUmV0dXJucyB0cnVlIGlmIGB4YCBpcyBib3hlZCB2YWx1ZSAmIHNpZ25pZmllcyB0aGF0XG4vLyByZWR1Y3Rpb24gaXMgY29tcGxldGUuXG5leHBvcnQgY29uc3QgaXNSZWR1Y2VkID0geCA9PlxuICB4IGluc3RhbmNlb2YgUmVkdWNlZCB8fCAoeCAmJiB4WyRyZWR1Y2VkXSlcblxuZXhwb3J0IGNvbnN0IGlzUmVkdWNpYmxlID0geCA9PlxuICB4ICYmIG1ldGhvZE9mKHgsICRyZWR1Y2UpXG5cbmV4cG9ydCBjb25zdCBpc1JlZHVjZXIgPSB4ID0+XG4gIHggaW5zdGFuY2VvZiBSZWR1Y2VyIHx8IG1ldGhvZE9mKHgsICRzdGVwKVxuXG5leHBvcnQgY29uc3QgaXNUcmFuc2Zvcm1lciA9IHggPT5cbiAgeCAmJiB4WyR0cmFuc2Zvcm1lcl1cblxuLy8gQ2xhc3MgaXMgdXNlZCB0byBib3ggcmVzdWx0IG9mIHJlZHVjdGlvbiBzdGVwIGluIG9yZGVyXG4vLyB0byBzaWduYWwgY2hhaW5lZCB0cmFuc2R1Y2VyIHRoYXQgcmVkdWN0aW9uIGhhcyBjb21wbGV0ZWQuXG5leHBvcnQgY2xhc3MgUmVkdWNlZCB7XG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpc1skcmVkdWNlZF0gPSB0cnVlXG4gICAgdGhpc1skdmFsdWVdID0gdmFsdWVcblxuICAgIC8vIENvbXBhdGliaWxpdHkgd2l0aCBvdGhlciBsaWJzOlxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9jb2duaXRlY3QtbGFicy90cmFuc2R1Y2Vycy1qc1xuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9qbG9uZ3N0ZXIvdHJhbnNkdWNlcnMuanNcbiAgICB0aGlzLl9fdHJhbnNkdWNlcnNfcmVkdWNlZF9fID0gdHJ1ZVxuICAgIHRoaXMudmFsdWUgPSB2YWx1ZVxuICB9XG59XG5SZWR1Y2VkLnN5bWJvbCA9ICRyZWR1Y2VkXG5cblxuZXhwb3J0IGNsYXNzIFJlZHVjZXIge1xuICBjb25zdHJ1Y3Rvcih7aW5pdCwgc3RlcCwgcmVzdWx0fSkge1xuICAgIHRoaXNbJGluaXRdID0gaW5pdCB8fCB0aGlzWyRpbml0XVxuICAgIHRoaXNbJHN0ZXBdID0gc3RlcCB8fCB0aGlzWyRzdGVwXVxuICAgIHRoaXNbJHJlc3VsdF0gPSByZXN1bHQgfHwgdGhpc1skcmVzdWx0XVxuICB9XG4gIFskaW5pdF0oKSB7XG4gICAgdGhyb3cgVHlwZUVycm9yKCdSZWR1Y2VyIG11c3QgaW1wbGVtZW50IFtTeW1ib2wuZm9yKFwidHJhbnNkdWNlci9pbml0XCIpXScpXG4gIH1cbiAgWyRzdGVwXShyZXN1bHQsIGlucHV0KSB7XG4gICAgdGhyb3cgVHlwZUVycm9yKCdSZWR1Y2VyIG11c3QgaW1wbGVtZW50IFtTeW1ib2wuZm9yKFwidHJhbnNkdWNlci9zdGVwXCIpXScpXG4gIH1cbiAgWyRyZXN1bHRdKHJlc3VsdCkge1xuICAgIHRocm93IFR5cGVFcnJvcignUmVkdWNlciBtdXN0IGltcGxlbWVudCBbU3ltYm9sLmZvcihcInRyYW5zZHVjZXIvcmVzdWx0XCIpXScpXG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFByb2R1Y2VyIGV4dGVuZHMgUmVkdWNlciB7XG4gIGNvbnN0cnVjdG9yKHNvdXJjZSkge1xuICAgIHRoaXNbJGluaXRdID0gbWV0aG9kT2Yoc291cmNlLCAkaW5pdClcbiAgICB0aGlzWyRzdGVwXSA9IG1ldGhvZE9mKHNvdXJjZSwgJHN0ZXApXG4gICAgdGhpc1skcmVzdWx0XSA9IG1ldGhvZE9mKHNvdXJjZSwgJHJlc3VsdClcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgU3RlcHBlciBleHRlbmRzIFJlZHVjZXIge1xuICBjb25zdHJ1Y3RvcihmKSB7XG4gICAgdGhpc1skc3RlcF0gPSBmXG4gIH1cbiAgWyRpbml0XSgpIHtcbiAgICByZXR1cm4gdGhpc1skc3RlcF0oKVxuICB9XG4gIFskcmVzdWx0XShyZXN1bHQpIHtcbiAgICByZXR1cm4gcmVzdWx0XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFRyYW5zZHVjZXIgZXh0ZW5kcyBSZWR1Y2VyIHtcbiAgY29uc3RydWN0b3IocmVkdWNlciwgLi4ucGFyYW1zKSB7XG4gICAgdGhpcy5yZWR1Y2VyID0gcmVkdWNlclxuICAgIHRoaXMuc2V0dXAoLi4ucGFyYW1zKVxuICB9XG4gIHNldHVwKCkge1xuICB9XG4gIFskaW5pdF0oKSB7XG4gICAgcmV0dXJuIHRoaXMucmVkdWNlclskaW5pdF0oKVxuICB9XG4gIFskc3RlcF0ocmVzdWx0LCBpbnB1dCkge1xuICAgIHJldHVybiB0aGlzLmFkdmFuY2UocmVzdWx0LCBpbnB1dClcbiAgfVxuICBhZHZhbmNlKHJlc3VsdCwgaW5wdXQpIHtcbiAgICByZXR1cm4gdGhpcy5yZWR1Y2VyWyRzdGVwXShyZXN1bHQsIGlucHV0KVxuICB9XG4gIFskcmVzdWx0XShyZXN1bHQpIHtcbiAgICByZXR1cm4gdGhpcy5yZWR1Y2VyWyRyZXN1bHRdKHJlc3VsdClcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgQ29tcG9zaXRlIGV4dGVuZHMgVHJhbnNkdWNlciB7XG4gIGNvbnN0cnVjdG9yKHNvdXJjZSwgdHJhbnNmb3JtZXIsIFRyYW5zZHVjZXJUeXBlLCAuLi5wYXJhbXMpIHtcbiAgICB0aGlzLnJlZHVjZXIgPSBuZXcgVHJhbnNkdWNlclR5cGUodHJhbnNmb3JtZXIoc291cmNlKSwgLi4ucGFyYW1zKVxuICB9XG59XG5cbi8vIENyZWF0ZXMgYSB0cmFuc2Zvcm1lciBmdW5jdGlvbiB0aGF0IGlzIGEgdGh1bmsgZm9yIGBUcmFuc2R1Y2VyVHlwZWAgYW5kIGl0J3MgcGFyYW1ldGVycy5cbi8vIE9uY2UgcmV0dXJuZWQgdHJhbnNmb3JtZXIgaXMgaW5vdmtlZCBpdCdzIGdvaW5nIHRvIGRvIG9uZSBvZiB0aGUgZm9sbG93aW5nIHRoaW5nczpcbi8vIC0gSWYgYXJndW1lbnQgaXMgYW4gaW5zdGFuY2Ugb2YgYSBgUmVkdWNlcmAgaXQncyBnb2luZyB0byBjcmVhdGUgYW4gaW5zdGFuY2Ugb2YgVHJhbnNkdWNlclxuLy8gICB3aXRoIGEgZ2l2ZW4gYXJndW1lbnQgYXQgdGhlIGJvdHRvbSBvZiB0aGUgY2hhaW4uXG4vLyAtIElmIGFyZ3VtZW50IGlzIGFub3RoZXIgdHJhbnNmb3JtZXIgaXQncyBnb2luZyB0byByZXR1cm4gY29tcG9zZWQgdHJhbnNmb3JtZXIuXG4vLyAtIElmIGFyZ3VtZW50IGlzIGEgcmVkdWNpYmxlIGRhdGEgc3RydWN0dXJlIHdpdGggZGVmaW5lZCByZWR1Y2VyIGl0J3MgZ29pbmcgdG8gcmV0dXJuXG4vLyAgIHRyYW5zZHVjZXIgYXBwbGljYXRpb24gb3ZlciBpdC5cbmV4cG9ydCBjb25zdCBUcmFuc2Zvcm0gPSAoVHJhbnNkdWNlclR5cGUsIC4uLnBhcmFtcykgPT4ge1xuICBjb25zdCB0cmFuc2Zvcm0gPSBzb3VyY2UgPT4ge1xuICAgIGlmIChzb3VyY2UgaW5zdGFuY2VvZiBSZWR1Y2VyKSB7XG4gICAgICByZXR1cm4gbmV3IFRyYW5zZHVjZXJUeXBlKHNvdXJjZSwgLi4ucGFyYW1zKVxuICAgIH0gZWxzZSBpZiAoc291cmNlICYmIHNvdXJjZVskdHJhbnNmb3JtZXJdKSB7XG4gICAgICByZXR1cm4gVHJhbnNmb3JtKENvbXBvc2l0ZSwgc291cmNlLCBUcmFuc2R1Y2VyVHlwZSwgLi4ucGFyYW1zKVxuICAgIH0gZWxzZSBpZiAoaXNSZWR1Y2VyKHNvdXJjZSkpIHtcbiAgICAgIGNvbnN0IHRyYW5zZHVjZXIgPSBuZXcgVHJhbnNkdWNlclR5cGUobmV3IFByb2R1Y2VyKHNvdXJjZSksIC4uLnBhcmFtcylcbiAgICAgIGNvbnN0IGluaXRpYWwgPSB0cmFuc2R1Y2VyWyRpbml0XSgpXG4gICAgICBjb25zdCByZXN1bHQgPSByZWR1Y2UodHJhbnNkdWNlciwgaW5pdGlhbCwgc291cmNlKVxuICAgICAgcmV0dXJuIHRyYW5zZHVjZXJbJHJlc3VsdF0ocmVzdWx0KVxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBUeXBlRXJyb3IoXCJVbnN1cHBvcnRlZCBhcmd1bWVudCB0eXBlIHdhcyBwYXNzZWQgdG8gYSB0cmFuc2Zvcm1lclwiKVxuICAgIH1cbiAgfVxuICAvLyBTaG91bGQgdXNlIGB0cmFuc2Zvcm1lcmAgaW5zdGVhZCBidXQgZm9yIGRlYnVnZ2luZyBpdCdzIGtpbmRcbiAgLy8gb2YgaGFuZHkgdG8gYXR0YWNoIGBUcmFuc2R1Y2VyVHlwZWAgYW5kIGl0IGBwYXJhbXNgIHNvIHdlIGtlZXBcbiAgLy8gdGhpcyBmb3Igbm93LlxuICB0cmFuc2Zvcm1bJHRyYW5zZm9ybWVyXSA9IHRydWVcbiAgdHJhbnNmb3JtLlRyYW5zZHVjZXIgPSBUcmFuc2R1Y2VyVHlwZVxuICB0cmFuc2Zvcm0ucGFyYW1zID0gcGFyYW1zXG4gIHJldHVybiB0cmFuc2Zvcm1cbn1cblRyYW5zZm9ybS5zeW1ib2wgPSAkdHJhbnNmb3JtZXJcblxuLy8gTGlrZSBgVHJhbnNmb3JtYCBidXQgYWxsb3dzIHBhc3NpbmcgcGFyYW1ldGVycyBpbiB0aGUgc2VwYXJhdGUgY2FsbC5cbmV4cG9ydCBjb25zdCBUcmFuc2Zvcm1lciA9IFRyYW5zZHVjZXJUeXBlID0+ICguLi5wYXJhbXMpID0+XG4gIFRyYW5zZm9ybShUcmFuc2R1Y2VyVHlwZSwgLi4ucGFyYW1zKVxuXG4vLyBUcmFuc2R1Y2Vycy5cblxuY2xhc3MgTWFwIGV4dGVuZHMgVHJhbnNkdWNlciB7XG4gIHNldHVwKGYpIHtcbiAgICB0aGlzLmYgPSBmXG4gIH1cbiAgWyRzdGVwXShzdGF0ZSwgaW5wdXQpIHtcbiAgICByZXR1cm4gdGhpcy5hZHZhbmNlKHN0YXRlLCB0aGlzLmYoaW5wdXQpKVxuICB9XG59XG5cbmV4cG9ydCBjb25zdCBtYXAgPSBUcmFuc2Zvcm1lcihNYXApXG5cblxuY2xhc3MgRmlsdGVyIGV4dGVuZHMgVHJhbnNkdWNlciB7XG4gIHNldHVwKHApIHtcbiAgICB0aGlzLnAgPSBwXG4gIH1cbiAgWyRzdGVwXShzdGF0ZSwgaW5wdXQpIHtcbiAgICBpZiAodGhpcy5wKGlucHV0KSkge1xuICAgICAgcmV0dXJuIHRoaXMuYWR2YW5jZShzdGF0ZSwgaW5wdXQpXG4gICAgfVxuICAgIHJldHVybiBzdGF0ZVxuICB9XG59XG5cbmV4cG9ydCBjb25zdCBmaWx0ZXIgPSBUcmFuc2Zvcm1lcihGaWx0ZXIpXG5leHBvcnQgY29uc3QgcmVtb3ZlID0gcCA9PiBmaWx0ZXIoeCA9PiAhcCh4KSlcblxuY2xhc3MgRHJvcFJlcGVhdHMgZXh0ZW5kcyBUcmFuc2R1Y2VyIHtcbiAgWyRzdGVwXShzdGF0ZSwgaW5wdXQpIHtcbiAgICBpZiAoaW5wdXQgIT09IHRoaXMubGFzdCkge1xuICAgICAgdGhpcy5sYXN0ID0gaW5wdXRcbiAgICAgIHJldHVybiB0aGlzLmFkdmFuY2Uoc3RhdGUsIGlucHV0KVxuICAgIH1cbiAgICByZXR1cm4gc3RhdGVcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgZHJvcFJlcGVhdHMgPSBUcmFuc2Zvcm0oRHJvcFJlcGVhdHMpXG5cblxuY2xhc3MgVGFrZVdoaWxlIGV4dGVuZHMgVHJhbnNkdWNlciB7XG4gIHNldHVwKHApIHtcbiAgICB0aGlzLnAgPSBwXG4gIH1cbiAgWyRzdGVwXShzdGF0ZSwgaW5wdXQpIHtcbiAgICBpZiAodGhpcy5wKGlucHV0KSkge1xuICAgICAgcmV0dXJuIHRoaXMuYWR2YW5jZShzdGF0ZSwgaW5wdXQpXG4gICAgfVxuICAgIHJldHVybiBuZXcgUmVkdWNlZChzdGF0ZSlcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgdGFrZVdoaWxlID0gVHJhbnNmb3JtZXIoVGFrZVdoaWxlKVxuXG5jbGFzcyBUYWtlIGV4dGVuZHMgVHJhbnNkdWNlciB7XG4gIHNldHVwKG4pIHtcbiAgICB0aGlzLm4gPSBuXG4gIH1cbiAgWyRzdGVwXShzdGF0ZSwgaW5wdXQpIHtcbiAgICBpZiAodGhpcy5uID4gMCkge1xuICAgICAgdGhpcy5uID0gdGhpcy5uIC0gMVxuICAgICAgc3RhdGUgPSB0aGlzLmFkdmFuY2Uoc3RhdGUsIGlucHV0KVxuICAgICAgaWYgKHRoaXMubiA9PT0gMCAmJiAhaXNSZWR1Y2VkKHN0YXRlKSkge1xuICAgICAgICBzdGF0ZSA9IG5ldyBSZWR1Y2VkKHN0YXRlKVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gc3RhdGVcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgdGFrZSA9IFRyYW5zZm9ybWVyKFRha2UpXG5cbmNsYXNzIERyb3AgZXh0ZW5kcyBUcmFuc2R1Y2VyIHtcbiAgc2V0dXAobikge1xuICAgIHRoaXMubiA9IG5cbiAgfVxuICBbJHN0ZXBdKHN0YXRlLCBpbnB1dCkge1xuICAgIHRoaXMubiA9IHRoaXMubiAtIDE7XG4gICAgcmV0dXJuIHRoaXMubiA+PSAwID8gc3RhdGUgOiB0aGlzLmFkdmFuY2Uoc3RhdGUsIGlucHV0KVxuICB9XG59XG5cbmV4cG9ydCBjb25zdCBkcm9wID0gVHJhbnNmb3JtZXIoRHJvcClcblxuY2xhc3MgRHJvcFdoaWxlIGV4dGVuZHMgVHJhbnNkdWNlciB7XG4gIHNldHVwKHApIHtcbiAgICB0aGlzLnAgPSBwXG4gICAgdGhpcy5kcm9wcGluZyA9IHRydWVcbiAgfVxuICBbJHN0ZXBdKHN0YXRlLCBpbnB1dCkge1xuICAgIHRoaXMuZHJvcHBpbmcgPSB0aGlzLmRyb3BwaW5nICYmIHRoaXMucChpbnB1dClcbiAgICByZXR1cm4gdGhpcy5kcm9wcGluZyA/IHN0YXRlIDogdGhpcy5hZHZhbmNlKHN0YXRlLCBpbnB1dClcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgZHJvcFdoaWxlID0gVHJhbnNmb3JtZXIoRHJvcFdoaWxlKVxuXG5jbGFzcyBQYXJ0aXRpb24gZXh0ZW5kcyBUcmFuc2R1Y2VyIHtcbiAgc2V0dXAobikge1xuICAgIHRoaXMubiA9IG5cbiAgICB0aGlzLmkgPSAwXG4gICAgdGhpcy5wYXJ0ID0gbmV3IEFycmF5KG4pXG4gIH1cbiAgWyRyZXN1bHRdKHN0YXRlKSB7XG4gICAgaWYgKHRoaXMuaSA+IDApIHtcbiAgICAgIHN0YXRlID0gdGhpcy5hZHZhbmNlKHN0YXRlLCB0aGlzLnBhcnQuc2xpY2UoMCwgdGhpcy5pKSlcbiAgICAgIHN0YXRlID0gaXNSZWR1Y2VkKHN0YXRlKSA/IHN0YXRlWyR2YWx1ZV0gOiBzdGF0ZVxuICAgIH1cbiAgICByZXR1cm4gc3VwZXJbJHJlc3VsdF0oc3RhdGUpXG4gIH1cbiAgWyRzdGVwXShzdGF0ZSwgaW5wdXQpIHtcbiAgICB0aGlzLnBhcnRbdGhpcy5pXSA9IGlucHV0XG4gICAgdGhpcy5pID0gdGhpcy5pICsgMVxuICAgIGlmICh0aGlzLmkgPT0gdGhpcy5uKSB7XG4gICAgICB0aGlzLmkgPSAwXG4gICAgICByZXR1cm4gdGhpcy5hZHZhbmNlKHN0YXRlLCB0aGlzLnBhcnQuc2xpY2UoMCkpXG4gICAgfVxuICAgIHJldHVybiBzdGF0ZVxuICB9XG59XG5cbmV4cG9ydCBjb25zdCBwYXJ0aXRpb24gPSBUcmFuc2Zvcm1lcihQYXJ0aXRpb24pXG5cbmNsYXNzIEZvcndhcmRlciBleHRlbmRzIFRyYW5zZHVjZXIge1xuICBbJHN0ZXBdKHN0YXRlLCBpbnB1dCkge1xuICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuYWR2YW5jZShzdGF0ZSwgaW5wdXQpXG4gICAgcmV0dXJuIGlzUmVkdWNlZChyZXN1bHQpID8gcmVzdWx0WyR2YWx1ZV0gOiByZXN1bHRcbiAgfVxufVxuXG5jbGFzcyBDYXQgZXh0ZW5kcyBUcmFuc2R1Y2VyIHtcbiAgc2V0dXAoKSB7XG4gICAgdGhpcy5mb3J3YXJkZXIgPSBuZXcgRm9yd2FyZGVyKHRoaXMucmVkdWNlcilcbiAgfVxuICBbJHN0ZXBdKHN0YXRlLCBpbnB1dCkge1xuICAgIHJldHVybiByZWR1Y2UodGhpcy5mb3J3YXJkZXIsIHN0YXRlLCBpbnB1dClcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgY2F0ID0gVHJhbnNmb3JtKENhdClcblxuZXhwb3J0IGNvbnN0IHRyYW5zZHVjZSA9ICh0cmFuc2Zvcm1lciwgcmVkdWNlciwgaW5pdGlhbCwgc291cmNlKSA9PiB7XG4gIHJlZHVjZXIgPSByZWR1Y2VyIGluc3RhbmNlb2YgUmVkdWNlciA/IHJlZHVjZXIgOlxuICAgICAgICAgICAgaXNSZWR1Y2VyKHJlZHVjZXIpID8gbmV3IFByb2R1Y2VyKHJlZHVjZXIpIDpcbiAgICAgICAgICAgIHR5cGVvZihyZWR1Y2VyKSA9PT0gXCJmdW5jdGlvblwiID8gbmV3IFN0ZXBwZXIocmVkdWNlcikgOlxuICAgICAgICAgICAgbnVsbFxuXG4gIGlmICghcmVkdWNlcikge1xuICAgIHRocm93IFR5cGVFcnJvcihgSW52YWxpZCByZWR1Y2VyIHdhcyBwYXNzZWRgKVxuICB9XG5cbiAgY29uc3QgdHJhbnNkdWNlciA9IHRyYW5zZm9ybWVyKHJlZHVjZXIpXG5cbiAgaWYgKHNvdXJjZSA9PT0gdm9pZCgwKSAmJiBpbml0aWFsICE9PSB2b2lkKDApKSB7XG4gICAgW3NvdXJjZSwgaW5pdGlhbF0gPSBbaW5pdGlhbCwgdHJhbnNkdWNlclskaW5pdF0oKV1cbiAgfVxuXG4gIGNvbnN0IHJlc3VsdCA9IHJlZHVjZSh0cmFuc2R1Y2VyLCBpbml0aWFsLCBzb3VyY2UpXG4gIHJldHVybiB0cmFuc2R1Y2VyWyRyZXN1bHRdKHJlc3VsdClcbn1cblxuLy8gSW50ZXJmYWNlIGltcGxlbWVudGF0aW9ucyBmb3IgYnVpbHQtaW4gdHlwZXMgc28gd2UgZG9uJ3QgaGF2ZVxuLy8gdG8gcGF0Y2ggYnVpbHQtaW5zLlxuXG4vLyBEZWZhbHR1IHR5cGUgaXMgdGhlIGJvdHRvbSB0eXBlIGFsbCB0eXBlcyBpbmNsdWRpbmcgbnVsbCB1bmRlZmluZWRcbi8vIGFuZCBvYmplY3QgYXJlIGdvaW5nIHRvIGluaGVyaXQgZnJvbSBpdC5cbmV4cG9ydCBjbGFzcyBEZWZhdWx0VHlwZSB7XG4gIFtpbml0LnN5bWJvbF0oKSB7XG4gICAgcmV0dXJuIG5ldyB0aGlzLmNvbnN0cnVjdG9yKClcbiAgfVxuICBbcmVzdWx0LnN5bWJvbF0ocmVzdWx0KSB7XG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG59XG5cblxuLy8gV2UgZG9uIG5vdCBtYWtlIG9iamVjdHMgdHJhbnNkdWNpYmxlLlxuZXhwb3J0IGNsYXNzIE9iamVjdFR5cGUgZXh0ZW5kcyBEZWZhdWx0VHlwZSB7fVxuXG4vLyBXZSBkbyBub3QgbWFrZSBmdW5jdGlvbnMgdHJhbnNkdWNpYmxlLlxuZXhwb3J0IGNsYXNzIEZ1bmN0aW9uVHlwZSBleHRlbmRzIERlZmF1bHRUeXBlIHt9XG5cblxuLy8gQWxsIHByaW1pdGl2ZXMgZ29uaWcgdG8gaW5oZXJpdCBmcm9tIEF0b21pdFR5cGUgd2hpY2hcbi8vIHByb3ZpZGVzIGByZWR1Y2VgIGltcGxlbWVudGF0aW9uIHRoYXQncyBnb25pZyB0byBpbnZva2Vcbi8vIHJlZHVjZXIganVzdCBvbmNlIHdpdGggYSB2YWx1ZSBvZiB0aGUgZGF0YSB0eXBlIGl0c2VsZi5cbmV4cG9ydCBjbGFzcyBBdG9taWNUeXBlIGV4dGVuZHMgRGVmYXVsdFR5cGUge1xuICBbcmVkdWNlLnN5bWJvbF0ocmVkdWNlciwgaW5pdGlhbCwgdmFsdWUpIHtcbiAgICBjb25zdCByZXN1bHQgPSByZWR1Y2VyWyRzdGVwXShpbml0aWFsLCB2YWx1ZSlcbiAgICByZXR1cm4gaXNSZWR1Y2VkKHJlc3VsdCkgPyByZXN1bHRbJHZhbHVlXSA6IHJlc3VsdFxuICB9XG59XG5cbi8vIEFueSB0cmFuc2Zvcm0gb3ZlciBgbnVsbGAgaXMganVzdCBgbnVsbGAuXG5leHBvcnQgY2xhc3MgTnVsbFR5cGUgZXh0ZW5kcyBBdG9taWNUeXBlIHtcbiAgW2luaXQuc3ltYm9sXSgpIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG4gIFtzdGVwLnN5bWJvbF0ocmVzdWx0LCBpbnB1dCkge1xuICAgIHJldHVybiBudWxsXG4gIH1cbn1cblxuXG4vLyBBbnkgdHJhbnNmb3JtIG92ZXIgYHVuZGVmaW5lZGAgaXMganVzdCBgdW5kZWZpbmVkYFxuZXhwb3J0IGNsYXNzIFVuZGVmaW5lZFR5cGUgZXh0ZW5kcyBBdG9taWNUeXBlIHtcbiAgW2luaXQuc3ltYm9sXSgpIHtcbiAgICByZXR1cm4gdm9pZCgwKVxuICB9XG4gIFtzdGVwLnN5bWJvbF0ocmVzdWx0LCBpbnB1dCkge1xuICAgIHJldHVybiB2b2lkKDApXG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIE51bWJlclR5cGUgZXh0ZW5kcyBBdG9taWNUeXBlIHtcbiAgc3RhdGljIGFkZCh4LCB5KSB7XG4gICAgcmV0dXJuIHggKyB5XG4gIH1cbiAgLy8gQmFzZSBudW1iZXIgaXMgYDBgLlxuICBbaW5pdC5zeW1ib2xdKCkge1xuICAgIHJldHVybiAwXG4gIH1cbiAgW3N0ZXAuc3ltYm9sXShudW1iZXIsIGlucHV0KSB7XG4gICAgLy8gSWYgaW5wdXQgaXMgYW4gYXJyYXkgb2YgbnVtYmVycyBhZGQgZWFjaCBvbmUsIG90aGVyd2lzZVxuICAgIC8vIGp1c3QgYWRkIG51bWJlcnMuXG4gICAgcmV0dXJuIGlzQXJyYXkoaW5wdXQpID8gaW5wdXQucmVkdWNlKE51bWJlclR5cGUuYWRkLCBudW1iZXIpIDpcbiAgICBudW1iZXIgKyBpbnB1dFxuICB9XG59XG5cblxuZXhwb3J0IGNsYXNzIEJvb2xlYW5UeXBlIGV4dGVuZHMgQXRvbWljVHlwZSB7fVxuXG5leHBvcnQgY2xhc3MgU3ltYm9sVHlwZSBleHRlbmRzIEF0b21pY1R5cGUge31cblxuXG4vLyBHZW5lcmljIHR5cGUgdG8gc2hhcmUgYHJlZHVjZWAgaW1wbGVtZW50YXRpb24gYmV0d2VlblxuLy8gYXJyYXkgc3RyaW5nIG9yIGFueXRoaW5nIHRoYXQgaGF2ZSBgbGVuZ3RoYCBhbmQgYWNjZXNzIGJ5XG4vLyBpbmRleC5cbmV4cG9ydCBjbGFzcyBJbmRleGVkVHlwZSBleHRlbmRzIERlZmF1bHRUeXBlIHtcbiAgW3JlZHVjZS5zeW1ib2xdKHJlZHVjZXIsIGluaXRpYWwsIGluZGV4ZWQpIHtcbiAgICBsZXQgaW5kZXggPSAwXG4gICAgbGV0IHN0YXRlID0gaW5pdGlhbFxuICAgIGNvbnN0IGNvdW50ID0gaW5kZXhlZC5sZW5ndGhcbiAgICB3aGlsZSAoaW5kZXggPCBjb3VudCkge1xuICAgICAgc3RhdGUgPSByZWR1Y2VyWyRzdGVwXShzdGF0ZSwgaW5kZXhlZFtpbmRleF0pXG4gICAgICBpZiAoaXNSZWR1Y2VkKHN0YXRlKSkge1xuICAgICAgICByZXR1cm4gc3RhdGVbJHZhbHVlXVxuICAgICAgfVxuICAgICAgaW5kZXggPSBpbmRleCArIDFcbiAgICB9XG4gICAgcmV0dXJuIHN0YXRlXG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFN0cmluZ1R5cGUgZXh0ZW5kcyBJbmRleGVkVHlwZSB7XG4gIC8vIEJhc2Ugc3RyaW5nIGlzIGVtcHR5IHN0cmluZy5cbiAgW2luaXQuc3ltYm9sXSgpIHtcbiAgICByZXR1cm4gXCJcIlxuICB9XG4gIC8vIElmIGlucHV0IGlzIGFuIGFycmF5IGNvbmNhdCB0aGVtIG9udG8gcmVzdWx0IG90aGVyd2lzZSBqdXN0XG4gIC8vIGNvbmNhdCB0byBzdHJpbmdzLlxuICBbc3RlcC5zeW1ib2xdKHJlc3VsdCwgaW5wdXQpIHtcbiAgICByZXR1cm4gaXNBcnJheShpbnB1dCkgPyByZXN1bHQuY29uY2F0KC4uLmlucHV0KSA6IHJlc3VsdCArIGlucHV0XG4gIH1cbn1cblxuXG5leHBvcnQgY2xhc3MgQXJyYXlUeXBlIGV4dGVuZHMgSW5kZXhlZFR5cGUge1xuICBbaW5pdC5zeW1ib2xdKCkge1xuICAgIHJldHVybiBbXVxuICB9XG4gIFtzdGVwLnN5bWJvbF0oYXJyYXksIHZhbHVlKSB7XG4gICAgYXJyYXkucHVzaCh2YWx1ZSlcbiAgICByZXR1cm4gYXJyYXlcbiAgfVxufVxuXG5cbi8vIEl0ZXJhY3RvcnMgYXJlIGtpbmQgb2Ygc3BlY2lhbCBpbiBhIHNlbmNlIHRoYXQgdGhleSBwcm9kdWNlXG5leHBvcnQgY2xhc3MgSXRlcmF0b3JUeXBlIGV4dGVuZHMgT2JqZWN0VHlwZSB7XG4gIFtpbml0LnN5bWJvbF0oKSB7XG4gICAgcmV0dXJuIEl0ZXJhdG9yTGF6eVRyYW5zZm9ybVxuICB9XG4gIFtzdGVwLnN5bWJvbF0ocmVzdWx0LCBpbnB1dCkge1xuICAgIHJldHVybiByZXN1bHRbc3RlcC5zeW1ib2xdKHJlc3VsdCwgaW5wdXQpXG4gIH1cbiAgW3JlZHVjZS5zeW1ib2xdKHRyYW5zZHVjZXIsIGluaXRpYWwsIHNvdXJjZSkge1xuICAgIGNvbnN0IGl0ZXJhdG9yID0gc291cmNlWyRpdGVyYXRvcl0oKVxuICAgIC8vIElmIGl0IGlzIHRyYW5zZm9ybWF0aW9uIGZyb20gaXRlcmF0b3IgdG8gaXRlcmF0b3IsIHRoZW4gaW5pdGlhbCB2YWx1ZSBpc1xuICAgIC8vIGdvaW5nIHRvIGJlIGBJdGVyYXRvckxhenlUcmFuc2Zvcm1gIGFzIChyZXR1cm5lZCBieSBbaW5pdC5zeW1ib2xdIG1ldGhvZCBhYm92ZSlcbiAgICAvLyBJbiBzdWNoIGNhc2Ugd2UganVzdCBjcmVhdGUgYW4gaW5zdGFuY2Ugb2YgYEl0ZXJhdG9yTGF6eVRyYW5zZm9ybWAgYW5kIHJldHVybiBpdFxuICAgIC8vIGJhY2tlIGFjdHVhbCB0cmFuc2Zvcm1hdGlvbiB3aWxsIGhhcHBlbiBvbiBkZW1hbmQgYnkgYEl0ZXJhdG9yTGF6eVRyYW5zZm9ybWAuXG4gICAgaWYgKGluaXRpYWwgPT09IEl0ZXJhdG9yTGF6eVRyYW5zZm9ybSkge1xuICAgICAgcmV0dXJuIG5ldyBJdGVyYXRvckxhenlUcmFuc2Zvcm0oaXRlcmF0b3IsIHRyYW5zZHVjZXIpXG4gICAgfVxuXG4gICAgLy8gT3RoZXJ3aXNlIGVhY2ggdmFsdWUgd2lsbCBiZSBmb3J3cmFkZWQgdG8gdGhlIHRyYW5zZHVjZXIgdW50aWwgZG9uZVxuICAgIC8vIGl0ZXJhdGlvbiBvciB1bnRpbCByZWR1Y2VkIHJlc3VsdCBpcyByZXR1cm5lZC5cbiAgICBsZXQgcmVzdWx0ID0gaW5pdGlhbFxuICAgIHdoaWxlKHRydWUpIHtcbiAgICAgIGNvbnN0IHtkb25lLCB2YWx1ZX0gPSBpdGVyYXRvci5uZXh0KClcbiAgICAgIGlmIChkb25lKSB7XG4gICAgICAgIHJldHVybiByZXN1bHRcbiAgICAgIH1cblxuICAgICAgcmVzdWx0ID0gdHJhbnNkdWNlclskc3RlcF0ocmVzdWx0LCB2YWx1ZSlcblxuICAgICAgaWYgKGlzUmVkdWNlZChyZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiByZXN1bHRbJHZhbHVlXVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgSXRlcmF0b3JMYXp5VHJhbnNmb3JtIGV4dGVuZHMgSXRlcmF0b3JUeXBlIHtcbiAgY29uc3RydWN0b3Ioc291cmNlLCB0cmFuc2R1Y2VyKSB7XG4gICAgLy8gRWFjaCB0cmFuc2Zvcm1hdGlvbiBzdGVwIGB0aGlzLnRyYW5zZHVjZXIuc3RlcGAgbWF5IHByb2R1Y2UgMCwgMSBvciBtb3JlXG4gICAgLy8gc3RlcHMgaW4gcmV0dXJuLiBJbiBvcmRlciB0byBhY2NvbW9kYXRlIGV4dHJhIHZhbHVlcyBpbnRlcm5hbCBidWZmZXIgaXNcbiAgICAvLyBnb2luZyB0byBiZSB1c2VkLlxuICAgIHRoaXNbJGJ1ZmZlcl0gPSBbXVxuXG4gICAgdGhpcy5zb3VyY2UgPSBzb3VyY2VcbiAgICB0aGlzLnRyYW5zZHVjZXIgPSB0cmFuc2R1Y2VyXG4gICAgdGhpcy5pc0RyYWluZWQgPSBmYWxzZVxuICAgIHRoaXMuZG9uZSA9IGZhbHNlXG4gIH1cbiAgW3N0ZXAuc3ltYm9sXSh0YXJnZXQsIHZhbHVlKSB7XG4gICAgdGFyZ2V0WyRidWZmZXJdLnB1c2godmFsdWUpXG4gICAgcmV0dXJuIHRhcmdldFxuICB9XG4gIFskaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzXG4gIH1cbiAgbmV4dCgpIHtcbiAgICAvLyBQdWxsIGZyb20gdGhlIHNvdXJjZSB1bnRpbCBzb21ldGhpbmcgaXMgcHVzaGVkIGludG8gYSBidWZmZXIgb3JcbiAgICAvLyBvciB1bnRpbCBzb3VyY2UgaXMgZHJhaW5lZC4gYHRoaXMudHJhbnNkdWNlcmAgbWF5YmUgZmlsdGVyaW5nIHNvXG4gICAgLy8gc3RlcCBtYXkgbm90IHB1c2ggYW55dGhpbmcgdG8gYSBidWZmZXIsIG9yIGl0IGNvdWxkIGJlIG1hcGNhdHRpbmdcbiAgICAvLyBpbiB3aGljaCBjYXNlIHNldmVyYWwgdmFsdWVzIHdpbGwgYmUgcHVzaGVkLiBJdCBhbHNvIG1heWJlIHRoYXRcbiAgICAvLyB0cmFuc2R1Y2VyIGlzIGFjY3VtdWxhdGluZyBvbmQgb24gcmVzdWx0IG1vcmUgdmFsdWVzIHdpbGwgYmUgcHVzaGVkXG4gICAgLy8gKGxpa2UgcGFydGl0aW9uKS5cbiAgICB3aGlsZSAodGhpc1skYnVmZmVyXS5sZW5ndGggPT09IDAgJiYgIXRoaXMuaXNEcmFpbmVkKSB7XG4gICAgICBjb25zdCB7ZG9uZSwgdmFsdWV9ID0gdGhpcy5zb3VyY2UubmV4dCgpXG4gICAgICAvLyBJZiBzb3VyY2UgaXRlcmF0b3IgaXMgZHJhaW5lZCBpbnZva2UgcmVzdWx0IG9uIHRyYW5zZHVjZXIgdG8gbGV0XG4gICAgICAvLyBpdCBjbGVhbnVwIG9yIHB1c2ggd2hhdGV2ZXIgaXQgYWdncmVnYXRlZC5cbiAgICAgIGlmIChkb25lKSB7XG4gICAgICAgIHRoaXMudHJhbnNkdWNlclskcmVzdWx0XSh0aGlzKVxuICAgICAgICB0aGlzLmlzRHJhaW5lZCA9IGRvbmVcbiAgICAgIH1cbiAgICAgIC8vIE90aGVyd2lzZSBrZWVwIGNhbGxpbmcgc3RlcCwgaWYgcmVzdWx0IGlzIHJlZHVjZWQgdGhlbiBtYXJrIHRoaXNcbiAgICAgIC8vIGl0ZXJhdG9yIGRyYWluZWQgdG8gc3RvcCBwdWxsaW5nLlxuICAgICAgZWxzZSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMudHJhbnNkdWNlclskc3RlcF0odGhpcywgdmFsdWUpXG4gICAgICAgIHRoaXMuaXNEcmFpbmVkID0gaXNSZWR1Y2VkKHJlc3VsdClcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBdCB0aGlzIHBvaW4gd2UgZWl0aGVyIGdldCBzb21ldGhpbmcgaW4gYSBidWZmZXIgb3Igc291cmNlIHdhcyBleGhhdXN0ZWRcbiAgICAvLyBvciBib3RoLiBJZiBzb21ldGhpbmcgaXMgaW4gYSBidWZmZXIganVzdCByZXR1cm4gZnJvbSBpdC4gSWYgYnVmZmVyIGlzXG4gICAgLy8gZW1wdHkgdGhlbiBzb3VyY2UgaXMgZHJhaW5lZCBhcyB3ZWxsIHNvIHdlIG1hcmsgdGhpcyBkb25lIGFuZCBmaW5pc2guXG4gICAgaWYgKHRoaXNbJGJ1ZmZlcl0ubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy52YWx1ZSA9IHRoaXNbJGJ1ZmZlcl0uc2hpZnQoKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnZhbHVlID0gdW5kZWZpbmVkXG4gICAgICB0aGlzLmRvbmUgPSB0aGlzLmlzRHJhaW5lZFxuICAgIH1cblxuICAgIHJldHVybiB0aGlzXG4gIH1cbn1cbmNvbnN0ICRidWZmZXIgPSBzeW1ib2woXCJJdGVyYXRvckxhenlUcmFuc2Zvcm0vYnVmZmVyXCIpXG5JdGVyYXRvckxhenlUcmFuc2Zvcm0uYnVmZmVyID0gJGJ1ZmZlclxuIl19 -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "transducers", 3 | "version": "0.0.3", 4 | "description": "Clojure inspired transducers implementation in JS", 5 | "author": "Irakli Gozalishvili (http://jeditoolkit.com)", 6 | "homepage": "https://github.com/gozala/transducers", 7 | "keywords": [ 8 | "transducers", 9 | "underscore", 10 | "lodash", 11 | "functional", 12 | "transformation", 13 | "util", 14 | "reducer" 15 | ], 16 | "repository": { 17 | "type": "git", 18 | "url": "git://github.com/gozala/transducers.git", 19 | "web": "https://github.com/Gozala/transducers" 20 | }, 21 | "bugs": { 22 | "url": "https://github.com/gozala/transducers/issues" 23 | }, 24 | "license": "MIT", 25 | "main": "./lib/transducers.js", 26 | "directories": { 27 | "test": "test" 28 | }, 29 | "scripts": { 30 | "test": "tap lib/test/*.js", 31 | "start": "babel --watch --modules umdStrict --source-maps-inline --out-dir ./lib ./src", 32 | "prepublish": "babel --modules umdStrict --source-maps-inline --out-dir ./lib ./src" 33 | }, 34 | "testling": { 35 | "files": "lib/test/*.js", 36 | "browsers": [ 37 | "ie/9..latest", 38 | "chrome/25..latest", 39 | "firefox/20..latest", 40 | "safari/5.1..latest", 41 | "opera/11.0..latest", 42 | "iphone/6..latest", 43 | "ipad/6..latest", 44 | "android-browser/4.2..latest" 45 | ] 46 | }, 47 | "devDependencies": { 48 | "babel": "^4.7.4", 49 | "immutable": "^3.6.4", 50 | "tap": "~0.4.8", 51 | "tape": "~2.3.2" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/test/index.js: -------------------------------------------------------------------------------- 1 | import test from "./test" 2 | import * as Immutable from "immutable" 3 | import {reduce, transduce, map, filter, remove, cat, 4 | mapcat, partition, take, takeWhile, 5 | drop, dropWhile, dropRepeats, 6 | 7 | init, step, result} from "../../" 8 | 9 | // utility 10 | const inc = x => x + 1 11 | const upperCase = char => char.toUpperCase() 12 | const lowerCase = char => char.toLowerCase() 13 | const add = x => y => x + y 14 | const multiply = x => y => x * y 15 | const stringify = json => JSON.stringify(json) 16 | const isEven = x => !(x % 2) 17 | const isLowerCase = char => char.toLowerCase() === char 18 | const lessThan = x => y => y < x 19 | const constant = x => _ => x 20 | const identity = x => x 21 | 22 | const True = constant(true) 23 | const False = constant(false) 24 | 25 | if (!Array.from) { 26 | Array.from = iterator => { 27 | const array = [] 28 | while (true) { 29 | const {value, done} = iterator.next() 30 | if (done) { 31 | return array 32 | } else { 33 | array.push(value) 34 | } 35 | } 36 | } 37 | } 38 | 39 | test("map", assert => { 40 | const incer = map(inc) 41 | 42 | assert.deepEqual(incer([1, 2, 3, 4]), 43 | [2, 3, 4, 5], 44 | "array elements get mapped") 45 | 46 | assert.deepEqual(incer(0), 1, 47 | "function is applied to number") 48 | 49 | assert.deepEqual(incer(null), null, 50 | "map over null is no op") 51 | 52 | assert.deepEqual(incer(void(0)), void(0), 53 | "map over void is void") 54 | 55 | assert.equal(map(upperCase)("Hello"), 56 | "HELLO", 57 | "strings can be mapped over") 58 | 59 | const iterator = Immutable.Iterable({x: 1, y: 2}) 60 | 61 | assert.deepEqual([...incer(iterator.values())], 62 | [2, 3], 63 | "iterable makes lazy transformation") 64 | 65 | assert.deepEqual([...map(upperCase)(iterator.keys())], 66 | ["X", "Y"], 67 | "iterable makes lazy transformation") 68 | 69 | assert.deepEqual(map(identity)([[1, 2], [3, 4]]), 70 | [[1, 2], [3, 4]], 71 | "map does not expands") 72 | }) 73 | 74 | test("filter", assert => { 75 | const evens = filter(isEven) 76 | 77 | assert.deepEqual(evens([1, 2, 3, 4]), [2, 4], 78 | "array elements got filtered") 79 | 80 | assert.deepEqual(evens([1, 3, 5, 7]), [], 81 | "filtered out all elements") 82 | 83 | assert.deepEqual(evens(7), 0, 84 | "filtered out odd number to empty number") 85 | 86 | assert.deepEqual(evens(6), 6, 87 | "number was kept as it was even") 88 | 89 | assert.deepEqual(filter(True)(null), null, 90 | "null remains null regardless of operation") 91 | 92 | assert.deepEqual(filter(False)(void(0)), void(0), 93 | "void remains void regardless of operation") 94 | 95 | assert.deepEqual(filter(isLowerCase)("Hello World"), "ello orld", 96 | "filters out upper case letters") 97 | 98 | const iterator = Immutable.Iterable({x: 1, Y: 2, z: 3}) 99 | 100 | assert.deepEqual([...evens(iterator.values())], 101 | [2], 102 | "filter value iterators") 103 | 104 | assert.deepEqual([...filter(isLowerCase)(iterator.keys())], 105 | ["x", "z"], 106 | "filter key iterators") 107 | }) 108 | 109 | 110 | 111 | test("remove", assert => { 112 | const odds = remove(isEven) 113 | const upperCaseChars = remove(isLowerCase) 114 | 115 | assert.deepEqual(odds([1, 2, 3, 4]), 116 | [1, 3], 117 | "evens were removed") 118 | 119 | assert.deepEqual(remove(True)(null), 120 | null, 121 | "transducing null return null") 122 | 123 | assert.deepEqual(remove(False)(null), 124 | null, 125 | "transducing null return null") 126 | 127 | assert.deepEqual(remove(True)(void(0)), 128 | void(0), 129 | "transducing void return void") 130 | 131 | assert.deepEqual(remove(False)(void(0)), 132 | void(0), 133 | "transducing void return void") 134 | 135 | assert.deepEqual(remove(x => x > 0)(7), 136 | 0, 137 | "removing matching number returns 0") 138 | 139 | assert.deepEqual(remove(x => x < 0)(7), 140 | 7, 141 | "removing unmatched number returns number") 142 | 143 | assert.deepEqual(upperCaseChars("Hello World"), 144 | "HW", 145 | "removes lower case chars") 146 | 147 | assert.deepEqual(upperCaseChars("what?"), 148 | "", 149 | "removes all chars") 150 | 151 | const iterator = Immutable.Iterable({x: 1, Y: 2, z: 3}) 152 | 153 | assert.deepEqual([...odds(iterator.values())], 154 | [1, 3], 155 | "removes from iterator") 156 | }) 157 | 158 | test("drop", assert => { 159 | assert.deepEqual(drop(2)([1, 2, 3, 4, 5]), 160 | [3, 4, 5], 161 | "dropped two items") 162 | 163 | assert.deepEqual(drop(9)([1, 2, 3, 4]), 164 | [], 165 | "dropes all items") 166 | 167 | assert.deepEqual(drop(7)([]), 168 | [], 169 | "nothing to drop") 170 | 171 | assert.deepEqual(drop(0)([1, 2, 3, 4]), 172 | [1, 2, 3, 4], 173 | "no need to drop") 174 | 175 | assert.deepEqual(drop(-7)([1, 2, 3]), 176 | [1, 2, 3], 177 | "no need to drop") 178 | 179 | assert.deepEqual(drop(0)(1), 180 | 1, 181 | "number was not dropped") 182 | assert.deepEqual(drop(5)(8), 183 | 0, 184 | "number was reset to 0") 185 | 186 | assert.deepEqual(drop(3)("hello"), 187 | "lo", 188 | "three characters were dropped") 189 | 190 | assert.deepEqual(drop(9)("hello"), 191 | "", 192 | "dropped all chars") 193 | 194 | assert.deepEqual(drop(8)(""), 195 | "", 196 | "nothing to drop") 197 | 198 | assert.deepEqual(drop(9)(null), 199 | null) 200 | 201 | assert.deepEqual(drop(0)(null), 202 | null) 203 | 204 | assert.deepEqual(drop(8)(void(0)), 205 | void(0)) 206 | 207 | assert.deepEqual(drop(0)(void(0)), 208 | void(0)) 209 | 210 | 211 | const iterator = Immutable.Iterable({x: 1, y: 2}) 212 | 213 | assert.deepEqual([...drop(0)(iterator.values())], 214 | [1, 2], 215 | "0 drops") 216 | 217 | assert.deepEqual([...drop(1)(iterator.values())], 218 | [2], 219 | "dropped first") 220 | 221 | assert.deepEqual([...drop(8)(iterator.values())], 222 | [], 223 | "dropped all") 224 | }) 225 | 226 | test("dropWhile", assert => { 227 | assert.deepEqual(dropWhile(lessThan(9))([1, 8, 12, 9, 45]), 228 | [12, 9, 45]) 229 | 230 | assert.deepEqual(dropWhile(lessThan(9))([10, 9, 8, 7]), 231 | [10, 9, 8, 7]) 232 | 233 | assert.deepEqual(dropWhile(lessThan(9))([1, 2, 3]), 234 | []) 235 | 236 | assert.deepEqual(dropWhile(lessThan(9))([]), 237 | []) 238 | 239 | assert.deepEqual(dropWhile(False)(5), 5) 240 | assert.deepEqual(dropWhile(True)(5), 0) 241 | 242 | 243 | assert.deepEqual(dropWhile(True)(null), null) 244 | assert.deepEqual(dropWhile(False)(null), null) 245 | 246 | 247 | assert.deepEqual(dropWhile(True)(void(0)), void(0)) 248 | assert.deepEqual(takeWhile(False)(void(0)), void(0)) 249 | 250 | assert.deepEqual(dropWhile(isLowerCase)("never mind You"), 251 | "You") 252 | assert.deepEqual(dropWhile(isLowerCase)("Hi there"), 253 | "Hi there") 254 | assert.deepEqual(dropWhile(True)(""), "") 255 | assert.deepEqual(dropWhile(False)(""), "") 256 | 257 | const iterator = Immutable.Iterable({x: 0, y: 5, z: 10}) 258 | 259 | assert.deepEqual([...dropWhile(lessThan(7))(iterator.values())], 260 | [10]) 261 | 262 | assert.deepEqual([...dropWhile(lessThan(0))(iterator.values())], 263 | [0, 5, 10]) 264 | 265 | assert.deepEqual([...dropWhile(lessThan(99))(iterator.values())], 266 | []) 267 | }) 268 | 269 | test("dropRepeats", assert => { 270 | assert.deepEqual(dropRepeats([1, 2, 3, 3, 4, 3]), 271 | [1, 2, 3, 4, 3], 272 | "removed repeated elements") 273 | 274 | assert.deepEqual(dropRepeats([1, 1, 1, 1, 1]), 275 | [1], 276 | "keeps just one") 277 | 278 | assert.deepEqual(dropRepeats(1), 279 | 1, 280 | "number has no repeats") 281 | 282 | assert.deepEqual(dropRepeats(null), 283 | null, 284 | "null transfromed is null") 285 | 286 | assert.deepEqual(dropRepeats(void(0)), 287 | void(0), 288 | "void transfromed is void") 289 | 290 | assert.deepEqual(dropRepeats("what"), 291 | "what", 292 | "nothing to drop") 293 | 294 | assert.deepEqual(dropRepeats("hello"), 295 | "helo", 296 | "dropes repeated chars") 297 | 298 | const iterator = Immutable.Iterable({x: 1, Y: 2, z: 2}) 299 | 300 | assert.deepEqual([...dropRepeats(iterator.values())], 301 | [1, 2], 302 | "removes repeats form iterator") 303 | }) 304 | 305 | test("take", assert => { 306 | assert.deepEqual(take(2)([1, 2, 3, 4, 5]), 307 | [1, 2], 308 | "took two") 309 | 310 | assert.deepEqual(take(9)([1, 2, 3, 4]), 311 | [1, 2, 3, 4], 312 | "took all") 313 | 314 | assert.deepEqual(take(7)([]), 315 | [], 316 | "nothing to take") 317 | 318 | assert.deepEqual(take(0)([1, 2, 3, 4]), 319 | [], 320 | "took 0") 321 | 322 | assert.deepEqual(take(-7)([1, 2, 3]), 323 | [], 324 | "took none") 325 | 326 | assert.deepEqual(take(0)(1), 0) 327 | assert.deepEqual(take(5)(8), 8) 328 | 329 | assert.deepEqual(take(3)("hello"), "hel") 330 | 331 | assert.deepEqual(take(9)("hello"), "hello") 332 | 333 | assert.deepEqual(take(8)(""), "") 334 | 335 | assert.deepEqual(take(9)(null), null) 336 | 337 | assert.deepEqual(take(0)(null), null) 338 | 339 | assert.deepEqual(take(8)(void(0)), void(0)) 340 | 341 | assert.deepEqual(drop(0)(void(0)), void(0)) 342 | 343 | 344 | const iterator = Immutable.Iterable({x: 1, y: 2}) 345 | 346 | assert.deepEqual([...take(9)(iterator.values())], 347 | [1, 2]) 348 | 349 | assert.deepEqual([...take(1)(iterator.values())], 350 | [1], 351 | "took first") 352 | 353 | assert.deepEqual([...take(0)(iterator.values())], 354 | [], 355 | "took none") 356 | }) 357 | 358 | test("takeWhile", assert => { 359 | const digits = takeWhile(lessThan(10)) 360 | 361 | assert.deepEqual(digits([1, 8, 12, 9, 45]), 362 | [1, 8], 363 | "takes only digits") 364 | 365 | assert.deepEqual(digits([10, 9, 8, 7]), 366 | [], 367 | "takes none") 368 | 369 | assert.deepEqual(digits(5), 370 | 5, 371 | "take matching number") 372 | 373 | assert.deepEqual(digits(97), 374 | 0, 375 | "returns 0 on unmatched number") 376 | 377 | assert.deepEqual(takeWhile(True)(null), 378 | null, 379 | "return null") 380 | 381 | assert.deepEqual(takeWhile(False)(null), 382 | null, 383 | "returns null") 384 | 385 | 386 | assert.deepEqual(takeWhile(True)(void(0)), 387 | void(0), 388 | "return void") 389 | 390 | assert.deepEqual(takeWhile(False)(void(0)), 391 | void(0), 392 | "return void") 393 | 394 | assert.deepEqual(takeWhile(isLowerCase)("never mind You"), 395 | "never mind ", 396 | "takes until upper case") 397 | 398 | assert.deepEqual(takeWhile(isLowerCase)("Hi there"), 399 | "", 400 | "blank string") 401 | 402 | const iterator = Immutable.Iterable({x: 0, y: 5, z: 10}) 403 | 404 | assert.deepEqual([...takeWhile(lessThan(7))(iterator.values())], 405 | [0, 5], 406 | "removes repeats form iterator") 407 | }) 408 | 409 | test("partition", assert => { 410 | assert.deepEqual(partition(2)([1, 2, 3, 4, 5, 6, 7, 8]), 411 | [[1, 2], [3, 4], [5, 6], [7, 8]]) 412 | 413 | assert.deepEqual(partition(3)([1, 2, 3, 4, 5, 6, 7, 8]), 414 | [[1, 2, 3], [4, 5, 6], [7, 8]]) 415 | 416 | assert.deepEqual(partition(4)([1, 2]),[[1, 2]]) 417 | 418 | assert.deepEqual(partition(3)([]), []) 419 | 420 | assert.deepEqual(partition(3)(9), 9) 421 | assert.deepEqual(partition(2)("hello"), "hello") 422 | 423 | assert.deepEqual(partition(2)(null), null) 424 | assert.deepEqual(partition(2)(void(0)), void(0)) 425 | 426 | const iterator = Immutable.Iterable({x: 0, y: 5, z: 10}) 427 | 428 | assert.deepEqual([...partition(2)(iterator.values())], 429 | [[0, 5], [10]]) 430 | }) 431 | 432 | // TODO:! 433 | test("partitionBy", assert => { 434 | }) 435 | 436 | test("cat", assert => { 437 | assert.deepEqual(cat([[1, 2], [3], [4, 5]]), 438 | [1, 2, 3, 4, 5]) 439 | 440 | assert.deepEqual(cat([]), []) 441 | assert.deepEqual(cat([1, 2, 3]), [1, 2, 3]) 442 | assert.deepEqual(cat(null), null) 443 | assert.deepEqual(cat(void(0)), void(0)) 444 | assert.deepEqual(cat(4), 4) 445 | assert.deepEqual(cat("hello"), "hello") 446 | 447 | const valueIter = Immutable.Iterable([0, 5, 10]).values() 448 | 449 | assert.deepEqual([...cat(valueIter)], 450 | [0, 5, 10]) 451 | 452 | const arrayIter = Immutable.Iterable([[1, 2], [3], [4, 5, 6]]).values() 453 | assert.deepEqual([...cat(arrayIter)], 454 | [1, 2, 3, 4, 5, 6]) 455 | }) 456 | 457 | test("mapcat", assert => { 458 | assert.deepEqual((map(x => x.split("/"))) 459 | (cat) 460 | (["path/to", "dir/file"]), 461 | ["path", "to", "dir", "file"]) 462 | }) 463 | 464 | test("composition", assert => { 465 | const incer = map(inc) 466 | const add2 = incer(incer) 467 | 468 | assert.equal(typeof(add2), "function", 469 | "passing transducer to transducer composes a new one") 470 | 471 | assert.deepEqual(add2([1, 2, 3, 4]), 472 | [3, 4, 5, 6], 473 | "array elements get mapped") 474 | 475 | assert.deepEqual(add2(0), 2, 476 | "function is applied to number") 477 | 478 | assert.deepEqual(add2(null), null, 479 | "map over null is no op") 480 | 481 | assert.deepEqual(add2(void(0)), void(0), 482 | "map over void is void") 483 | 484 | assert.deepEqual((filter(isEven)) 485 | (map(inc)) 486 | ([1, 4, 9, 10]), 487 | [5, 11]) 488 | }) 489 | 490 | 491 | test("trasduce", assert => { 492 | const evens = filter(isEven) 493 | assert.equal(transduce(evens, 494 | (x, y) => y === void(0) ? x : x + y, 495 | 2, 496 | [1, 2, 3, 4]), 497 | 8, 498 | "transduced array with custom reducer") 499 | 500 | assert.equal(transduce(evens, 501 | (x, y) => x === void(0) ? 0 : 502 | y === void(0) ? x : 503 | x + y, 504 | [1, 2, 3, 4]), 505 | 6, 506 | "transduced without initial value") 507 | 508 | 509 | const iterator = Immutable.Iterable({x: 1, Y: 2, z: 3, w: 4}) 510 | assert.equal(transduce(evens, 511 | (x, y) => y === void(0) ? x : x + y, 512 | 5, 513 | iterator.values()), 514 | 11, 515 | "transduce iterator with custom reducer") 516 | }) 517 | 518 | 519 | test("immutable list", assert => { 520 | const incer = map(inc) 521 | const list = Immutable.List.of(1, 2, 3, 4) 522 | const t1 = incer(list) 523 | 524 | assert.notOk(t1 instanceof Immutable.List, 525 | "result is not a list") 526 | 527 | assert.deepEqual([...t1], 528 | [2, 3, 4, 5], 529 | "result is an iterator") 530 | 531 | Immutable.List.prototype[init.symbol] = () => 532 | Immutable.List().asMutable() 533 | 534 | Immutable.List.prototype[result.symbol] = (list) => 535 | list.asImmutable() 536 | 537 | Immutable.List.prototype[step.symbol] = (list, item) => 538 | list.push(item) 539 | 540 | 541 | const t2 = incer(list) 542 | 543 | 544 | assert.ok(t2 instanceof Immutable.List, 545 | "result is a list") 546 | 547 | 548 | assert.ok(t2.equals(Immutable.List.of(2, 3, 4, 5)), 549 | "transformed list was returned") 550 | 551 | const t3 = (filter(isEven)) 552 | (incer) 553 | (incer) 554 | (incer) 555 | (list) 556 | 557 | assert.ok(t3.equals(Immutable.List.of(5, 7)), 558 | "composed transform works fine") 559 | 560 | }) 561 | 562 | 563 | 564 | 565 | test("immutable map", assert => { 566 | const f = map(([key, value]) => [key.toUpperCase(), 567 | value * value]) 568 | 569 | const m1 = Immutable.Map({x: 1, y: 2}) 570 | 571 | const t1 = f(m1) 572 | 573 | assert.notOk(t1 instanceof Immutable.Map, 574 | "result is not a map") 575 | 576 | assert.deepEqual([...t1], 577 | [["X", 1], ["Y", 4]], 578 | "result is transformed iterator") 579 | 580 | Immutable.Map.prototype[init.symbol] = () => 581 | Immutable.Map().asMutable() 582 | 583 | Immutable.Map.prototype[result.symbol] = (map) => 584 | map.asImmutable() 585 | 586 | Immutable.Map.prototype[step.symbol] = (map, [key, value]) => 587 | map.set(key, value) 588 | 589 | 590 | const t2 = f(m1) 591 | 592 | 593 | assert.ok(t2 instanceof Immutable.Map, 594 | "result is instanceof Map") 595 | 596 | 597 | assert.ok(t2.equals(Immutable.Map({X: 1, Y: 4})), 598 | "map was transformed") 599 | }) 600 | 601 | 602 | -------------------------------------------------------------------------------- /src/test/test.js: -------------------------------------------------------------------------------- 1 | import * as tape from "tape" 2 | 3 | export default (description, unit) => tape.test(description, test => { 4 | const result = unit(test) 5 | if (result && result.then) { 6 | result.then(_ => test.end(), error => test.end(error || true)) 7 | } else { 8 | test.end() 9 | } 10 | }) 11 | -------------------------------------------------------------------------------- /src/transducers.js: -------------------------------------------------------------------------------- 1 | const isSymbolDefined = typeof(Symbol) !== 'undefined'; 2 | const symbol = (isSymbolDefined && Symbol.for) || hint => `@@${hint}` 3 | 4 | const $iterator = isSymbolDefined && Symbol.iterator || symbol('iterator') 5 | 6 | 7 | 8 | export const methodOf = (target, id) => { 9 | let method = target && target[id] 10 | if (!method) { 11 | const type = typeof(target) 12 | method = target === null ? NullType.prototype[id] : 13 | target === void(0) ? UndefinedType.prototype[id] : 14 | type === 'string' ? StringType.prototype[id] : 15 | type === 'number' ? NumberType.prototype[id] : 16 | type === 'boolean' ? BooleanType.prototype[id] : 17 | type === 'symbol' ? SymbolType.prototype[id] : 18 | isArray(target) ? ArrayType.prototype[id] : 19 | isIterator(target) ? IteratorType.prototype[id] : 20 | isRegExp(target) ? RegExpType.prototype[id] : 21 | type === 'function' ? FunctionType.prototype[id] : 22 | type === 'object' ? ObjectType.prototype[id] : 23 | DefaultType.prototype[id] 24 | } 25 | return method 26 | } 27 | 28 | const dispatcher = (name, index=0) => { 29 | const id = symbol(name) 30 | const dispatch = (a, b, c, d, e) => { 31 | const target = index === 0 ? a : 32 | index === 1 ? b : 33 | index === 2 ? c : 34 | index === 3 ? d : 35 | e; 36 | const method = methodOf(target, id) 37 | 38 | if (!method) { 39 | throw TypeError(`target does not implements ${id} method`) 40 | } 41 | 42 | return method.call(target, a, b, c, d, e) 43 | } 44 | dispatch.symbol = id 45 | return dispatch 46 | } 47 | 48 | export const init = dispatcher("transducer/init") 49 | const $init = init.symbol 50 | 51 | export const result = dispatcher("transducer/result") 52 | const $result = result.symbol 53 | 54 | export const step = dispatcher("transducer/step") 55 | const $step = step.symbol 56 | 57 | export const reduce = dispatcher("transducer/reduce", 2) 58 | const $reduce = reduce.symbol 59 | 60 | export const reduced = value => new Reduced(value) 61 | const $reduced = reduced.symbol = symbol("transducer/reduced") 62 | 63 | export const value = reduced => reduced[$value] 64 | const $value = value.symbol = symbol("transducer/value") 65 | 66 | export const transformer = transform => { 67 | transform[$transformer] = true 68 | return transformer 69 | } 70 | const $transformer = transformer.symbol = symbol("transducer/transformer") 71 | 72 | const prototype = Object.prototype 73 | 74 | // Returns `true` if given `x` is a JS array. 75 | export const isArray = Array.isArray || 76 | x => prototype.toString.call(x) === '[object Array]' 77 | 78 | // Returns `true` if given `x` is a regular expression. 79 | export const isRegExp = x => 80 | prototype.toString.call(x) === '[object RegExp]' 81 | 82 | // Returns `true` if given `x` is a JS iterator. 83 | export const isIterator = x => 84 | x && x[$iterator] 85 | 86 | // Returns true if `x` is boxed value & signifies that 87 | // reduction is complete. 88 | export const isReduced = x => 89 | x instanceof Reduced || (x && x[$reduced]) 90 | 91 | export const isReducible = x => 92 | x && methodOf(x, $reduce) 93 | 94 | export const isReducer = x => 95 | x instanceof Reducer || methodOf(x, $step) 96 | 97 | export const isTransformer = x => 98 | x && x[$transformer] 99 | 100 | // Class is used to box result of reduction step in order 101 | // to signal chained transducer that reduction has completed. 102 | export class Reduced { 103 | constructor(value) { 104 | this[$reduced] = true 105 | this[$value] = value 106 | 107 | // Compatibility with other libs: 108 | // https://github.com/cognitect-labs/transducers-js 109 | // https://github.com/jlongster/transducers.js 110 | this.__transducers_reduced__ = true 111 | this.value = value 112 | } 113 | } 114 | Reduced.symbol = $reduced 115 | 116 | 117 | export class Reducer { 118 | constructor({init, step, result}) { 119 | this[$init] = init || this[$init] 120 | this[$step] = step || this[$step] 121 | this[$result] = result || this[$result] 122 | } 123 | [$init]() { 124 | throw TypeError('Reducer must implement [Symbol.for("transducer/init")]') 125 | } 126 | [$step](result, input) { 127 | throw TypeError('Reducer must implement [Symbol.for("transducer/step")]') 128 | } 129 | [$result](result) { 130 | throw TypeError('Reducer must implement [Symbol.for("transducer/result")]') 131 | } 132 | } 133 | 134 | export class Producer extends Reducer { 135 | constructor(source) { 136 | this[$init] = methodOf(source, $init) 137 | this[$step] = methodOf(source, $step) 138 | this[$result] = methodOf(source, $result) 139 | } 140 | } 141 | 142 | export class Stepper extends Reducer { 143 | constructor(f) { 144 | this[$step] = f 145 | } 146 | [$init]() { 147 | return this[$step]() 148 | } 149 | [$result](result) { 150 | return result 151 | } 152 | } 153 | 154 | export class Transducer extends Reducer { 155 | constructor(reducer, ...params) { 156 | this.reducer = reducer 157 | this.setup(...params) 158 | } 159 | setup() { 160 | } 161 | [$init]() { 162 | return this.reducer[$init]() 163 | } 164 | [$step](result, input) { 165 | return this.advance(result, input) 166 | } 167 | advance(result, input) { 168 | return this.reducer[$step](result, input) 169 | } 170 | [$result](result) { 171 | return this.reducer[$result](result) 172 | } 173 | } 174 | 175 | export class Composite extends Transducer { 176 | constructor(source, transformer, TransducerType, ...params) { 177 | this.reducer = new TransducerType(transformer(source), ...params) 178 | } 179 | } 180 | 181 | // Creates a transformer function that is a thunk for `TransducerType` and it's parameters. 182 | // Once returned transformer is inovked it's going to do one of the following things: 183 | // - If argument is an instance of a `Reducer` it's going to create an instance of Transducer 184 | // with a given argument at the bottom of the chain. 185 | // - If argument is another transformer it's going to return composed transformer. 186 | // - If argument is a reducible data structure with defined reducer it's going to return 187 | // transducer application over it. 188 | export const Transform = (TransducerType, ...params) => { 189 | const transform = source => { 190 | if (source instanceof Reducer) { 191 | return new TransducerType(source, ...params) 192 | } else if (source && source[$transformer]) { 193 | return Transform(Composite, source, TransducerType, ...params) 194 | } else if (isReducer(source)) { 195 | const transducer = new TransducerType(new Producer(source), ...params) 196 | const initial = transducer[$init]() 197 | const result = reduce(transducer, initial, source) 198 | return transducer[$result](result) 199 | } else { 200 | throw TypeError("Unsupported argument type was passed to a transformer") 201 | } 202 | } 203 | // Should use `transformer` instead but for debugging it's kind 204 | // of handy to attach `TransducerType` and it `params` so we keep 205 | // this for now. 206 | transform[$transformer] = true 207 | transform.Transducer = TransducerType 208 | transform.params = params 209 | return transform 210 | } 211 | Transform.symbol = $transformer 212 | 213 | // Like `Transform` but allows passing parameters in the separate call. 214 | export const Transformer = TransducerType => (...params) => 215 | Transform(TransducerType, ...params) 216 | 217 | // Transducers. 218 | 219 | class Map extends Transducer { 220 | setup(f) { 221 | this.f = f 222 | } 223 | [$step](state, input) { 224 | return this.advance(state, this.f(input)) 225 | } 226 | } 227 | 228 | export const map = Transformer(Map) 229 | 230 | 231 | class Filter extends Transducer { 232 | setup(p) { 233 | this.p = p 234 | } 235 | [$step](state, input) { 236 | if (this.p(input)) { 237 | return this.advance(state, input) 238 | } 239 | return state 240 | } 241 | } 242 | 243 | export const filter = Transformer(Filter) 244 | export const remove = p => filter(x => !p(x)) 245 | 246 | class DropRepeats extends Transducer { 247 | [$step](state, input) { 248 | if (input !== this.last) { 249 | this.last = input 250 | return this.advance(state, input) 251 | } 252 | return state 253 | } 254 | } 255 | 256 | export const dropRepeats = Transform(DropRepeats) 257 | 258 | 259 | class TakeWhile extends Transducer { 260 | setup(p) { 261 | this.p = p 262 | } 263 | [$step](state, input) { 264 | if (this.p(input)) { 265 | return this.advance(state, input) 266 | } 267 | return new Reduced(state) 268 | } 269 | } 270 | 271 | export const takeWhile = Transformer(TakeWhile) 272 | 273 | class Take extends Transducer { 274 | setup(n) { 275 | this.n = n 276 | } 277 | [$step](state, input) { 278 | if (this.n > 0) { 279 | this.n = this.n - 1 280 | state = this.advance(state, input) 281 | if (this.n === 0 && !isReduced(state)) { 282 | state = new Reduced(state) 283 | } 284 | } 285 | return state 286 | } 287 | } 288 | 289 | export const take = Transformer(Take) 290 | 291 | class Drop extends Transducer { 292 | setup(n) { 293 | this.n = n 294 | } 295 | [$step](state, input) { 296 | this.n = this.n - 1; 297 | return this.n >= 0 ? state : this.advance(state, input) 298 | } 299 | } 300 | 301 | export const drop = Transformer(Drop) 302 | 303 | class DropWhile extends Transducer { 304 | setup(p) { 305 | this.p = p 306 | this.dropping = true 307 | } 308 | [$step](state, input) { 309 | this.dropping = this.dropping && this.p(input) 310 | return this.dropping ? state : this.advance(state, input) 311 | } 312 | } 313 | 314 | export const dropWhile = Transformer(DropWhile) 315 | 316 | class Partition extends Transducer { 317 | setup(n) { 318 | this.n = n 319 | this.i = 0 320 | this.part = new Array(n) 321 | } 322 | [$result](state) { 323 | if (this.i > 0) { 324 | state = this.advance(state, this.part.slice(0, this.i)) 325 | state = isReduced(state) ? state[$value] : state 326 | } 327 | return super[$result](state) 328 | } 329 | [$step](state, input) { 330 | this.part[this.i] = input 331 | this.i = this.i + 1 332 | if (this.i == this.n) { 333 | this.i = 0 334 | return this.advance(state, this.part.slice(0)) 335 | } 336 | return state 337 | } 338 | } 339 | 340 | export const partition = Transformer(Partition) 341 | 342 | class Forwarder extends Transducer { 343 | [$step](state, input) { 344 | const result = this.advance(state, input) 345 | return isReduced(result) ? result[$value] : result 346 | } 347 | } 348 | 349 | class Cat extends Transducer { 350 | setup() { 351 | this.forwarder = new Forwarder(this.reducer) 352 | } 353 | [$step](state, input) { 354 | return reduce(this.forwarder, state, input) 355 | } 356 | } 357 | 358 | export const cat = Transform(Cat) 359 | 360 | export const transduce = (transformer, reducer, initial, source) => { 361 | reducer = reducer instanceof Reducer ? reducer : 362 | isReducer(reducer) ? new Producer(reducer) : 363 | typeof(reducer) === "function" ? new Stepper(reducer) : 364 | null 365 | 366 | if (!reducer) { 367 | throw TypeError(`Invalid reducer was passed`) 368 | } 369 | 370 | const transducer = transformer(reducer) 371 | 372 | if (source === void(0) && initial !== void(0)) { 373 | [source, initial] = [initial, transducer[$init]()] 374 | } 375 | 376 | const result = reduce(transducer, initial, source) 377 | return transducer[$result](result) 378 | } 379 | 380 | // Interface implementations for built-in types so we don't have 381 | // to patch built-ins. 382 | 383 | // Defaltu type is the bottom type all types including null undefined 384 | // and object are going to inherit from it. 385 | export class DefaultType { 386 | [init.symbol]() { 387 | return new this.constructor() 388 | } 389 | [result.symbol](result) { 390 | return result 391 | } 392 | } 393 | 394 | 395 | // We don not make objects transducible. 396 | export class ObjectType extends DefaultType {} 397 | 398 | // We do not make functions transducible. 399 | export class FunctionType extends DefaultType {} 400 | 401 | 402 | // All primitives gonig to inherit from AtomitType which 403 | // provides `reduce` implementation that's gonig to invoke 404 | // reducer just once with a value of the data type itself. 405 | export class AtomicType extends DefaultType { 406 | [reduce.symbol](reducer, initial, value) { 407 | const result = reducer[$step](initial, value) 408 | return isReduced(result) ? result[$value] : result 409 | } 410 | } 411 | 412 | // Any transform over `null` is just `null`. 413 | export class NullType extends AtomicType { 414 | [init.symbol]() { 415 | return null 416 | } 417 | [step.symbol](result, input) { 418 | return null 419 | } 420 | } 421 | 422 | 423 | // Any transform over `undefined` is just `undefined` 424 | export class UndefinedType extends AtomicType { 425 | [init.symbol]() { 426 | return void(0) 427 | } 428 | [step.symbol](result, input) { 429 | return void(0) 430 | } 431 | } 432 | 433 | export class NumberType extends AtomicType { 434 | static add(x, y) { 435 | return x + y 436 | } 437 | // Base number is `0`. 438 | [init.symbol]() { 439 | return 0 440 | } 441 | [step.symbol](number, input) { 442 | // If input is an array of numbers add each one, otherwise 443 | // just add numbers. 444 | return isArray(input) ? input.reduce(NumberType.add, number) : 445 | number + input 446 | } 447 | } 448 | 449 | 450 | export class BooleanType extends AtomicType {} 451 | 452 | export class SymbolType extends AtomicType {} 453 | 454 | 455 | // Generic type to share `reduce` implementation between 456 | // array string or anything that have `length` and access by 457 | // index. 458 | export class IndexedType extends DefaultType { 459 | [reduce.symbol](reducer, initial, indexed) { 460 | let index = 0 461 | let state = initial 462 | const count = indexed.length 463 | while (index < count) { 464 | state = reducer[$step](state, indexed[index]) 465 | if (isReduced(state)) { 466 | return state[$value] 467 | } 468 | index = index + 1 469 | } 470 | return state 471 | } 472 | } 473 | 474 | export class StringType extends IndexedType { 475 | // Base string is empty string. 476 | [init.symbol]() { 477 | return "" 478 | } 479 | // If input is an array concat them onto result otherwise just 480 | // concat to strings. 481 | [step.symbol](result, input) { 482 | return isArray(input) ? result.concat(...input) : result + input 483 | } 484 | } 485 | 486 | 487 | export class ArrayType extends IndexedType { 488 | [init.symbol]() { 489 | return [] 490 | } 491 | [step.symbol](array, value) { 492 | array.push(value) 493 | return array 494 | } 495 | } 496 | 497 | 498 | // Iteractors are kind of special in a sence that they produce 499 | export class IteratorType extends ObjectType { 500 | [init.symbol]() { 501 | return IteratorLazyTransform 502 | } 503 | [step.symbol](result, input) { 504 | return result[step.symbol](result, input) 505 | } 506 | [reduce.symbol](transducer, initial, source) { 507 | const iterator = source[$iterator]() 508 | // If it is transformation from iterator to iterator, then initial value is 509 | // going to be `IteratorLazyTransform` as (returned by [init.symbol] method above) 510 | // In such case we just create an instance of `IteratorLazyTransform` and return it 511 | // backe actual transformation will happen on demand by `IteratorLazyTransform`. 512 | if (initial === IteratorLazyTransform) { 513 | return new IteratorLazyTransform(iterator, transducer) 514 | } 515 | 516 | // Otherwise each value will be forwraded to the transducer until done 517 | // iteration or until reduced result is returned. 518 | let result = initial 519 | while(true) { 520 | const {done, value} = iterator.next() 521 | if (done) { 522 | return result 523 | } 524 | 525 | result = transducer[$step](result, value) 526 | 527 | if (isReduced(result)) { 528 | return result[$value] 529 | } 530 | } 531 | } 532 | } 533 | 534 | export class IteratorLazyTransform extends IteratorType { 535 | constructor(source, transducer) { 536 | // Each transformation step `this.transducer.step` may produce 0, 1 or more 537 | // steps in return. In order to accomodate extra values internal buffer is 538 | // going to be used. 539 | this[$buffer] = [] 540 | 541 | this.source = source 542 | this.transducer = transducer 543 | this.isDrained = false 544 | this.done = false 545 | } 546 | [step.symbol](target, value) { 547 | target[$buffer].push(value) 548 | return target 549 | } 550 | [$iterator]() { 551 | return this 552 | } 553 | next() { 554 | // Pull from the source until something is pushed into a buffer or 555 | // or until source is drained. `this.transducer` maybe filtering so 556 | // step may not push anything to a buffer, or it could be mapcatting 557 | // in which case several values will be pushed. It also maybe that 558 | // transducer is accumulating ond on result more values will be pushed 559 | // (like partition). 560 | while (this[$buffer].length === 0 && !this.isDrained) { 561 | const {done, value} = this.source.next() 562 | // If source iterator is drained invoke result on transducer to let 563 | // it cleanup or push whatever it aggregated. 564 | if (done) { 565 | this.transducer[$result](this) 566 | this.isDrained = done 567 | } 568 | // Otherwise keep calling step, if result is reduced then mark this 569 | // iterator drained to stop pulling. 570 | else { 571 | const result = this.transducer[$step](this, value) 572 | this.isDrained = isReduced(result) 573 | } 574 | } 575 | 576 | // At this poin we either get something in a buffer or source was exhausted 577 | // or both. If something is in a buffer just return from it. If buffer is 578 | // empty then source is drained as well so we mark this done and finish. 579 | if (this[$buffer].length > 0) { 580 | this.value = this[$buffer].shift() 581 | } else { 582 | this.value = undefined 583 | this.done = this.isDrained 584 | } 585 | 586 | return this 587 | } 588 | } 589 | const $buffer = symbol("IteratorLazyTransform/buffer") 590 | IteratorLazyTransform.buffer = $buffer 591 | --------------------------------------------------------------------------------