-
Notifications
You must be signed in to change notification settings - Fork 4
/
bricklink-helper.js
121 lines (111 loc) · 3.87 KB
/
bricklink-helper.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
var argv = require('yargs')
.demand([ 'in', 'out' ])
.alias('searchPageDepth', 'd')
.argv,
async = require('async'),
csv = require('csv'),
fs = require('fs'),
path = require('path'),
_ = require('underscore'),
// local
bricklinkSearch = new require('./bricklink-search')({
'debug': true,
'searchPageDepth': argv.searchPageDepth,
}),
bricklinkOrder = new require('./bricklink-order-simplex')(),
ldrReader = new require('./ldr-reader')(),
lxfReader = new require('./lxf-reader')();
var readPartsList = function (filenames, callback) {
var readCSV = function (filename, callback) {
csv()
.from.path(filename, { 'columns': true })
.to.array(function (data) {
callback(null, data);
});
}
var readFile = function (filename, callback) {
switch (path.extname(filename.toLowerCase())) {
case '.csv':
readFunction = readCSV
break;
case '.lxf':
readFunction = lxRreader.read
break;
case '.ldr':
readFunction = ldrReader.read
break;
}
readFunction(filename, callback);
}
filenames = [ ].concat(filenames || [ ]);
async.reduce(filenames, { }, function (memo, filename, callback) {
readFile(filename, function (err, data) {
data.forEach(function (d) {
memo[d.partId] = parseInt(d.quantity) + (memo[d.partId] || 0);
});
callback(err, memo);
});
}, function (err, data) {
callback(err, _.keys(data).map(function (partId) { return { 'partId': partId, 'quantity': data[partId] }; }));
});
};
var writeOrders = function(orders, callback) {
// At the moment this is not really useful: the R output is exactly the same
// file!
csv()
.from.array(orders)
.to.path(argv.out, {
'header': true,
'columns': [ "sellerUsername" ].concat(_.difference(_.keys(orders[0]).sort(), [ "sellerUsername" ])),
})
.on('close', function (count) {
callback(null);
});
}
var makeOrder = function (partsList_, availability_, callback) {
// clones the input parameters
var partsList = JSON.parse(JSON.stringify(partsList_)),
availability = JSON.parse(JSON.stringify(availability_));
// print a warning about the pieces that could not be found in their
// full quantity from at least one seller (read the documentation at
// http://dico.im/1nBkI4i to understand why)
var couldNotBeFound = partsList.reduce(function (memo, part) {
if (!_.find(availability, function (a) {
return (a.partId === part.partId) && (a.quantity >= part.quantity);
})) memo = memo.concat(part.partId);
return memo;
}, [ ]);
if (couldNotBeFound.length > 0) {
console.log("*** WARNING *** Suitable sellers could not be found for part ids: " + couldNotBeFound.join(", ") + ".");
// remove the aforementioned pieces from both the requirements and
// the availability data
partsList = partsList.filter(function (p) { return !_.contains(couldNotBeFound, p.partId); });
availability = availability.filter(function (a) { return !_.contains(couldNotBeFound, a.partId); });
}
// call the dedicated algorithm to formulate the necessary orders
bricklinkOrder.makeOrder(partsList, availability, callback);
}
// main
readPartsList(argv.in, function (err, partsList) {
var complete = function (err, orders) {
writeOrders(orders, function (err) {
console.log("Finished.");
});
};
var availability;
if (argv.cache && fs.existsSync(argv.cache)) {
// if a cache filename was specified and the file exists, read the
// bricks availability from there
console.log("Reading parts availability from cache...");
availability = JSON.parse(fs.readFileSync(argv.cache));
makeOrder(partsList, availability, complete);
} else {
// alternatively, query BrickLink from scratch
console.log("Searching for parts availability online...");
bricklinkSearch.search(partsList, function (err, a) {
availability = a;
if (argv.cache) fs.writeFileSync(argv.cache, JSON.stringify(availability));
makeOrder(partsList, availability, complete);
});
}
});