UNPKG

2.23 kBJavaScriptView Raw
1var conversions = require('./conversions');
2
3/*
4 this function routes a model to all other models.
5
6 all functions that are routed have a property `.conversion` attached
7 to the returned synthetic function. This property is an array
8 of strings, each with the steps in between the 'from' and 'to'
9 color models (inclusive).
10
11 conversions that are not possible simply are not included.
12*/
13
14// https://jsperf.com/object-keys-vs-for-in-with-closure/3
15var models = Object.keys(conversions);
16
17function buildGraph() {
18 var graph = {};
19
20 for (var len = models.length, i = 0; i < len; i++) {
21 graph[models[i]] = {
22 // http://jsperf.com/1-vs-infinity
23 // micro-opt, but this is simple.
24 distance: -1,
25 parent: null
26 };
27 }
28
29 return graph;
30}
31
32// https://en.wikipedia.org/wiki/Breadth-first_search
33function deriveBFS(fromModel) {
34 var graph = buildGraph();
35 var queue = [fromModel]; // unshift -> queue -> pop
36
37 graph[fromModel].distance = 0;
38
39 while (queue.length) {
40 var current = queue.pop();
41 var adjacents = Object.keys(conversions[current]);
42
43 for (var len = adjacents.length, i = 0; i < len; i++) {
44 var adjacent = adjacents[i];
45 var node = graph[adjacent];
46
47 if (node.distance === -1) {
48 node.distance = graph[current].distance + 1;
49 node.parent = current;
50 queue.unshift(adjacent);
51 }
52 }
53 }
54
55 return graph;
56}
57
58function link(from, to) {
59 return function (args) {
60 return to(from(args));
61 };
62}
63
64function wrapConversion(toModel, graph) {
65 var path = [graph[toModel].parent, toModel];
66 var fn = conversions[graph[toModel].parent][toModel];
67
68 var cur = graph[toModel].parent;
69 while (graph[cur].parent) {
70 path.unshift(graph[cur].parent);
71 fn = link(conversions[graph[cur].parent][cur], fn);
72 cur = graph[cur].parent;
73 }
74
75 fn.conversion = path;
76 return fn;
77}
78
79module.exports = function (fromModel) {
80 var graph = deriveBFS(fromModel);
81 var conversion = {};
82
83 var models = Object.keys(graph);
84 for (var len = models.length, i = 0; i < len; i++) {
85 var toModel = models[i];
86 var node = graph[toModel];
87
88 if (node.parent === null) {
89 // no possible conversion, or this node is the source model.
90 continue;
91 }
92
93 conversion[toModel] = wrapConversion(toModel, graph);
94 }
95
96 return conversion;
97};
98