From 09d694bd27d032d98cf56045e721ca5d248af711 Mon Sep 17 00:00:00 2001 From: Viktor Dorozsmai Date: Wed, 7 Feb 2018 16:34:36 +0000 Subject: [PATCH 1/2] Expose more API --- include/NodeTimeSeriesClassificationData.h | 3 + src/NodeDTW.cc | 18 +++-- src/NodeTimeSeriesClassificationData.cc | 91 +++++++++++++++++----- 3 files changed, 86 insertions(+), 26 deletions(-) diff --git a/include/NodeTimeSeriesClassificationData.h b/include/NodeTimeSeriesClassificationData.h index c8e64ee..f0e3411 100644 --- a/include/NodeTimeSeriesClassificationData.h +++ b/include/NodeTimeSeriesClassificationData.h @@ -18,7 +18,10 @@ class NodeTimeSeriesClassificationData : public Nan::ObjectWrap { static NAN_METHOD(New); static NAN_METHOD(SetNumDimensions); static NAN_METHOD(GetNumDimensions); + static NAN_METHOD(SetDatasetName); + static NAN_METHOD(SetInfoText); static NAN_METHOD(AddSample); + static NAN_METHOD(GetNumSamples); static NAN_METHOD(Load); static NAN_METHOD(Save); static NAN_METHOD(Clear); diff --git a/src/NodeDTW.cc b/src/NodeDTW.cc index d400f46..112476b 100644 --- a/src/NodeDTW.cc +++ b/src/NodeDTW.cc @@ -8,7 +8,7 @@ NAN_MODULE_INIT(NodeDTW::Init) { v8::Local tpl = Nan::New(New); tpl->SetClassName(Nan::New("DTW").ToLocalChecked()); tpl->InstanceTemplate()->SetInternalFieldCount(1); - + Nan::SetPrototypeMethod(tpl, "train", Train); Nan::SetPrototypeMethod(tpl, "predict", Predict); Nan::SetPrototypeMethod(tpl, "getPredictedClassLabel", GetPredictedClassLabel); @@ -27,26 +27,27 @@ NodeDTW::~NodeDTW() { NAN_METHOD(NodeDTW::Train) { v8::Isolate* isolate = info.GetIsolate(); - + if (info.Length() < 1) { isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "Wrong number of arguments"))); return; } - + NodeDTW* obj = Nan::ObjectWrap::Unwrap(info.This()); NodeTimeSeriesClassificationData* data = Nan::ObjectWrap::Unwrap(info[0]->ToObject()); - - obj->dtw->train(*data->getTimeSeriesClassificationData()); + + bool returnValue = obj->dtw->train(*data->getTimeSeriesClassificationData()); + info.GetReturnValue().Set(returnValue); } NAN_METHOD(NodeDTW::Predict) { v8::Isolate* isolate = info.GetIsolate(); - + if (info.Length() < 1) { isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "Wrong number of arguments"))); return; } - + NodeDTW* obj = Nan::ObjectWrap::Unwrap(info.This()); if (!info[0]->IsArray()) { isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "Wrong argument"))); @@ -73,7 +74,8 @@ NAN_METHOD(NodeDTW::Predict) { sample.push_back(vector); vector.clear(); } - obj->dtw->predict(sample); + bool returnValue = obj->dtw->predict(sample); + info.GetReturnValue().Set(returnValue); } NAN_METHOD(NodeDTW::GetPredictedClassLabel) { diff --git a/src/NodeTimeSeriesClassificationData.cc b/src/NodeTimeSeriesClassificationData.cc index 3ce787b..45222df 100644 --- a/src/NodeTimeSeriesClassificationData.cc +++ b/src/NodeTimeSeriesClassificationData.cc @@ -10,9 +10,12 @@ NAN_MODULE_INIT(NodeTimeSeriesClassificationData::Init) { Nan::SetPrototypeMethod(tpl, "setNumDimensions", SetNumDimensions); Nan::SetPrototypeMethod(tpl, "getNumDimensions", GetNumDimensions); + Nan::SetPrototypeMethod(tpl, "setDatasetName", SetDatasetName); + Nan::SetPrototypeMethod(tpl, "setInfoText", SetInfoText); Nan::SetPrototypeMethod(tpl, "addSample", AddSample); - Nan::SetPrototypeMethod(tpl, "save", Save); + Nan::SetPrototypeMethod(tpl, "getNumSamples", GetNumSamples); Nan::SetPrototypeMethod(tpl, "load", Load); + Nan::SetPrototypeMethod(tpl, "save", Save); Nan::SetPrototypeMethod(tpl, "clear", Clear); constructor.Reset(Nan::GetFunction(tpl).ToLocalChecked()); @@ -23,23 +26,23 @@ NodeTimeSeriesClassificationData::NodeTimeSeriesClassificationData() { tscd = new GRT::TimeSeriesClassificationData(); } -NodeTimeSeriesClassificationData::~NodeTimeSeriesClassificationData() { +NodeTimeSeriesClassificationData::~NodeTimeSeriesClassificationData() { } GRT::TimeSeriesClassificationData* NodeTimeSeriesClassificationData::getTimeSeriesClassificationData() { return tscd; } - NAN_METHOD(NodeTimeSeriesClassificationData::SetNumDimensions) { v8::Isolate* isolate = info.GetIsolate(); - + if (info.Length() < 1) { - isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "Wrong number of arguments"))); + std::string argsLength = std::to_string(info.Length()); + isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, ("Wrong number of arguments: expected 1, got " + argsLength).c_str()))); return; } - if (!info[0]->IsNumber()) { + if (!info[0]->IsInt32()) { isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "Wrong argument"))); return; } @@ -48,7 +51,6 @@ NAN_METHOD(NodeTimeSeriesClassificationData::SetNumDimensions) { int dimensions = ( int )( info[0]->Int32Value() ); bool returnValue = obj->tscd->setNumDimensions(dimensions); - // std::cout << "Dimensions: " << dimensions << std::endl; info.GetReturnValue().Set(returnValue); } @@ -61,19 +63,62 @@ NAN_METHOD(NodeTimeSeriesClassificationData::GetNumDimensions) { info.GetReturnValue().Set(returnValue); } +NAN_METHOD(NodeTimeSeriesClassificationData::SetDatasetName) { + v8::Isolate* isolate = info.GetIsolate(); + + if (info.Length() < 1) { + isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "Wrong number of arguments"))); + return; + } + + if (!info[0]->IsString()) { + isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "Wrong argument"))); + return; + } + + v8::String::Utf8Value param1(info[0]->ToString()); + std::string name = std::string(*param1); + + NodeTimeSeriesClassificationData* obj = Nan::ObjectWrap::Unwrap(info.This()); + bool returnValue = obj->tscd->setDatasetName(name); + info.GetReturnValue().Set(returnValue); +} + +NAN_METHOD(NodeTimeSeriesClassificationData::SetInfoText) { + v8::Isolate* isolate = info.GetIsolate(); + + if (info.Length() < 1) { + isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "Wrong number of arguments"))); + return; + } + + if (!info[0]->IsString()) { + isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "Wrong argument"))); + return; + } + + v8::String::Utf8Value param1(info[0]->ToString()); + std::string name = std::string(*param1); + + NodeTimeSeriesClassificationData* obj = Nan::ObjectWrap::Unwrap(info.This()); + bool returnValue = obj->tscd->setInfoText(name); + info.GetReturnValue().Set(returnValue); +} + + NAN_METHOD(NodeTimeSeriesClassificationData::AddSample) { v8::Isolate* isolate = info.GetIsolate(); - + if (info.Length() < 2) { isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "Wrong number of arguments"))); return; } - - if (!info[0]->IsNumber()) { + + if (!info[0]->IsInt32()) { isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "Wrong argument"))); return; } - + NodeTimeSeriesClassificationData* obj = Nan::ObjectWrap::Unwrap(info.This()); if (!info[1]->IsArray()) { @@ -92,10 +137,12 @@ NAN_METHOD(NodeTimeSeriesClassificationData::AddSample) { val = jsArray->Get(i); if (!val->IsArray()) { isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "Wrong argument"))); + return; } item = v8::Handle::Cast(val); if (item->Length() != obj->tscd->getNumDimensions()) { - isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "Wrong argument"))); + isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "Incorrect dimension in sample"))); + return; } for (unsigned int j = 0; j < item->Length(); j++) { itemVal = item->Get(j); @@ -105,22 +152,30 @@ NAN_METHOD(NodeTimeSeriesClassificationData::AddSample) { sample.push_back(vector); vector.clear(); } - obj->tscd->addSample(label, sample); + + bool returnValue =obj->tscd->addSample(label, sample); + info.GetReturnValue().Set(returnValue); +} + +NAN_METHOD(NodeTimeSeriesClassificationData::GetNumSamples) { + NodeTimeSeriesClassificationData* obj = Nan::ObjectWrap::Unwrap(info.This()); + int returnValue = obj->tscd->getNumSamples(); + info.GetReturnValue().Set(returnValue); } NAN_METHOD(NodeTimeSeriesClassificationData::Load) { v8::Isolate* isolate = info.GetIsolate(); - + if (info.Length() < 1) { isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "Wrong number of arguments"))); return; } - + if (!info[0]->IsString()) { isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "Wrong argument"))); return; } - + v8::String::Utf8Value param1(info[0]->ToString()); std::string fileName = std::string(*param1); @@ -137,12 +192,12 @@ NAN_METHOD(NodeTimeSeriesClassificationData::Save) { isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "Wrong number of arguments"))); return; } - + if (!info[0]->IsString()) { isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "Wrong argument"))); return; } - + v8::String::Utf8Value param1(info[0]->ToString()); std::string fileName = std::string(*param1); From 0d5b74e2c4f2e7b9b0c2198bfa81f0b066555ea8 Mon Sep 17 00:00:00 2001 From: Viktor Dorozsmai Date: Wed, 7 Feb 2018 16:34:55 +0000 Subject: [PATCH 2/2] Add tests --- package-lock.json | 264 ++++++++++++++++++---------------------------- package.json | 1 + test/index.js | 230 +++++++++++++++++++++++++++++++--------- 3 files changed, 284 insertions(+), 211 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5c33b3d..a2a119d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,20 +1,18 @@ { "name": "node-grt", - "version": "0.0.1", + "version": "0.0.5", "lockfileVersion": 1, "requires": true, "dependencies": { "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, "requires": { "co": "4.6.0", "fast-deep-equal": "1.0.0", @@ -25,20 +23,17 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" }, "are-we-there-yet": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", - "dev": true, "requires": { "delegates": "1.0.0", "readable-stream": "2.3.3" @@ -47,44 +42,42 @@ "asn1": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", - "dev": true + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", - "dev": true + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "bcrypt-pbkdf": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "dev": true, "optional": true, "requires": { "tweetnacl": "0.14.5" @@ -99,7 +92,6 @@ "version": "0.0.9", "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "dev": true, "requires": { "inherits": "2.0.3" } @@ -108,7 +100,6 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", - "dev": true, "requires": { "hoek": "4.2.0" } @@ -117,7 +108,6 @@ "version": "1.1.8", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "dev": true, "requires": { "balanced-match": "1.0.0", "concat-map": "0.0.1" @@ -126,26 +116,40 @@ "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "chai": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", + "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", + "requires": { + "assertion-error": "1.1.0", + "check-error": "1.0.2", + "deep-eql": "3.0.1", + "get-func-name": "2.0.0", + "pathval": "1.1.0", + "type-detect": "4.0.8" + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "combined-stream": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", - "dev": true, "requires": { "delayed-stream": "1.0.0" } @@ -159,26 +163,22 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cryptiles": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", - "dev": true, "requires": { "boom": "5.2.0" }, @@ -187,7 +187,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", - "dev": true, "requires": { "hoek": "4.2.0" } @@ -198,7 +197,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, "requires": { "assert-plus": "1.0.0" } @@ -212,17 +210,23 @@ "ms": "0.7.1" } }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "requires": { + "type-detect": "4.0.8" + } + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, "diff": { "version": "1.4.0", @@ -234,7 +238,6 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "dev": true, "optional": true, "requires": { "jsbn": "0.1.1" @@ -249,38 +252,32 @@ "extend": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", - "dev": true + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", - "dev": true + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=" }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "form-data": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", - "dev": true, "requires": { "asynckit": "0.4.0", "combined-stream": "1.0.5", @@ -290,14 +287,12 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fstream": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "inherits": "2.0.3", @@ -309,7 +304,6 @@ "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, "requires": { "aproba": "1.2.0", "console-control-strings": "1.1.0", @@ -321,11 +315,15 @@ "wide-align": "1.1.2" } }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, "requires": { "assert-plus": "1.0.0" } @@ -343,8 +341,7 @@ "graceful-fs": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, "growl": { "version": "1.9.2", @@ -355,14 +352,12 @@ "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", - "dev": true, "requires": { "ajv": "5.5.2", "har-schema": "2.0.0" @@ -371,14 +366,12 @@ "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, "hawk": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", - "dev": true, "requires": { "boom": "4.3.1", "cryptiles": "3.1.2", @@ -389,14 +382,12 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==", - "dev": true + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, "requires": { "assert-plus": "1.0.0", "jsprim": "1.4.1", @@ -407,7 +398,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "1.4.0", "wrappy": "1.0.2" @@ -416,14 +406,12 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, "requires": { "number-is-nan": "1.0.1" } @@ -431,26 +419,22 @@ "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "jade": { "version": "0.26.3", @@ -480,32 +464,27 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, "optional": true }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, "json-schema-traverse": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -522,14 +501,12 @@ "mime-db": { "version": "1.30.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", - "dev": true + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" }, "mime-types": { "version": "2.1.17", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", - "dev": true, "requires": { "mime-db": "1.30.0" } @@ -547,14 +524,12 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, "requires": { "minimist": "0.0.8" } @@ -586,14 +561,12 @@ "nan": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", - "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", - "dev": true + "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=" }, "node-gyp": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz", "integrity": "sha1-m/vlRWIoYoSDjnUOrAUpWFP6HGA=", - "dev": true, "requires": { "fstream": "1.0.11", "glob": "7.1.2", @@ -614,7 +587,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, "requires": { "fs.realpath": "1.0.0", "inflight": "1.0.6", @@ -628,7 +600,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "1.1.8" } @@ -639,7 +610,6 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, "requires": { "abbrev": "1.1.1" } @@ -648,7 +618,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, "requires": { "are-we-there-yet": "1.1.4", "console-control-strings": "1.1.0", @@ -659,26 +628,22 @@ "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "oauth-sign": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1.0.2" } @@ -686,20 +651,17 @@ "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, "osenv": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", - "dev": true, "requires": { "os-homedir": "1.0.2", "os-tmpdir": "1.0.2" @@ -708,38 +670,37 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "process-nextick-args": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" }, "qs": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", - "dev": true + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" }, "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", @@ -754,7 +715,6 @@ "version": "2.83.0", "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", - "dev": true, "requires": { "aws-sign2": "0.7.0", "aws4": "1.6.0", @@ -784,7 +744,6 @@ "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, "requires": { "glob": "7.1.2" }, @@ -793,7 +752,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, "requires": { "fs.realpath": "1.0.0", "inflight": "1.0.6", @@ -807,7 +765,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "1.1.8" } @@ -817,20 +774,17 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, "semver": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "sigmund": { "version": "1.0.1", @@ -841,14 +795,12 @@ "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, "sntp": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", - "dev": true, "requires": { "hoek": "4.2.0" } @@ -857,7 +809,6 @@ "version": "1.13.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", - "dev": true, "requires": { "asn1": "0.2.3", "assert-plus": "1.0.0", @@ -873,7 +824,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, "requires": { "code-point-at": "1.1.0", "is-fullwidth-code-point": "1.0.0", @@ -884,7 +834,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, "requires": { "safe-buffer": "5.1.1" } @@ -892,14 +841,12 @@ "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", - "dev": true + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -914,7 +861,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", - "dev": true, "requires": { "block-stream": "0.0.9", "fstream": "1.0.11", @@ -931,7 +877,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", - "dev": true, "requires": { "punycode": "1.4.1" } @@ -940,7 +885,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, "requires": { "safe-buffer": "5.1.1" } @@ -949,26 +893,27 @@ "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, "optional": true }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", - "dev": true + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, "requires": { "assert-plus": "1.0.0", "core-util-is": "1.0.2", @@ -979,7 +924,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", - "dev": true, "requires": { "isexe": "2.0.0" } @@ -988,7 +932,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", - "dev": true, "requires": { "string-width": "1.0.2" } @@ -996,8 +939,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" } } } diff --git a/package.json b/package.json index 6853090..ab78dda 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ }, "dependencies": { "bindings": "^1.2.1", + "chai": "^4.1.2", "nan": "^2.0.5", "node-gyp": "^3.6.2", "prebuild-install": "^2.5.0" diff --git a/test/index.js b/test/index.js index 0321ff0..b69b1fa 100644 --- a/test/index.js +++ b/test/index.js @@ -1,50 +1,180 @@ -// FIXME -// var nativeExtension = require('../'); -// var assert = require('assert'); - - -// describe('native extension', function() { -// it('should export a wrapped object', function() { -// var obj = new nativeExtension.MyObject(0); -// assert.equal(obj.plusOne(), 1); -// assert.equal(obj.plusOne(), 2); -// assert.equal(obj.plusOne(), 3); -// }); - -// it('should export function that returns nothing', function() { -// assert.equal(nativeExtension.nothing(), undefined); -// }); - -// it('should export a function that returns a string', function() { -// assert.equal(typeof nativeExtension.aString(), 'string'); -// }); - -// it('should export a function that returns a boolean', function() { -// assert.equal(typeof nativeExtension.aBoolean(), 'boolean'); -// }); - -// it('should export function that returns a number', function() { -// assert.equal(typeof nativeExtension.aNumber(), 'number'); -// }); - -// it('should export function that returns an object', function() { -// assert.equal(typeof nativeExtension.anObject(), 'object'); -// }); - -// it('should export function that returns an object with a key, value pair', function() { -// assert.deepEqual(nativeExtension.anObject(), {'key': 'value'}); -// }); - -// it('should export function that returns an array', function() { -// assert.equal(Array.isArray(nativeExtension.anArray()), true); -// }); - -// it('should export function that returns an array with some values', function() { -// assert.deepEqual(nativeExtension.anArray(), [1, 2, 3]); -// }); - -// it('should export function that calls a callback', function(done) { -// nativeExtension.callback(done); -// }); - -// }); +const nativeExtension = require('../'); +const assert = require('assert'); +const { expect } = require('chai'); +const fs = require('fs'); + +describe('TimeSeriesClassificationData', function() { + let trainingData; + before(() => { + trainingData = new nativeExtension.TimeSeriesClassificationData(); + }); + + after(() => { + + // Delete training data file after running the test + fs.unlink('foo.grt', (err) => { + if (err) throw err; + console.log('Successfully deleted ../foo.grt'); + }); + }); + + // setNumDimensions + + it('setNumDimensions should throw an error with wrong number of arguments', function() { + expect(() => trainingData.setNumDimensions()).to.throw('Wrong number of arguments'); + }); + + it('setNumDimensions should throw an error if argument is not an integer', function() { + expect(() => trainingData.setNumDimensions(1.2)).to.throw('Wrong argument'); + }); + + it('setNumDimensions should return true when calling the method with one integer argument', function() { + assert.equal(trainingData.setNumDimensions(2), true); + }); + + // getNumDimensions + + it('getNumDimensions should return the right number for the dimensions if previously set', function() { + assert.equal(trainingData.getNumDimensions(2), 2); + }); + + // setDatasetName + + it('setDatasetName should throw an error with wrong number of arguments', function() { + expect(() => trainingData.setDatasetName()).to.throw('Wrong number of arguments'); + }); + + it('setDatasetName should throw an error if argument is not a string', function() { + expect(() => trainingData.setDatasetName(1)).to.throw('Wrong argument'); + }); + + it('setDatasetName should return true when calling the method with one string argument', function() { + expect(() => trainingData.setDatasetName(1)).to.throw('Wrong argument'); + }); + + // setInfoText + + it('setInfoText should throw an error with wrong number of arguments', function() { + expect(() => trainingData.setInfoText()).to.throw('Wrong number of arguments'); + }); + + it('setInfoText should throw an error if argument is not a string', function() { + expect(() => trainingData.setInfoText(1)).to.throw('Wrong argument'); + }); + + it('setInfoText should return true when calling the method with one string argument', function() { + expect(() => trainingData.setInfoText(1)).to.throw('Wrong argument'); + }); + + // addSample + + it('addSample should throw an error with wrong number of arguments', function() { + expect(() => trainingData.addSample('foo')).to.throw('Wrong number of arguments'); + }); + + it('addSample should throw an error if first argument is not an integer', function() { + expect(() => trainingData.addSample('foo', [])).to.throw('Wrong argument'); + }); + + it('addSample should throw an error if second argument is not an array', function() { + expect(() => trainingData.addSample(1, 'foo')).to.throw('Wrong argument'); + }); + + it('addSample should throw an error if second argument is not a two-dimensional array', function() { + expect(() => trainingData.addSample(1, [1])).to.throw('Wrong argument'); + }); + + it('addSample should throw an error when the sample dimension is incorrect' , function() { + expect(() => trainingData.addSample(1, [[1]])).to.throw('Incorrect dimension in sample'); + }); + + it('addSample should return true when calling the method with one integer and one array arguments with the correct dimension', function() { + assert.equal(trainingData.addSample(1, [[1, 2]]), true); + }); + + // save + + it('save should throw an error with wrong number of arguments', function() { + expect(() => trainingData.save()).to.throw('Wrong number of arguments'); + }); + + it('save should throw an error if argument is not a string', function() { + expect(() => trainingData.save(1)).to.throw('Wrong argument'); + }); + + it('save should return true when calling the method with one string argument', function() { + assert.equal(trainingData.save('foo.grt'), true); + }); + + // load + + it('load should throw an error with wrong number of arguments', function() { + expect(() => trainingData.load()).to.throw('Wrong number of arguments'); + }); + + it('load should throw an error if argument is not a string', function() { + expect(() => trainingData.load(1)).to.throw('Wrong argument'); + }); + + it('load should return true when calling the method with one string argument', function() { + assert.equal(trainingData.load('foo.grt'), true); + }); + + // clear + + it('clear should empty the training data', function() { + trainingData.clear(); + assert.equal(trainingData.getNumSamples(), 0); + }); +}); + +describe('DTW', function() { + let trainingData; + let timeWarpingAlgorithm; + before(() => { + timeWarpingAlgorithm = new nativeExtension.DTW(); + trainingData = new nativeExtension.TimeSeriesClassificationData(); + trainingData.setNumDimensions(2); + trainingData.addSample(1, [[1, 2]]); + }); + + // train + + it('train should throw an error with wrong number of arguments', function() { + expect(() => timeWarpingAlgorithm.train()).to.throw('Wrong number of arguments'); + }); + + it('train should return true when calling the method with a populated training data argument', function() { + assert.equal(timeWarpingAlgorithm.train(trainingData), true); + }); + + // predict + + it('predict should throw an error with wrong number of arguments', function() { + expect(() => timeWarpingAlgorithm.predict()).to.throw('Wrong number of arguments'); + }); + + it('predict should throw an error if argument is not an array', function() { + expect(() => timeWarpingAlgorithm.predict('foo', [])).to.throw('Wrong argument'); + }); + + it('predict should throw an error if argument is not a two-dimensional array', function() { + expect(() => timeWarpingAlgorithm.predict([1])).to.throw('Wrong argument'); + }); + + it('predict should return true when calling the method with one array argument with the correct dimension', function() { + assert.equal(timeWarpingAlgorithm.predict([[1, 2]]), true); + }); + + // getPredictedClassLabel + + it('getPredictedClassLabel should return the correct label', function() { + assert.equal(timeWarpingAlgorithm.getPredictedClassLabel(), 1); + }); + + // getMaximumLikelihood + + it('getMaximumLikelihood should return 1 if sample and trainingData is a perfect match', function() { + assert.equal(timeWarpingAlgorithm.getMaximumLikelihood(), 1); + }); +});