Comparar commits
44 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| b4829adbc3 | |||
| a3cfa9f8e3 | |||
| 62a80d1f9f | |||
| b0ad46c66b | |||
| 7e2b83b5cc | |||
| 5193bbd931 | |||
| b513bcbec4 | |||
| 408ee8e0f4 | |||
| dd92726044 | |||
| 5d2098e6e1 | |||
| 341497323c | |||
| 1f71b254b5 | |||
| db97a492e1 | |||
| f863fc2638 | |||
| 3d6c654028 | |||
| 64f64ecd2a | |||
| 09b33792d9 | |||
| ab932c1a52 | |||
| 206f4ce6fc | |||
| 1618460984 | |||
| 41cfdfb007 | |||
| 57a60d6919 | |||
| ab3ba50886 | |||
| cc21727a7b | |||
| 1dbbf8a302 | |||
| 6f6ab1af1e | |||
| 09a51dd518 | |||
| 3e0b1c0e50 | |||
| 628c636129 | |||
| d2173bd9f3 | |||
| 2baf4a72bf | |||
| de1ca7a2d2 | |||
| 2b75f16b9a | |||
| 20618ddb40 | |||
| be97f4806e | |||
| cb97a14e59 | |||
| 6faa7d444a | |||
| 806780bd1f | |||
| 2e0ddfaeb9 | |||
| c83d4ecbc5 | |||
| a467e67524 | |||
| 271f237eac | |||
| 857be35efa | |||
| 87f73359ab |
@@ -2,3 +2,4 @@ src/common/lua.js
|
||||
src/visualizers/widgets/TextEditor/lib/*
|
||||
src/common/js-yaml.min.js
|
||||
src/visualizers/Visualizers.json
|
||||
config/config.webgme.js
|
||||
|
||||
+5
-4
@@ -1,18 +1,19 @@
|
||||
env:
|
||||
browser: true
|
||||
node: true
|
||||
mocha: true
|
||||
es6: true
|
||||
extends: 'eslint:recommended'
|
||||
rules:
|
||||
indent:
|
||||
- error
|
||||
- 2
|
||||
- 4
|
||||
linebreak-style:
|
||||
- error
|
||||
- 2
|
||||
- unix
|
||||
quotes:
|
||||
- error
|
||||
- 2
|
||||
- single
|
||||
semi:
|
||||
- error
|
||||
- 2
|
||||
- always
|
||||
|
||||
+13
-6
@@ -1,4 +1,4 @@
|
||||
[](https://img.shields.io/badge/state-pre--alpha-red.svg)
|
||||
[](https://img.shields.io/badge/state-alpha-orange.svg)
|
||||
[](./LICENSE)
|
||||
[](https://travis-ci.org/dfst/deepforge)
|
||||
[](https://gitter.im/dfst/deepforge?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
@@ -6,14 +6,21 @@
|
||||
# DeepForge
|
||||
DeepForge is an open-source visual development environment for deep learning. Currently, it supports Convolutional Neural Networks but we are planning on supporting additional deep learning classifiers such as RNNs and LSTMs. Additional features include real-time collaborative editing and version control.
|
||||
|
||||
## Quick Setup
|
||||
After cloning the repo, run
|
||||
## Quick Start
|
||||
Install dependencies:
|
||||
+ NodeJS (version 6.2.0)
|
||||
+ npm (version 2.x)
|
||||
+ Torch7
|
||||
+ MongoDB
|
||||
+ [git-lfs](https://git-lfs.github.com/)
|
||||
|
||||
First, start mongodb locally.
|
||||
```
|
||||
npm install && npm start
|
||||
git clone https://github.com/dfst/deepforge.git
|
||||
cd deepforge
|
||||
npm install && npm run local
|
||||
```
|
||||
|
||||
Now, navigate to `localhost:8888` in a browser and create a new project. Select `nn` as the seed and start creating your neural nets!
|
||||
Finally, navigate to [http://localhost:8888](http://localhost:8888) to start using DeepForge! For more, detailed instructions,check out our [wiki](https://github.com/dfst/deepforge/wiki/Installation-Guide).
|
||||
|
||||
## Caffe Support?
|
||||
DeepForge uses Torch to perform the actual training and testing of the models. If you are interested in DeepForge using Caffe for actual training and testing, check out [DeepForge-Caffe](https://github.com/dfst/deepforge-caffe).
|
||||
|
||||
@@ -4,6 +4,7 @@ var spawn = require('child_process').spawn,
|
||||
execJob,
|
||||
workerJob = null;
|
||||
|
||||
process.env.NODE_ENV = 'local';
|
||||
execJob = spawn('npm', [
|
||||
'start'
|
||||
]);
|
||||
|
||||
+13
-3
@@ -1,8 +1,9 @@
|
||||
'use strict';
|
||||
/*globals process, __dirname, require*/
|
||||
|
||||
var path = require('path'),
|
||||
fs = require('fs'),
|
||||
spawn = require('child_process').spawn,
|
||||
childProcess = require('child_process'),
|
||||
spawn = childProcess.spawn,
|
||||
projectConfig = require(__dirname + '/../config'),
|
||||
executorSrc = path.join(__dirname, '..', 'node_modules', 'webgme', 'src',
|
||||
'server', 'middleware', 'executor', 'worker'),
|
||||
@@ -12,13 +13,22 @@ var path = require('path'),
|
||||
address,
|
||||
config = {};
|
||||
|
||||
// Check torch support
|
||||
var result = childProcess.spawnSync('th', ['--help']);
|
||||
if (result.error) {
|
||||
console.error('Checking Torch7 dependency failed. Do you have Torch7 installed ' +
|
||||
'and in your PATH?\n\nFor Torch7 installation instructions, check out ' +
|
||||
'http://torch.ch/docs/getting-started.html');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var startExecutor = function() {
|
||||
// Start the executor
|
||||
var execJob = spawn('node', [
|
||||
'node_worker.js',
|
||||
workerConfigPath,
|
||||
workerTmp
|
||||
]);
|
||||
]);
|
||||
execJob.stdout.pipe(process.stdout);
|
||||
execJob.stderr.pipe(process.stderr);
|
||||
};
|
||||
|
||||
@@ -3,6 +3,13 @@
|
||||
"hotkeys": "none",
|
||||
"LayerColors": {}
|
||||
},
|
||||
"FloatingActionButton": {
|
||||
"hideOnEmpty": true
|
||||
},
|
||||
"GenericUIProjectNavigatorController": {
|
||||
"rootMenuClass": "deepforge-logo",
|
||||
"rootDisplayName": "DeepForge"
|
||||
},
|
||||
"CHFLayout": {
|
||||
"panels": [
|
||||
{
|
||||
@@ -13,7 +20,7 @@
|
||||
},
|
||||
{
|
||||
"id": "Footer",
|
||||
"panel": "FooterControls/FooterControlsPanel",
|
||||
"panel": "Footer/FooterPanel",
|
||||
"container": "footer",
|
||||
"DEBUG_ONLY": false
|
||||
},
|
||||
@@ -36,26 +43,41 @@
|
||||
"nodes": [
|
||||
{
|
||||
"nodeName": "MyArchitectures",
|
||||
"icon": "shuffle",
|
||||
"rank": 1,
|
||||
"description": "Neural network architectures are stored here and can be used in pipelines."
|
||||
},
|
||||
{
|
||||
"nodeName": "MyExecutions",
|
||||
"description": "Executions are read-only snapshots of pipelines that have been executed. Past and current executing pipelines are stored here."
|
||||
},
|
||||
{
|
||||
"nodeName": "MyPipelines",
|
||||
"description": "Pipelines are used for training, testing and ensembling models."
|
||||
},
|
||||
{
|
||||
"nodeName": "MyOperations",
|
||||
"icon": "mode_edit",
|
||||
"rank": 2,
|
||||
"color": "blue-grey",
|
||||
"description": "Operations are the building blocks of pipelines. Custom operations can be created and stored here."
|
||||
},
|
||||
{
|
||||
"nodeName": "MyPipelines",
|
||||
"icon": "input",
|
||||
"rank": 3,
|
||||
"description": "Pipelines compose operations together to effectively train, test and/or ensemble models."
|
||||
},
|
||||
{
|
||||
"nodeName": "MyArtifacts",
|
||||
"icon": "view_quilt",
|
||||
"rank": 4,
|
||||
"color": "blue-grey",
|
||||
"description": "Artifacts from pipeline executions are stored here."
|
||||
},
|
||||
{
|
||||
"nodeName": "MyExecutions",
|
||||
"icon": "list",
|
||||
"rank": 5,
|
||||
"description": "Executions are read-only snapshots of pipelines that have been executed. Past and current executing pipelines are stored here."
|
||||
},
|
||||
{
|
||||
"nodeName": "MyDataTypes",
|
||||
"icon": "settings",
|
||||
"rank": 6,
|
||||
"color": "blue-grey",
|
||||
"description": "Custom defined data types are stored here."
|
||||
}
|
||||
]
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
var config = require('./config.webgme'),
|
||||
validateConfig = require('webgme/config/validator');
|
||||
|
||||
require('dotenv').load();
|
||||
require('dotenv').load({silent: true});
|
||||
|
||||
// Add/overwrite any additional settings here
|
||||
config.server.port = process.env.PORT || config.server.port;
|
||||
config.mongo.uri = process.env.MONGO_URI || config.mongo.uri;
|
||||
@@ -16,5 +17,7 @@ config.plugin.allowServerExecution = true;
|
||||
|
||||
config.executor.enable = true;
|
||||
|
||||
config.visualization.extraCss.push('deepforge/styles/global.css');
|
||||
|
||||
validateConfig(config);
|
||||
module.exports = config;
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// Config for running deepforge w/ one local worker
|
||||
// jshint node: true
|
||||
'use strict';
|
||||
|
||||
var config = require('./config.default'),
|
||||
validateConfig = require('webgme/config/validator');
|
||||
|
||||
// Turn up the worker polling rate
|
||||
config.executor.workerRefreshInterval = 150;
|
||||
config.executor.clearOldDataAtStartUp = true,
|
||||
|
||||
validateConfig(config);
|
||||
module.exports = config;
|
||||
@@ -21,6 +21,7 @@ config.seedProjects.basePaths.push('src/seeds/pipeline');
|
||||
config.seedProjects.basePaths.push('src/seeds/devPipelineTests');
|
||||
config.seedProjects.basePaths.push('src/seeds/demo');
|
||||
config.seedProjects.basePaths.push('src/seeds/project');
|
||||
config.seedProjects.basePaths.push('src/seeds/minimal');
|
||||
|
||||
|
||||
|
||||
|
||||
+5
-3
@@ -5,18 +5,20 @@
|
||||
"start-dev": "NODE_ENV=dev node app.js",
|
||||
"worker": "node ./bin/start-worker.js",
|
||||
"local": "node ./bin/start-local.js",
|
||||
"test": "node ./node_modules/mocha/bin/mocha --recursive test"
|
||||
"test": "node ./node_modules/mocha/bin/mocha --recursive test",
|
||||
"watch-test": "./node_modules/nodemon/bin/nodemon.js --exec 'node ./node_modules/mocha/bin/mocha --recursive test'"
|
||||
},
|
||||
"version": "0.4.0",
|
||||
"version": "0.5.0",
|
||||
"dependencies": {
|
||||
"dotenv": "^2.0.0",
|
||||
"lodash.difference": "^4.1.2",
|
||||
"nodemon": "^1.9.2",
|
||||
"webgme": "^2.0.0",
|
||||
"webgme-autoviz": "^2.0.3",
|
||||
"webgme-breadcrumbheader": "^2.0.0",
|
||||
"webgme-chflayout": "^2.0.0",
|
||||
"webgme-easydag": "dfst/webgme-easydag",
|
||||
"webgme-fab": "^2.0.2",
|
||||
"webgme-fab": "dfst/webgme-fab",
|
||||
"webgme-simple-nodes": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*globals define, WebGMEGlobal*/
|
||||
define([
|
||||
'q'
|
||||
], function(
|
||||
Q
|
||||
) {
|
||||
var PtrCodeGen = function() {
|
||||
};
|
||||
|
||||
PtrCodeGen.prototype.getPtrCodeHash = function(ptrId) {
|
||||
return this.core.loadByPath(this.rootNode, ptrId)
|
||||
.then(ptrNode => {
|
||||
// Look up the plugin to use
|
||||
var metanode = this.core.getMetaType(ptrNode),
|
||||
pluginId;
|
||||
|
||||
pluginId = this.core.getRegistry(ptrNode, 'validPlugins').split(' ').shift();
|
||||
this.logger.info(`generating code for ${this.core.getAttribute(ptrNode, 'name')} using ${pluginId}`);
|
||||
|
||||
var context = WebGMEGlobal.Client.getCurrentPluginContext(pluginId);
|
||||
|
||||
context.managerConfig.namespace = this.core.getNamespace(metanode);
|
||||
context.managerConfig.activeNode = this.core.getPath(ptrNode);
|
||||
|
||||
// Load and run the plugin
|
||||
return Q.nfcall(this.executePlugin.bind(this), pluginId, context);
|
||||
})
|
||||
.then(hashes => hashes[0]); // Grab the first asset for now
|
||||
};
|
||||
|
||||
PtrCodeGen.prototype.executePlugin = function(pluginId, config, callback) {
|
||||
// Call the Interpreter manager in a Q.ninvoke friendly way
|
||||
// I need to create a custom context for the given plugin:
|
||||
// - Set the activeNode to the given referenced node
|
||||
// - If the activeNode is namespaced, set META to the given namespace
|
||||
//
|
||||
// FIXME: Check if it is running in the browser or on the server
|
||||
WebGMEGlobal.Client.runBrowserPlugin(pluginId, config, (err, result) => {
|
||||
if (!result.success) {
|
||||
return callback(result.getError());
|
||||
}
|
||||
this.logger.info('Finished calling ' + pluginId);
|
||||
callback(null, result.artifacts);
|
||||
});
|
||||
};
|
||||
|
||||
return PtrCodeGen;
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Audiowide';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Audiowide'), local('Audiowide-Regular'), url(https://fonts.gstatic.com/s/audiowide/v4/7pSgz2MbVvTCvvm7vukSHxJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Audiowide';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Audiowide'), local('Audiowide-Regular'), url(https://fonts.gstatic.com/s/audiowide/v4/8XtYtNKEyyZh481XVWfVOltXRa8TVwTICgirnJhmVJw.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||
}
|
||||
|
||||
.deepforge-logo .item-label {
|
||||
font-family: 'Audiowide', cursive;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*globals define, _*/
|
||||
/*jshint browser: true, camelcase: false*/
|
||||
|
||||
/**
|
||||
* @author brollb / https://github.com/brollb
|
||||
*/
|
||||
|
||||
define([
|
||||
'js/Decorators/DecoratorBase',
|
||||
'./EasyDAG/DcOpDecorator.EasyDAGWidget'
|
||||
], function (
|
||||
DecoratorBase,
|
||||
DcOpDecoratorEasyDAGWidget
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var DcOpDecorator,
|
||||
__parent__ = DecoratorBase,
|
||||
__parent_proto__ = DecoratorBase.prototype,
|
||||
DECORATOR_ID = 'DcOpDecorator';
|
||||
|
||||
DcOpDecorator = function (params) {
|
||||
var opts = _.extend({loggerName: this.DECORATORID}, params);
|
||||
|
||||
__parent__.apply(this, [opts]);
|
||||
|
||||
this.logger.debug('DcOpDecorator ctor');
|
||||
};
|
||||
|
||||
_.extend(DcOpDecorator.prototype, __parent_proto__);
|
||||
DcOpDecorator.prototype.DECORATORID = DECORATOR_ID;
|
||||
|
||||
/*********************** OVERRIDE DecoratorBase MEMBERS **************************/
|
||||
|
||||
DcOpDecorator.prototype.initializeSupportedWidgetMap = function () {
|
||||
this.supportedWidgetMap = {
|
||||
EasyDAG: DcOpDecoratorEasyDAGWidget
|
||||
};
|
||||
};
|
||||
|
||||
return DcOpDecorator;
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @author brollb / https://github.com/brollb
|
||||
*/
|
||||
.dcop-decorator {
|
||||
min-width: 65px;
|
||||
height: 40px;
|
||||
border: 1px solid black;
|
||||
background-color: #dedede;
|
||||
padding: 3px;
|
||||
text-align: center; }
|
||||
.dcop-decorator .attr-title {
|
||||
font-style: italic;
|
||||
}
|
||||
.dcop-decorator .name {
|
||||
margin-top: 10px;
|
||||
white-space: nowrap;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||
text-align: center; }
|
||||
.dcop-decorator .connector {
|
||||
background-color: #fefefe;
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
border: 1px solid blue;
|
||||
z-index: 10;
|
||||
margin-left: -6px;
|
||||
left: 50%; }
|
||||
.dcop-decorator .connector:hover {
|
||||
border-color: rgba(82, 168, 236, 0.8);
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); }
|
||||
.dcop-decorator .connector.top {
|
||||
top: -6px; }
|
||||
.dcop-decorator .connector.bottom {
|
||||
bottom: -6px; }
|
||||
|
||||
.selected .dcop-decorator {
|
||||
border: 1px solid #52a8ec;
|
||||
background-color: #dbeafc; }
|
||||
@@ -0,0 +1,86 @@
|
||||
/*globals define, _*/
|
||||
/*jshint browser: true, camelcase: false*/
|
||||
|
||||
/**
|
||||
* @author brollb / https://github.com/brollb
|
||||
*/
|
||||
|
||||
define([
|
||||
'js/Constants',
|
||||
'decorators/OperationDecorator/EasyDAG/OperationDecorator.EasyDAGWidget',
|
||||
'css!./DcOpDecorator.EasyDAGWidget.css'
|
||||
], function (
|
||||
CONSTANTS,
|
||||
DecoratorBase
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var DcOpDecorator,
|
||||
DECORATOR_ID = 'DcOpDecorator';
|
||||
|
||||
// DcOp nodes need to be able to...
|
||||
// - dynamically change their outputs (downcast)
|
||||
DcOpDecorator = function (options) {
|
||||
options.color = options.color || '#78909c';
|
||||
DecoratorBase.call(this, options);
|
||||
};
|
||||
|
||||
_.extend(DcOpDecorator.prototype, DecoratorBase.prototype);
|
||||
|
||||
DcOpDecorator.prototype.DECORATOR_ID = DECORATOR_ID;
|
||||
|
||||
DcOpDecorator.prototype.getTargetFilterFnFor = function() {
|
||||
return id => {
|
||||
var node = this.client.getNode(id);
|
||||
return node.getId() !== node.getMetaTypeId(); // not meta node
|
||||
};
|
||||
};
|
||||
|
||||
DcOpDecorator.prototype.savePointer = function(name, to) {
|
||||
// When the 'artifact' pointer is changed, we should change the base
|
||||
// of the data output node to the target type
|
||||
if (name === 'artifact' && (typeof to === 'string')) {
|
||||
var output = this._node.outputs[0];
|
||||
|
||||
this.client.startTransaction(`Setting output of ${this.name} to ${to}`);
|
||||
if (!output) {
|
||||
// create the output node
|
||||
this._createOutputNode(to);
|
||||
} else {
|
||||
this.client.makePointer(output.id, CONSTANTS.POINTER_BASE, to);
|
||||
}
|
||||
|
||||
// 'cast' the output node to the correct type
|
||||
this.client.makePointer(this._node.id, name, to);
|
||||
this.client.completeTransaction();
|
||||
} else {
|
||||
DecoratorBase.prototype.savePointer.call(this, name, to);
|
||||
}
|
||||
};
|
||||
|
||||
DcOpDecorator.prototype._createOutputNode = function(baseId) {
|
||||
// Get the outputCntrId
|
||||
// TOOD
|
||||
var n = this.client.getNode(this._node.id),
|
||||
outputCntrId;
|
||||
|
||||
outputCntrId = n.getChildrenIds().find(id => {
|
||||
var metaTypeId = this.client.getNode(id).getMetaTypeId(),
|
||||
metaType = this.client.getNode(metaTypeId);
|
||||
|
||||
if (!metaType) {
|
||||
this.logger.error(`Could not check the type of ${id}!`);
|
||||
return false;
|
||||
}
|
||||
return metaType.getAttribute('name') === 'Outputs';
|
||||
});
|
||||
|
||||
this.client.createChild({
|
||||
baseId: baseId,
|
||||
parentId: outputCntrId
|
||||
});
|
||||
};
|
||||
|
||||
return DcOpDecorator;
|
||||
});
|
||||
@@ -1,18 +1,20 @@
|
||||
/*globals define, WebGMEGlobal*/
|
||||
/*globals define */
|
||||
/*jshint node:true, browser:true, esversion: 6*/
|
||||
|
||||
define([
|
||||
'plugin/CreateExecution/CreateExecution/CreateExecution',
|
||||
'deepforge/plugin/PtrCodeGen',
|
||||
'common/core/constants',
|
||||
'q',
|
||||
'text!./metadata.json',
|
||||
'./Templates/index',
|
||||
'./templates/index',
|
||||
'./LocalExecutor',
|
||||
'executor/ExecutorClient',
|
||||
'jszip',
|
||||
'underscore'
|
||||
], function (
|
||||
CreateExecution,
|
||||
PtrCodeGen,
|
||||
CONSTANTS,
|
||||
Q,
|
||||
pluginMetadata,
|
||||
@@ -37,6 +39,8 @@ define([
|
||||
CreateExecution.call(this);
|
||||
this.pluginMetadata = pluginMetadata;
|
||||
|
||||
this._currentSave = Q();
|
||||
|
||||
// Cache
|
||||
this.nodes = {};
|
||||
|
||||
@@ -78,6 +82,7 @@ define([
|
||||
// inputs for the next operation cannot be created until the inputs have
|
||||
// been generated
|
||||
|
||||
this.pipelineName = this.core.getAttribute(this.activeNode, 'name');
|
||||
var startPromise;
|
||||
if (this.core.isTypeOf(this.activeNode, this.META.Pipeline)) {
|
||||
// If starting with a pipeline, we will create an Execution first
|
||||
@@ -103,16 +108,22 @@ define([
|
||||
this.buildCache(subtree);
|
||||
this.parsePipeline(children); // record deps, etc
|
||||
|
||||
//if (this.getCurrentConfig().reset) {
|
||||
this.clearResults();
|
||||
//}
|
||||
|
||||
// Execute the operations in the proper order
|
||||
this.executePipeline();
|
||||
return this.clearResults();
|
||||
})
|
||||
.then(() => this.executePipeline())
|
||||
.fail(e => this.logger.error(e));
|
||||
};
|
||||
|
||||
// Override 'save' to prevent race conditions while saving
|
||||
ExecutePipeline.prototype.save = function (msg) {
|
||||
// When 'save' is called, it should still finish any current save op
|
||||
// before continuing
|
||||
this._currentSave = this._currentSave
|
||||
.then(() => CreateExecution.prototype.save.call(this, msg));
|
||||
|
||||
return this._currentSave;
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.clearResults = function () {
|
||||
var nodes = Object.keys(this.nodes).map(id => this.nodes[id]);
|
||||
// Clear the pipeline's results
|
||||
@@ -124,13 +135,15 @@ define([
|
||||
// Set the status for each job to 'pending'
|
||||
nodes.filter(node => this.core.isTypeOf(node, this.META.Job))
|
||||
.forEach(node => this.core.setAttribute(node, 'status', 'pending'));
|
||||
|
||||
this.logger.info('Setting all jobs status to "pending"');
|
||||
this.logger.debug(`Making a commit from ${this.currentHash}`);
|
||||
return this.save(`Initializing ${this.pipelineName} for execution`);
|
||||
};
|
||||
|
||||
//////////////////////////// Operation Preparation/Execution ////////////////////////////
|
||||
ExecutePipeline.prototype.buildCache = function (nodes) {
|
||||
// Cache all nodes
|
||||
// Do I need to cache the data inputs? TODO
|
||||
// Probably not - I should be able to look them up as needed
|
||||
nodes.forEach(node => this.nodes[this.core.getPath(node)] = node);
|
||||
};
|
||||
|
||||
@@ -235,8 +248,10 @@ define([
|
||||
// Execute all ready operations
|
||||
readyOps.forEach(jobId => {
|
||||
delete this.incomingCounts[jobId];
|
||||
this.executeOperation(jobId);
|
||||
});
|
||||
readyOps.reduce((prev, jobId) => {
|
||||
return prev.then(() => this.executeOperation(jobId));
|
||||
}, Q());
|
||||
return readyOps.length;
|
||||
};
|
||||
|
||||
@@ -259,11 +274,12 @@ define([
|
||||
inputs;
|
||||
|
||||
// Execute any special operation types here - not on an executor
|
||||
this.logger.debug(`Executing operation "${name}"`);
|
||||
if (localTypeId !== null) {
|
||||
this.executeLocalOperation(localTypeId, node);
|
||||
return this.executeLocalOperation(localTypeId, node);
|
||||
} else {
|
||||
// Generate all execution files
|
||||
this.createOperationFiles(node).then(results => {
|
||||
return this.createOperationFiles(node).then(results => {
|
||||
files = results;
|
||||
artifactName = `${name}_${jobId.replace(/\//g, '_')}-execution-files`;
|
||||
artifact = this.blobClient.createArtifact(artifactName);
|
||||
@@ -307,7 +323,8 @@ define([
|
||||
.then(outputArgs => {
|
||||
var config,
|
||||
args = ['init.lua'],
|
||||
outputs;
|
||||
outputs,
|
||||
file;
|
||||
|
||||
outputs = outputArgs.map(pair => pair[0])
|
||||
.map(name => {
|
||||
@@ -333,6 +350,13 @@ define([
|
||||
files['executor_config.json'] = JSON.stringify(config, null, 4);
|
||||
|
||||
// Save the artifact
|
||||
// Remove empty hashes
|
||||
for (file in data) {
|
||||
if (!data[file]) {
|
||||
this.logger.warn(`Empty data hash has been found for file "${file}". Removing it...`);
|
||||
delete data[file];
|
||||
}
|
||||
}
|
||||
return artifact.addObjectHashes(data);
|
||||
})
|
||||
.then(() => {
|
||||
@@ -350,6 +374,7 @@ define([
|
||||
})
|
||||
.fail(e => {
|
||||
this.core.setAttribute(this.nodes[jobId], 'status', 'fail');
|
||||
this.logger.info(`Setting ${jobId} status to "fail"`);
|
||||
this.onPipelineComplete(`Distributed operation "${name}" failed ${e}`);
|
||||
});
|
||||
}
|
||||
@@ -367,9 +392,10 @@ define([
|
||||
|
||||
// Set the job status to 'running'
|
||||
this.core.setAttribute(this.nodes[jobId], 'status', 'running');
|
||||
|
||||
// Run the operation on an executor
|
||||
executor.createJob({hash})
|
||||
this.logger.info(`Setting ${jobId} status to "running" (${this.currentHash})`);
|
||||
this.logger.debug(`Making a commit from ${this.currentHash}`);
|
||||
this.save(`Started "${name}" operation in ${this.pipelineName}`)
|
||||
.then(() => executor.createJob({hash}))
|
||||
.then(() => this.watchOperation(executor, hash, opId, jobId))
|
||||
.catch(err => this.logger.error(`Could not execute "${name}": ${err}`));
|
||||
|
||||
@@ -394,6 +420,7 @@ define([
|
||||
this.result.addArtifact(info.resultHashes[name + '-all-files']);
|
||||
// Set the job to failed! Store the error
|
||||
this.core.setAttribute(this.nodes[jobId], 'status', 'fail');
|
||||
this.logger.info(`Setting ${jobId} status to "fail"`);
|
||||
this.onPipelineComplete(`Operation "${opId}" failed! ${JSON.stringify(info)}`); // Failed
|
||||
} else {
|
||||
name = this.core.getAttribute(this.nodes[opId], 'name');
|
||||
@@ -433,6 +460,7 @@ define([
|
||||
hash = artifact.descriptor.content[`outputs/${name}`].content;
|
||||
|
||||
this.core.setAttribute(outputMap[name], 'data', hash);
|
||||
this.logger.info(`Setting ${nodeId} data to ${hash}`);
|
||||
});
|
||||
|
||||
return this.onOperationComplete(node);
|
||||
@@ -445,45 +473,53 @@ define([
|
||||
nextPortIds = this.getOperationOutputIds(opNode),
|
||||
jNode = this.core.getParent(opNode),
|
||||
resultPorts,
|
||||
jobId = this.core.getPath(jNode),
|
||||
hasReadyOps;
|
||||
|
||||
// Set the operation to 'success'!
|
||||
this.core.setAttribute(jNode, 'status', 'success');
|
||||
this.logger.info(`Setting ${jobId} status to "success"`);
|
||||
this.logger.debug(`Making a commit from ${this.currentHash}`);
|
||||
this.save(`Operation "${name}" in ${this.pipelineName} completed successfully`)
|
||||
.then(() => {
|
||||
|
||||
// Transport the data from the outputs to any connected inputs
|
||||
// - Get all the connections from each outputId
|
||||
// - Get the corresponding dst outputs
|
||||
// - Use these new ids for checking 'hasReadyOps'
|
||||
resultPorts = nextPortIds.map(id => this.inputPortsFor[id])
|
||||
.reduce((l1, l2) => l1.concat(l2), []);
|
||||
// Transport the data from the outputs to any connected inputs
|
||||
// - Get all the connections from each outputId
|
||||
// - Get the corresponding dst outputs
|
||||
// - Use these new ids for checking 'hasReadyOps'
|
||||
resultPorts = nextPortIds.map(id => this.inputPortsFor[id])
|
||||
.reduce((l1, l2) => l1.concat(l2), []);
|
||||
|
||||
resultPorts.map((id, i) => [this.nodes[id], this.nodes[nextPortIds[i]]])
|
||||
.forEach(pair => { // [ resultPort, nextPort ]
|
||||
var result = pair[0],
|
||||
next = pair[1],
|
||||
hash = this.core.getAttribute(result, 'data');
|
||||
|
||||
this.logger.info(`forwarding data (${hash}) from ${this.core.getPath(result)} ` +
|
||||
`to ${this.core.getPath(next)}`);
|
||||
this.core.setAttribute(next, 'data', hash);
|
||||
resultPorts
|
||||
.map((id, i) => [this.nodes[id], this.nodes[nextPortIds[i]]])
|
||||
.forEach(pair => { // [ resultPort, nextPort ]
|
||||
var result = pair[0],
|
||||
next = pair[1],
|
||||
hash = this.core.getAttribute(result, 'data');
|
||||
|
||||
this.logger.info(`forwarding data (${hash}) from ${this.core.getPath(result)} ` +
|
||||
`to ${this.core.getPath(next)}`);
|
||||
this.core.setAttribute(next, 'data', hash);
|
||||
this.logger.info(`Setting ${jobId} data to ${hash}`);
|
||||
});
|
||||
|
||||
// For all the nextPortIds, decrement the corresponding operation's incoming counts
|
||||
hasReadyOps = nextPortIds.map(id => this.getSiblingIdContaining(id))
|
||||
.reduce((l1, l2) => l1.concat(l2), [])
|
||||
|
||||
// decrement the incoming counts for each operation id
|
||||
.map(opId => --this.incomingCounts[opId])
|
||||
.indexOf(0) > -1;
|
||||
|
||||
this.completedCount++;
|
||||
this.logger.debug(`Operation "${name}" completed. ` +
|
||||
`${this.totalCount - this.completedCount} remaining.`);
|
||||
if (hasReadyOps) {
|
||||
this.executeReadyOperations();
|
||||
} else if (this.completedCount === this.totalCount) {
|
||||
this.onPipelineComplete();
|
||||
}
|
||||
});
|
||||
|
||||
// For all the nextPortIds, decrement the corresponding operation's incoming counts
|
||||
hasReadyOps = resultPorts.map(id => this.opFor[id])
|
||||
.reduce((l1, l2) => l1.concat(l2), [])
|
||||
|
||||
// decrement the incoming counts for each operation id
|
||||
.map(opId => --this.incomingCounts[opId])
|
||||
.indexOf(0) > -1;
|
||||
|
||||
this.completedCount++;
|
||||
this.logger.info(`Operation "${name}" completed. ` +
|
||||
`${this.totalCount - this.completedCount} remaining.`);
|
||||
if (hasReadyOps) {
|
||||
this.executeReadyOperations();
|
||||
} else if (this.completedCount === this.totalCount) {
|
||||
this.onPipelineComplete();
|
||||
}
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.getOperationOutputIds = function(node) {
|
||||
@@ -526,14 +562,14 @@ define([
|
||||
.then(inputs => {
|
||||
// For each input, match the connection with the input name
|
||||
// [ name, type ] => [ name, type, node ]
|
||||
if (inputs.length > 1) {
|
||||
this.logger.warn('multiple inputs not yet fully supported!');
|
||||
}
|
||||
|
||||
//
|
||||
// For each input,
|
||||
// - create the deserializer
|
||||
// - put it in inputs/<name>/init.lua
|
||||
// - copy the data asset to /inputs/<name>/init.lua
|
||||
inputs = inputs
|
||||
.filter(pair => !!this.core.getAttribute(pair[2], 'data')); // remove empty inputs
|
||||
|
||||
files.inputAssets = {}; // data assets
|
||||
tplContents = inputs.map(pair => {
|
||||
var name = pair[0],
|
||||
@@ -544,10 +580,11 @@ define([
|
||||
code: this.core.getAttribute(node, 'deserialize')
|
||||
};
|
||||
});
|
||||
var hashes = inputs.map(pair =>
|
||||
var hashes = inputs
|
||||
// storing the hash for now...
|
||||
files.inputAssets[pair[0]] = this.core.getAttribute(pair[2], 'data')
|
||||
);
|
||||
.map(pair =>
|
||||
files.inputAssets[pair[0]] = this.core.getAttribute(pair[2], 'data')
|
||||
);
|
||||
return Q.all(hashes.map(h => this.blobClient.getMetadata(h)));
|
||||
})
|
||||
.then(metadatas => {
|
||||
@@ -562,57 +599,23 @@ define([
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.createPointers = function (node, files, cb) {
|
||||
var pointers = this.core.getPointerNames(node).filter(name => name !== 'base'),
|
||||
nIds = pointers.map(p => this.core.getPointerPath(node, p));
|
||||
var pointers,
|
||||
nIds;
|
||||
|
||||
pointers = this.core.getPointerNames(node)
|
||||
.filter(name => name !== 'base')
|
||||
.filter(id => this.core.getPointerPath(node, id) !== null);
|
||||
|
||||
nIds = pointers.map(p => this.core.getPointerPath(node, p));
|
||||
files.ptrAssets = {};
|
||||
Q.all(
|
||||
nIds.map(nId => this.core.loadByPath(this.rootNode, nId))
|
||||
nIds.map(nId => this.getPtrCodeHash(nId))
|
||||
)
|
||||
.then(nodes => {
|
||||
|
||||
var executePlugin = (pluginId, config, callback) => {
|
||||
// Call the Interpreter manager in a Q.ninvoke friendly way
|
||||
// I need to create a custom context for the given plugin:
|
||||
// - Set the activeNode to the given referenced node
|
||||
// - If the activeNode is namespaced, set META to the given namespace
|
||||
//
|
||||
// FIXME: Check if it is running in the browser or on the server
|
||||
WebGMEGlobal.Client.runBrowserPlugin(pluginId, config, (err, result) => {
|
||||
if (!result.success) {
|
||||
return callback(result.getError());
|
||||
}
|
||||
this.logger.info('Finished calling ' + pluginId);
|
||||
callback(null, result.artifacts);
|
||||
});
|
||||
};
|
||||
|
||||
return Q.all(
|
||||
nodes.map(ptrNode => {
|
||||
// Look up the plugin to use
|
||||
var metanode = this.core.getMetaType(ptrNode),
|
||||
pluginId;
|
||||
|
||||
pluginId = this.core.getRegistry(ptrNode, 'validPlugins').split(' ').shift();
|
||||
this.logger.info(`generating code for ${this.core.getAttribute(ptrNode, 'name')} using ${pluginId}`);
|
||||
|
||||
var context = WebGMEGlobal.Client.getCurrentPluginContext(pluginId);
|
||||
|
||||
context.managerConfig.namespace = this.core.getNamespace(metanode);
|
||||
context.managerConfig.activeNode = this.core.getPath(ptrNode);
|
||||
|
||||
// Load and run the plugin
|
||||
return Q.nfcall(executePlugin, pluginId, context);
|
||||
})
|
||||
);
|
||||
})
|
||||
.then(resultHashes => {
|
||||
var name = this.core.getAttribute(node, 'name');
|
||||
this.logger.info(`Pointer generation for ${name} FINISHED!`);
|
||||
resultHashes.forEach((hashes, index) => {
|
||||
// Grab the first asset for now
|
||||
// FIXME
|
||||
files.ptrAssets[`pointers/${pointers[index]}/init.lua`] = hashes[0];
|
||||
resultHashes.forEach((hash, index) => {
|
||||
files.ptrAssets[`pointers/${pointers[index]}/init.lua`] = hash;
|
||||
});
|
||||
return cb(null, files);
|
||||
})
|
||||
@@ -694,10 +697,12 @@ define([
|
||||
};
|
||||
|
||||
// Get input data arguments
|
||||
content.inputs = inputs;
|
||||
content.inputs = inputs
|
||||
.map(pair => [pair[0], !this.core.getAttribute(pair[2], 'data')]); // remove empty inputs
|
||||
|
||||
// Defined variables for each pointers
|
||||
content.pointers = pointers;
|
||||
content.pointers = pointers
|
||||
.map(id => [id, this.core.getPointerPath(node, id) === null]);
|
||||
|
||||
// Add remaining code
|
||||
content.code = code;
|
||||
@@ -745,7 +750,11 @@ define([
|
||||
return this[type](node);
|
||||
};
|
||||
|
||||
_.extend(ExecutePipeline.prototype, LocalExecutor.prototype);
|
||||
_.extend(
|
||||
ExecutePipeline.prototype,
|
||||
LocalExecutor.prototype,
|
||||
PtrCodeGen.prototype
|
||||
);
|
||||
|
||||
return ExecutePipeline;
|
||||
});
|
||||
|
||||
@@ -9,9 +9,24 @@ define([
|
||||
};
|
||||
|
||||
// Should these be in lua?
|
||||
LocalExecutor.prototype.BlobLoader = function(node) {
|
||||
var hash = this.core.getAttribute(node, 'data');
|
||||
return this.getOutputs(node)
|
||||
LocalExecutor.prototype.ArtifactLoader = function(node) {
|
||||
// FIXME: Get the hash from the output node
|
||||
var hash;
|
||||
return this.core.loadChildren(node)
|
||||
.then(cntrs => {
|
||||
// Get the output container and load it's children
|
||||
var output = cntrs
|
||||
.find(cntr => {
|
||||
var metaNode = this.core.getMetaType(cntr),
|
||||
metaName = this.core.getAttribute(metaNode, 'name');
|
||||
return metaName === 'Outputs';
|
||||
});
|
||||
return this.core.loadChildren(output);
|
||||
})
|
||||
.then(dataNodes => {
|
||||
hash = this.core.getAttribute(dataNodes[0], 'data');
|
||||
return this.getOutputs(node);
|
||||
})
|
||||
.then(outputTuples => {
|
||||
var outputs = outputTuples.map(tuple => tuple[2]),
|
||||
paths;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
require 'paths'
|
||||
|
||||
local path = 'inputs/<%= name %>/<%= filename %>'
|
||||
local abs_path = paths.concat('inputs', '<%= name %>', '<%= filename %>')
|
||||
|
||||
<%= code %>
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
-- input data
|
||||
<% inputs.forEach(function(pair) { var input = pair[0]%>
|
||||
<%= input %> = require './inputs/<%= input %>'
|
||||
<% }); %>
|
||||
-- input data<% inputs.forEach(function(pair) { var input = pair[0], isNil = pair[1];%>
|
||||
<%= isNil ? 'local ' : ''%><%= input %> = <% if (isNil) { %>nil<% } else { %>require './inputs/<%= input %>'<%}}); %>
|
||||
|
||||
-- load references
|
||||
<% pointers.forEach(function(pointer) { %><%= pointer %> = require './pointers/<%= pointer %>'
|
||||
<% }); %>
|
||||
-- load references<% pointers.forEach(function(pair) { var pointer = pair[0], isNil = pair[1];%>
|
||||
<%= isNil ? 'local ' : ''%><%= pointer %> = <% if (isNil) { %>nil<% } else { %>require './pointers/<%= pointer %>'<%}}); %>
|
||||
attributes = require './attributes'
|
||||
|
||||
-- main operation code for <%= name %>
|
||||
|
||||
@@ -29,6 +29,7 @@ define([
|
||||
* @classdesc This class represents the plugin GenerateArchitecture.
|
||||
* @constructor
|
||||
*/
|
||||
var INDEX = '__index__';
|
||||
var GenerateArchitecture = function () {
|
||||
// Call base class' constructor.
|
||||
PluginBase.call(this);
|
||||
@@ -43,46 +44,125 @@ define([
|
||||
|
||||
GenerateArchitecture.prototype.main = function () {
|
||||
this.LayerDict = createLayerDict(this.core, this.META);
|
||||
this.uniqueId = 2;
|
||||
this._oldTemplateSettings = _.templateSettings;
|
||||
return PluginBase.prototype.main.apply(this, arguments);
|
||||
};
|
||||
|
||||
GenerateArchitecture.prototype.createOutputFiles = function (tree) {
|
||||
var layers = tree[Constants.CHILDREN],
|
||||
//initialLayers,
|
||||
result = {},
|
||||
template,
|
||||
snippet,
|
||||
code,
|
||||
args;
|
||||
code;
|
||||
|
||||
code = [
|
||||
'require \'nn\'',
|
||||
'',
|
||||
'local net = nn.Sequential()'
|
||||
].join('\n');
|
||||
|
||||
// Start with sequential (just one input)
|
||||
for (var i = 0; i < layers.length; i++) {
|
||||
if (layers[i][Constants.NEXT].length > 1) {
|
||||
// no support for
|
||||
this.logger.error('No support for parallel layers... yet');
|
||||
break;
|
||||
} else {
|
||||
// args
|
||||
args = this.createArgString(layers[i]);
|
||||
template = _.template('net:add(nn.{{= name }}' + args + ')');
|
||||
snippet = template(layers[i]);
|
||||
code += '\n' + snippet;
|
||||
}
|
||||
}
|
||||
|
||||
code += '\n\nreturn net';
|
||||
//initialLayers = layers.filter(layer => layer[Constants.PREV].length === 0);
|
||||
// Add an index to each layer
|
||||
layers.forEach((l, index) => l[INDEX] = index);
|
||||
code = this.genArchCode(layers);
|
||||
|
||||
result[tree.name + '.lua'] = code;
|
||||
_.templateSettings = this._oldTemplateSettings; // FIXME: Fix this in SimpleNodes
|
||||
return result;
|
||||
};
|
||||
|
||||
GenerateArchitecture.prototype.genArchCode = function (layers) {
|
||||
// Create a 'null' start layer
|
||||
|
||||
return [
|
||||
'require \'nn\'',
|
||||
this.createSequential(layers[0], 'net').code,
|
||||
'\nreturn net'
|
||||
].join('\n');
|
||||
};
|
||||
|
||||
GenerateArchitecture.prototype.createSequential = function (layer, name) {
|
||||
var next = layer[Constants.NEXT][0],
|
||||
args,
|
||||
template,
|
||||
snippet,
|
||||
snippets,
|
||||
code = `\nlocal ${name} = nn.Sequential()`,
|
||||
|
||||
group,
|
||||
i,
|
||||
result;
|
||||
|
||||
while (layer) {
|
||||
// if there is only one successor, just add the given layer
|
||||
if (layer[Constants.PREV].length > 1) { // sequential layers are over
|
||||
next = layer; // the given layer will be added by the caller
|
||||
break;
|
||||
} else { // add the given layer
|
||||
args = this.createArgString(layer);
|
||||
template = _.template(name + ':add(nn.{{= name }}' + args + ')');
|
||||
snippet = template(layer);
|
||||
code += '\n' + snippet;
|
||||
|
||||
}
|
||||
|
||||
while (layer && layer[Constants.NEXT].length > 1) { // concat/parallel
|
||||
// if there is a fork, recurse and add a concat layer
|
||||
|
||||
this.logger.debug(`detected fork of size ${layer[Constants.NEXT].length}`);
|
||||
snippets = layer[Constants.NEXT].map(nlayer =>
|
||||
this.createSequential(nlayer, 'net_'+(this.uniqueId++)));
|
||||
code += '\n' + snippets.map(snippet => snippet.code).join('\n');
|
||||
|
||||
// Make sure all snippets end at the same concat node
|
||||
|
||||
// Until all snippets end at the same concat node
|
||||
snippets.sort((a, b) => a.endIndex < b.endIndex ? -1 : 1);
|
||||
group = [];
|
||||
while (snippets.length > 0) {
|
||||
// Add snippets to the group
|
||||
i = 0;
|
||||
while (i < snippets.length &&
|
||||
snippets[0].endIndex === snippets[i].endIndex) {
|
||||
|
||||
group.push(snippets[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
// Add concat layer
|
||||
layer = group[0].next;
|
||||
if (layer) {
|
||||
args = this.createArgString(layer);
|
||||
code += `\n\nlocal concat_${layer[INDEX]} = nn.Concat${args}\n` +
|
||||
group.map(snippet =>
|
||||
`concat_${layer[INDEX]}:add(${snippet.name})`)
|
||||
.join('\n') + `\n\n${name}:add(concat_${layer[INDEX]})`;
|
||||
|
||||
next = layer[Constants.NEXT][0];
|
||||
} else {
|
||||
next = null; // no next layers
|
||||
}
|
||||
|
||||
// Remove the updated snippets
|
||||
this.logger.debug('removing ' + i + ' snippet(s)');
|
||||
snippets.splice(0, i);
|
||||
|
||||
// merge the elements in the group
|
||||
if (snippets.length) { // prepare next iteration
|
||||
result = this.createSequential(next, 'net_'+(this.uniqueId++));
|
||||
code += result.code;
|
||||
group = [result];
|
||||
this.logger.debug('updating group ('+ snippets.length+ ' left)');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layer = next;
|
||||
next = layer && layer[Constants.NEXT][0];
|
||||
}
|
||||
|
||||
return {
|
||||
code: code,
|
||||
name: name,
|
||||
endIndex: next ? next[INDEX] : Infinity,
|
||||
next: next
|
||||
};
|
||||
};
|
||||
|
||||
GenerateArchitecture.prototype.createArgString = function (layer) {
|
||||
return '(' + this.LayerDict[layer.name].map(arg => {
|
||||
var value = layer[arg.name];
|
||||
|
||||
@@ -0,0 +1,344 @@
|
||||
/*globals define, _*/
|
||||
/*jshint node:true, browser:true*/
|
||||
|
||||
/**
|
||||
* Generated by PluginGenerator 1.7.0 from webgme on Sat Jun 04 2016 18:01:54 GMT-0500 (CDT).
|
||||
* A plugin that inherits from the PluginBase. To see source code documentation about available
|
||||
* properties and methods visit %host%/docs/source/PluginBase.html.
|
||||
*/
|
||||
|
||||
define([
|
||||
'text!./metadata.json',
|
||||
'plugin/PluginBase',
|
||||
'deepforge/plugin/PtrCodeGen',
|
||||
'q'
|
||||
], function (
|
||||
pluginMetadata,
|
||||
PluginBase,
|
||||
PtrCodeGen,
|
||||
Q
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
pluginMetadata = JSON.parse(pluginMetadata);
|
||||
var HEADER_LENGTH = 60;
|
||||
|
||||
/**
|
||||
* Initializes a new instance of GenerateExecFile.
|
||||
* @class
|
||||
* @augments {PluginBase}
|
||||
* @classdesc This class represents the plugin GenerateExecFile.
|
||||
* @constructor
|
||||
*/
|
||||
var GenerateExecFile = function () {
|
||||
// Call base class' constructor.
|
||||
PluginBase.call(this);
|
||||
this.pluginMetadata = pluginMetadata;
|
||||
|
||||
this._srcIdFor = {}; // input path -> output data node path
|
||||
|
||||
this._nameFor = {}; // input path -> opname
|
||||
this._dataNameFor = {};
|
||||
this._opNames = {};
|
||||
|
||||
// topo sort stuff
|
||||
this._nextOps = {};
|
||||
this._incomingCnts = {};
|
||||
|
||||
this._operations = {};
|
||||
this.activeNodeId = null;
|
||||
this.activeNodeDepth = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Metadata associated with the plugin. Contains id, name, version, description, icon, configStructue etc.
|
||||
* This is also available at the instance at this.pluginMetadata.
|
||||
* @type {object}
|
||||
*/
|
||||
GenerateExecFile.metadata = pluginMetadata;
|
||||
|
||||
// Prototypical inheritance from PluginBase.
|
||||
GenerateExecFile.prototype = Object.create(PluginBase.prototype);
|
||||
GenerateExecFile.prototype.constructor = GenerateExecFile;
|
||||
|
||||
/**
|
||||
* Main function for the plugin to execute. This will perform the execution.
|
||||
* Notes:
|
||||
* - Always log with the provided logger.[error,warning,info,debug].
|
||||
* - Do NOT put any user interaction logic UI, etc. inside this method.
|
||||
* - callback always has to be called even if error happened.
|
||||
*
|
||||
* @param {function(string, plugin.PluginResult)} callback - the result callback
|
||||
*/
|
||||
GenerateExecFile.prototype.main = function (callback) {
|
||||
// Get all the children and call generate exec file
|
||||
this.activeNodeId = this.core.getPath(this.activeNode);
|
||||
this.activeNodeDepth = this.activeNodeId.split('/').length + 1;
|
||||
|
||||
if (this.isMetaTypeOf(this.activeNode, this.META.Execution)) {
|
||||
this.activeNodeDepth++;
|
||||
}
|
||||
|
||||
return this.core.loadChildren(this.activeNode)
|
||||
.then(nodes => this.createExecFile(nodes))
|
||||
.then(code => this.blobClient.putFile('init.lua', code))
|
||||
.then(hash => {
|
||||
this.result.addArtifact(hash);
|
||||
this.result.setSuccess(true);
|
||||
callback(null, this.result);
|
||||
})
|
||||
.fail(err => callback(err));
|
||||
};
|
||||
|
||||
GenerateExecFile.prototype.createExecFile = function (children) {
|
||||
// Convert opNodes' jobs to the nested operations
|
||||
var opNodes,
|
||||
nodes;
|
||||
|
||||
return this.unpackJobs(children)
|
||||
.then(_nodes => {
|
||||
nodes = _nodes;
|
||||
opNodes = nodes
|
||||
.filter(node => this.isMetaTypeOf(node, this.META.Operation));
|
||||
return Q.all(nodes.map(node => this.registerNameAndData(node)));
|
||||
})
|
||||
.then(() => Q.all(opNodes.map(node => this.createOperation(node))))
|
||||
.then(operations => {
|
||||
var nextIds = opNodes.map(n => this.core.getPath(n))
|
||||
.filter(id => !this._incomingCnts[id]);
|
||||
|
||||
operations.forEach(op => this._operations[op.id] = op);
|
||||
|
||||
// Toposort and concat!
|
||||
return this.combineOpNodes(nextIds);
|
||||
})
|
||||
.fail(err => this.logger.error(err));
|
||||
};
|
||||
|
||||
GenerateExecFile.prototype.unpackJobs = function (nodes) {
|
||||
return Q.all(
|
||||
nodes.map(node => {
|
||||
if (!this.isMetaTypeOf(node, this.META.Job)) {
|
||||
return node;
|
||||
}
|
||||
return this.core.loadChildren(node)
|
||||
.then(children =>
|
||||
children.find(c => this.isMetaTypeOf(c, this.META.Operation))
|
||||
);
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
GenerateExecFile.prototype.combineOpNodes = function (opIds) {
|
||||
var nextIds = [],
|
||||
dstIds,
|
||||
code,
|
||||
id;
|
||||
|
||||
// Combine all nodes with incoming cnts of 0
|
||||
code = opIds.map(id => this._operations[id].code).join('\n');
|
||||
|
||||
// Decrement all next ops
|
||||
dstIds = opIds.map(id => this._nextOps[id])
|
||||
.reduce((l1, l2) => l1.concat(l2), []);
|
||||
for (var i = dstIds.length; i--;) {
|
||||
id = dstIds[i];
|
||||
if (--this._incomingCnts[id] === 0) {
|
||||
nextIds.push(id);
|
||||
}
|
||||
}
|
||||
|
||||
// append
|
||||
return [
|
||||
code,
|
||||
nextIds.length ? this.combineOpNodes(nextIds) : ''
|
||||
].join('\n');
|
||||
};
|
||||
|
||||
GenerateExecFile.prototype.registerNameAndData = function (node) {
|
||||
var name = this.core.getAttribute(node, 'name'),
|
||||
id = this.core.getPath(node),
|
||||
basename = name,
|
||||
i = 2;
|
||||
|
||||
if (this.isMetaTypeOf(node, this.META.Operation)) {
|
||||
|
||||
// Get a unique operation name
|
||||
while (this._opNames[name]) {
|
||||
name = basename + '_' + i;
|
||||
i++;
|
||||
}
|
||||
|
||||
// register the unique name
|
||||
this._opNames[name] = true;
|
||||
this._nameFor[id] = name;
|
||||
|
||||
// For operations, register all output data node names by path
|
||||
return this.core.loadChildren(node)
|
||||
.then(cntrs => {
|
||||
var cntr = cntrs.find(n => this.isMetaTypeOf(n, this.META.Outputs));
|
||||
return this.core.loadChildren(cntr);
|
||||
})
|
||||
.then(outputs => {
|
||||
outputs.forEach(output => {
|
||||
var dataId = this.core.getPath(output);
|
||||
|
||||
name = this.core.getAttribute(output, 'name');
|
||||
this._dataNameFor[dataId] = name;
|
||||
});
|
||||
});
|
||||
|
||||
// For each input data node, register the associated output id
|
||||
} else if (this.isMetaTypeOf(node, this.META.Transporter)) {
|
||||
var outputData = this.core.getPointerPath(node, 'src'),
|
||||
inputData = this.core.getPointerPath(node, 'dst'),
|
||||
srcOpId = this.getOpIdFor(outputData),
|
||||
dstOpId = this.getOpIdFor(inputData);
|
||||
|
||||
this._srcIdFor[inputData] = outputData;
|
||||
|
||||
// Store the next operation ids for the op id
|
||||
if (!this._nextOps[srcOpId]) {
|
||||
this._nextOps[srcOpId] = [];
|
||||
}
|
||||
this._nextOps[srcOpId].push(dstOpId);
|
||||
|
||||
// Increment the incoming counts for each dst op
|
||||
this._incomingCnts[dstOpId] = this._incomingCnts[dstOpId] || 0;
|
||||
this._incomingCnts[dstOpId]++;
|
||||
}
|
||||
};
|
||||
|
||||
GenerateExecFile.prototype.getOpIdFor = function (dataId) {
|
||||
var ids = dataId.split('/'),
|
||||
depth = ids.length;
|
||||
|
||||
ids.splice(this.activeNodeDepth - depth);
|
||||
return ids.join('/');
|
||||
};
|
||||
|
||||
// For each operation...
|
||||
// - unpack the inputs from prev ops
|
||||
// - add the attributes table (if used)
|
||||
// - check for '\<attributes\>' in code
|
||||
// - add the references
|
||||
// - generate the code
|
||||
// - replace the `return <thing>` w/ `<ref-name> = <thing>`
|
||||
GenerateExecFile.prototype.createOperation = function (node) {
|
||||
var id = this.core.getPath(node),
|
||||
operation = {};
|
||||
|
||||
operation.name = this._nameFor[id];
|
||||
operation.id = id;
|
||||
operation.code = this.core.getAttribute(node, 'code');
|
||||
|
||||
// Update the 'code' attribute
|
||||
// Change the last return statement to assign the results to a table
|
||||
operation.code = this.assignResultToVar(operation.code,
|
||||
`${operation.name}_results`);
|
||||
|
||||
// Get all the input names (and sources)
|
||||
return this.core.loadChildren(node)
|
||||
.then(containers => {
|
||||
var inputs;
|
||||
|
||||
inputs = containers
|
||||
.find(cntr => this.isMetaTypeOf(cntr, this.META.Inputs));
|
||||
|
||||
this.logger.info(`${name} has ${containers.length} cntrs`);
|
||||
return this.core.loadChildren(inputs);
|
||||
})
|
||||
.then(data => {
|
||||
// Get the input names and sources
|
||||
var inputNames = data.map(d => this.core.getAttribute(d, 'name')),
|
||||
ids = data.map(d => this.core.getPath(d)),
|
||||
srcIds = ids.map(id => this._srcIdFor[id]);
|
||||
|
||||
operation.inputs = inputNames.map((name, i) => {
|
||||
var id = srcIds[i],
|
||||
srcDataName = this._dataNameFor[id],
|
||||
srcOpId = this.getOpIdFor(id),
|
||||
srcOpName = this._nameFor[srcOpId];
|
||||
|
||||
return `local ${name} = ${srcOpName}_results.${srcDataName}`;
|
||||
});
|
||||
|
||||
return operation;
|
||||
|
||||
})
|
||||
.then(operation => {
|
||||
|
||||
// For each reference, run the plugin and retrieve the generated code
|
||||
operation.refNames = this.core.getPointerNames(node)
|
||||
.filter(name => name !== 'base');
|
||||
|
||||
var refs = operation.refNames
|
||||
.map(ref => [ref, this.core.getPointerPath(node, ref)]);
|
||||
|
||||
return Q.all(
|
||||
refs.map(pair => this.genPtrSnippet.apply(this, pair))
|
||||
);
|
||||
})
|
||||
.then(codeFiles => {
|
||||
operation.refs = codeFiles;
|
||||
this.genOperationCode(operation);
|
||||
return operation;
|
||||
});
|
||||
};
|
||||
|
||||
GenerateExecFile.prototype.genPtrSnippet = function (ptrName, pId) {
|
||||
return this.getPtrCodeHash(pId)
|
||||
.then(hash => this.blobClient.getObjectAsString(hash))
|
||||
.then(code => this.createHeader(`creating ${ptrName}`, 40) + '\n' +
|
||||
this.assignResultToVar(code, ptrName));
|
||||
};
|
||||
|
||||
GenerateExecFile.prototype.createHeader = function (title, length) {
|
||||
var len;
|
||||
title = ` ${title} `;
|
||||
length = length || HEADER_LENGTH;
|
||||
|
||||
len = Math.max(
|
||||
Math.floor((length - title.length)/2),
|
||||
2
|
||||
);
|
||||
|
||||
return [
|
||||
'',
|
||||
title,
|
||||
''
|
||||
].join(new Array(len+1).join('-')) + '\n';
|
||||
|
||||
};
|
||||
|
||||
GenerateExecFile.prototype.genOperationCode = function (operation) {
|
||||
var header = this.createHeader(`"${operation.name}" Operation`),
|
||||
codeParts = [];
|
||||
|
||||
codeParts.push(header);
|
||||
|
||||
if (operation.inputs.length) {
|
||||
codeParts.push(operation.inputs.join('\n'));
|
||||
}
|
||||
|
||||
if (operation.refs.length) {
|
||||
codeParts.push(operation.refs.join('\n'));
|
||||
}
|
||||
|
||||
codeParts.push(operation.code);
|
||||
codeParts.push('');
|
||||
operation.code = codeParts.join('\n');
|
||||
return operation;
|
||||
};
|
||||
|
||||
GenerateExecFile.prototype.assignResultToVar = function (code, name) {
|
||||
var i = code.lastIndexOf('return');
|
||||
return code.substring(0, i) +
|
||||
code.substring(i)
|
||||
.replace('return', `local ${name} = `);
|
||||
};
|
||||
|
||||
_.extend(GenerateExecFile.prototype, PtrCodeGen.prototype);
|
||||
|
||||
return GenerateExecFile;
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"id": "GenerateExecFile",
|
||||
"name": "Generate Execution File",
|
||||
"version": "0.1.0",
|
||||
"description": "",
|
||||
"icon": {
|
||||
"class": "glyphicon glyphicon-cog",
|
||||
"src": ""
|
||||
},
|
||||
"disableServerSideExecution": false,
|
||||
"disableBrowserSideExecution": false,
|
||||
"writeAccessRequired": false,
|
||||
"configStructure": []
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*globals define*/
|
||||
/*jshint node:true, browser:true*/
|
||||
|
||||
/**
|
||||
* Generated by PluginGenerator 1.7.0 from webgme on Tue Jun 07 2016 11:25:09 GMT-0500 (CDT).
|
||||
* A plugin that inherits from the PluginBase. To see source code documentation about available
|
||||
* properties and methods visit %host%/docs/source/PluginBase.html.
|
||||
*/
|
||||
|
||||
define([
|
||||
'text!./metadata.json',
|
||||
'plugin/PluginBase',
|
||||
'q'
|
||||
], function (
|
||||
pluginMetadata,
|
||||
PluginBase,
|
||||
Q
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
pluginMetadata = JSON.parse(pluginMetadata);
|
||||
|
||||
/**
|
||||
* Initializes a new instance of ImportArtifact.
|
||||
* @class
|
||||
* @augments {PluginBase}
|
||||
* @classdesc This class represents the plugin ImportArtifact.
|
||||
* @constructor
|
||||
*/
|
||||
var ImportArtifact = function () {
|
||||
// Call base class' constructor.
|
||||
PluginBase.call(this);
|
||||
this.pluginMetadata = pluginMetadata;
|
||||
};
|
||||
|
||||
/**
|
||||
* Metadata associated with the plugin. Contains id, name, version, description, icon, configStructue etc.
|
||||
* This is also available at the instance at this.pluginMetadata.
|
||||
* @type {object}
|
||||
*/
|
||||
ImportArtifact.metadata = pluginMetadata;
|
||||
|
||||
// Prototypical inheritance from PluginBase.
|
||||
ImportArtifact.prototype = Object.create(PluginBase.prototype);
|
||||
ImportArtifact.prototype.constructor = ImportArtifact;
|
||||
|
||||
/**
|
||||
* Main function for the plugin to execute. This will perform the execution.
|
||||
* Notes:
|
||||
* - Always log with the provided logger.[error,warning,info,debug].
|
||||
* - Do NOT put any user interaction logic UI, etc. inside this method.
|
||||
* - callback always has to be called even if error happened.
|
||||
*
|
||||
* @param {function(string, plugin.PluginResult)} callback - the result callback
|
||||
*/
|
||||
ImportArtifact.prototype.main = function (callback) {
|
||||
var self = this,
|
||||
config = this.getCurrentConfig(),
|
||||
hash = config.dataHash,
|
||||
baseName = config.dataTypeId,
|
||||
name,
|
||||
baseType,
|
||||
dataNode,
|
||||
|
||||
metaDict,
|
||||
metanodes;
|
||||
|
||||
// Create node of type "typeId" in the activeNode and set the hash, name
|
||||
metaDict = this.core.getAllMetaNodes(this.activeNode);
|
||||
metanodes = Object.keys(metaDict).map(id => metaDict[id]);
|
||||
baseType = metanodes.find(node =>
|
||||
this.core.getAttribute(node, 'name') === baseName
|
||||
);
|
||||
|
||||
if (!baseType) {
|
||||
callback(`Could not find data type "${baseName}"`, this.result);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the base node
|
||||
dataNode = this.core.createNode({
|
||||
base: baseType,
|
||||
parent: this.activeNode
|
||||
});
|
||||
|
||||
this.core.setAttribute(dataNode, 'data', hash);
|
||||
baseName = this.core.getAttribute(baseType, 'name');
|
||||
|
||||
var getName;
|
||||
if (config.name) {
|
||||
getName = Q().then(() => config.name);
|
||||
} else {
|
||||
getName = this.blobClient.getMetadata(hash)
|
||||
.then(md => {
|
||||
name = baseName[0].toLowerCase() + baseName.substring(1);
|
||||
if (md) {
|
||||
name = md.name.replace(/\.[^\.]*?$/, '');
|
||||
}
|
||||
return name;
|
||||
});
|
||||
}
|
||||
|
||||
getName.then(name => this.core.setAttribute(dataNode, 'name', name))
|
||||
.then(() => this.save(`Uploaded "${name}" data`))
|
||||
.then(function () {
|
||||
self.result.setSuccess(true);
|
||||
callback(null, self.result);
|
||||
})
|
||||
.fail(function (err) {
|
||||
callback(err, self.result);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
return ImportArtifact;
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"id": "ImportArtifact",
|
||||
"name": "ImportArtifact",
|
||||
"version": "0.1.0",
|
||||
"description": "",
|
||||
"icon": {
|
||||
"class": "glyphicon glyphicon-cog",
|
||||
"src": ""
|
||||
},
|
||||
"disableServerSideExecution": false,
|
||||
"disableBrowserSideExecution": false,
|
||||
"writeAccessRequired": true,
|
||||
"configStructure": [
|
||||
{
|
||||
"name": "name",
|
||||
"displayName": "Data name",
|
||||
"description": "Optional name for artifact",
|
||||
"value": "",
|
||||
"valueType": "string",
|
||||
"readOnly": false
|
||||
},
|
||||
{
|
||||
"name": "dataHash",
|
||||
"displayName": "Data to upload",
|
||||
"description": "",
|
||||
"value": "",
|
||||
"valueType": "asset",
|
||||
"readOnly": false
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:542fe611b9b0ec4af6fd8670a99511b356a68c0617c28b5a0922754c1fd9f7ac
|
||||
size 376944
|
||||
oid sha256:bcba8f6c56406f1d507e189200599dee8fa3810f716fa4673453f907087040b3
|
||||
size 639462
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b629fb57c876f346d10db920212c49aecaf2be1ab951bad9dcb645c7bf03e070
|
||||
size 346658
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ecabf81f5155b7b4c7255c2a1f77df95646884182c9e7e58611e3886016a7bed
|
||||
size 58424
|
||||
oid sha256:bf9e6d1c7b96fe80292203dcc084d50e3a730679a523a8b51028cc0c8fd4c1a4
|
||||
size 61790
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bcb09f0e67a5840a0579fa44353602b20a4203452c00b59796ce9bc2026666d2
|
||||
size 343292
|
||||
oid sha256:969c0d2d00b15217ee5af40f55db4d478229f35cc7184239fc8251714a8bf9c1
|
||||
size 354516
|
||||
|
||||
@@ -82,5 +82,11 @@
|
||||
"title": "DeserializeEditor",
|
||||
"panel": "panels/DeserializeEditor/DeserializeEditorPanel",
|
||||
"DEBUG_ONLY": false
|
||||
},
|
||||
{
|
||||
"id": "Footer",
|
||||
"title": "Footer",
|
||||
"panel": "panels/Footer/FooterPanel",
|
||||
"DEBUG_ONLY": false
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,83 @@
|
||||
/*globals define, _, WebGMEGlobal, $ */
|
||||
/*jshint browser: true*/
|
||||
/**
|
||||
* @author rkereskenyi / https://github.com/rkereskenyi
|
||||
*/
|
||||
|
||||
define([
|
||||
'js/PanelBase/PanelBase',
|
||||
'js/Widgets/NetworkStatus/NetworkStatusWidget',
|
||||
'js/Widgets/BranchStatus/BranchStatusWidget',
|
||||
'js/Widgets/BranchSelector/BranchSelectorWidget',
|
||||
'js/Widgets/KeyboardManager/KeyboardManagerWidget',
|
||||
'js/Widgets/Notification/NotificationWidget'
|
||||
], function (PanelBase,
|
||||
NetworkStatusWidget,
|
||||
BranchStatusWidget,
|
||||
BranchSelectorWidget,
|
||||
KeyboardManagerWidget,
|
||||
NotificationWidget) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var FooterPanel,
|
||||
__parent__ = PanelBase;
|
||||
|
||||
FooterPanel = function (layoutManager, params) {
|
||||
var options = {};
|
||||
//set properties from options
|
||||
options[PanelBase.OPTIONS.LOGGER_INSTANCE_NAME] = 'FooterPanel';
|
||||
|
||||
//call parent's constructor
|
||||
__parent__.apply(this, [options]);
|
||||
|
||||
this._client = params.client;
|
||||
|
||||
//initialize UI
|
||||
this._initialize();
|
||||
|
||||
this.logger.debug('FooterPanel ctor finished');
|
||||
};
|
||||
|
||||
//inherit from PanelBaseWithHeader
|
||||
_.extend(FooterPanel.prototype, __parent__.prototype);
|
||||
|
||||
FooterPanel.prototype._initialize = function () {
|
||||
//main container
|
||||
var navBar = $('<div/>', {class: 'navbar navbar-inverse navbar-fixed-bottom'}),
|
||||
navBarInner = $('<div/>', {class: 'navbar-inner'}),
|
||||
separator = $('<div class="spacer pull-right"></div>'),
|
||||
widgetPlaceHolder = $('<div class="pull-right"></div>'),
|
||||
keyBoardManagerEl,
|
||||
networkStatusEl,
|
||||
branchStatusEl,
|
||||
notificationEl;
|
||||
|
||||
navBar.append(navBarInner);
|
||||
this.$el.append(navBar);
|
||||
|
||||
//padding from screen right edge
|
||||
navBarInner.append(separator.clone());
|
||||
|
||||
//keyboard enable/disbale widget (NOTE: only on non touch device)
|
||||
if (WebGMEGlobal.SUPPORTS_TOUCH !== true) {
|
||||
keyBoardManagerEl = widgetPlaceHolder.clone();
|
||||
new KeyboardManagerWidget(keyBoardManagerEl);
|
||||
navBarInner.append(keyBoardManagerEl).append(separator.clone());
|
||||
}
|
||||
|
||||
networkStatusEl = widgetPlaceHolder.clone();
|
||||
new NetworkStatusWidget(networkStatusEl, this._client);
|
||||
navBarInner.append(networkStatusEl).append(separator.clone());
|
||||
|
||||
notificationEl = widgetPlaceHolder.clone();
|
||||
new NotificationWidget(notificationEl, this._client);
|
||||
navBarInner.append(notificationEl).append(separator.clone());
|
||||
|
||||
branchStatusEl = widgetPlaceHolder.clone();
|
||||
new BranchStatusWidget(branchStatusEl, this._client);
|
||||
navBarInner.append(branchStatusEl).append(separator.clone());
|
||||
};
|
||||
|
||||
return FooterPanel;
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
/*globals define, WebGMEGlobal*/
|
||||
/*globals define, Materialize, WebGMEGlobal*/
|
||||
// These are actions defined for specific meta types. They are evaluated from
|
||||
// the context of the ForgeActionButton
|
||||
define([
|
||||
@@ -126,15 +126,62 @@ define([
|
||||
return null;
|
||||
};
|
||||
|
||||
return {
|
||||
Data: [
|
||||
{
|
||||
name: 'Download',
|
||||
icon: 'play_for_work',
|
||||
href: downloadButton // function to create href url
|
||||
}
|
||||
],
|
||||
var UPLOAD_PLUGIN = 'ImportArtifact',
|
||||
DATA_TYPE_CONFIG = {
|
||||
name: 'dataTypeId',
|
||||
displayName: 'Data Type Id',
|
||||
valueType: 'string',
|
||||
valueItems: []
|
||||
};
|
||||
var uploadArtifact = function() {
|
||||
// Get the data types
|
||||
var dataBase,
|
||||
dataBaseId,
|
||||
metanodes = this.client.getAllMetaNodes(),
|
||||
dataTypes = []; // TODO
|
||||
|
||||
dataBase = metanodes.find(n => n.getAttribute('name') === 'Data');
|
||||
|
||||
if (!dataBase) {
|
||||
this.logger.error('Could not find the base Data node!');
|
||||
return;
|
||||
}
|
||||
|
||||
dataBaseId = dataBase.getId();
|
||||
dataTypes = metanodes.filter(n => this.client.isTypeOf(n.getId(), dataBaseId))
|
||||
.map(node => node.getAttribute('name'));
|
||||
|
||||
this.logger.info(`Found ${dataTypes.length} data types`);
|
||||
|
||||
// Add the target type to the pluginMetadata... hacky :/
|
||||
// FIXME: this should create it's own plugin dialog which allows
|
||||
// users to select the data type
|
||||
var metadata = WebGMEGlobal.allPluginsMetadata[UPLOAD_PLUGIN],
|
||||
config = metadata.configStructure
|
||||
.find(opt => opt.name === DATA_TYPE_CONFIG.name);
|
||||
|
||||
if (!config) {
|
||||
config = DATA_TYPE_CONFIG;
|
||||
WebGMEGlobal.allPluginsMetadata[UPLOAD_PLUGIN].configStructure.push(config);
|
||||
}
|
||||
|
||||
config.valueItems = dataTypes;
|
||||
config.value = dataTypes[0];
|
||||
|
||||
WebGMEGlobal.InterpreterManager.configureAndRun(metadata, (result) => {
|
||||
if (!result) {
|
||||
Materialize.toast('Artifact upload failed!');
|
||||
return;
|
||||
}
|
||||
this.logger.info('Finished uploading ' + UPLOAD_PLUGIN);
|
||||
Materialize.toast('Artifact upload complete!');
|
||||
});
|
||||
};
|
||||
|
||||
var returnToLastPipeline = () =>
|
||||
WebGMEGlobal.State.registerActiveObject(window.DeepForge.lastPipeline);
|
||||
return {
|
||||
// Meta nodes
|
||||
MyPipelines_META: [
|
||||
{
|
||||
name: 'Create new pipeline',
|
||||
@@ -163,6 +210,30 @@ define([
|
||||
action: create.Operation
|
||||
}
|
||||
],
|
||||
MyArtifacts_META: [
|
||||
{
|
||||
name: 'Upload artifact',
|
||||
icon: 'swap_vert',
|
||||
action: uploadArtifact
|
||||
}
|
||||
],
|
||||
Operation_META: [
|
||||
{
|
||||
name: 'Return to Pipeline',
|
||||
icon: 'input',
|
||||
filter: () => window.DeepForge && window.DeepForge.lastPipeline,
|
||||
action: returnToLastPipeline
|
||||
}
|
||||
],
|
||||
|
||||
// Instances
|
||||
Data: [
|
||||
{
|
||||
name: 'Download',
|
||||
icon: 'play_for_work',
|
||||
href: downloadButton // function to create href url
|
||||
}
|
||||
],
|
||||
Pipeline: [
|
||||
{
|
||||
name: 'Create new node',
|
||||
|
||||
@@ -37,14 +37,19 @@ define([
|
||||
base = this.client.getNode(node.getMetaTypeId()),
|
||||
isMeta = base && base.getId() === node.getId(),
|
||||
suffix = isMeta ? '_META' : '',
|
||||
actions,
|
||||
basename;
|
||||
|
||||
while (base && !ACTIONS[basename]) {
|
||||
while (base && !(actions && actions.length)) {
|
||||
basename = base.getAttribute('name') + suffix;
|
||||
base = this.client.getNode(base.getBaseId());
|
||||
actions = ACTIONS[basename];
|
||||
if (actions) {
|
||||
actions = actions.filter(action => !action.filter || action.filter());
|
||||
}
|
||||
}
|
||||
|
||||
return ACTIONS[basename] || [];
|
||||
return actions || [];
|
||||
};
|
||||
|
||||
ForgeActionButton.prototype.onNodeLoad = function(nodeId) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
/*jshint browser: true*/
|
||||
|
||||
define([
|
||||
'js/Constants',
|
||||
'panels/EasyDAG/EasyDAGControl',
|
||||
'deepforge/viz/PipelineControl',
|
||||
'common/core/coreQ',
|
||||
@@ -9,6 +10,7 @@ define([
|
||||
'q',
|
||||
'underscore'
|
||||
], function (
|
||||
CONSTANTS,
|
||||
EasyDAGControl,
|
||||
PipelineControl,
|
||||
Core,
|
||||
@@ -23,7 +25,11 @@ define([
|
||||
CONN = {
|
||||
SRC: 'src',
|
||||
DST: 'dst'
|
||||
};
|
||||
},
|
||||
DECORATORS = {
|
||||
ArtifactLoader: 'DcOpDecorator'
|
||||
},
|
||||
WIDGET_NAME = 'EasyDAG';
|
||||
|
||||
PipelineEditorControl = function (options) {
|
||||
EasyDAGControl.call(this, options);
|
||||
@@ -94,6 +100,11 @@ define([
|
||||
// Add a rule for them
|
||||
.forEach(opId => this._territories[opId] = this.TERRITORY_RULE);
|
||||
|
||||
// Add arch/artifact dir to the territory
|
||||
// loading more than necessary.... can restrict it in the future
|
||||
// if perf is a problem
|
||||
this._territories[CONSTANTS.PROJECT_ROOT_ID] = {children: 2};
|
||||
|
||||
this._client.updateTerritory(this._territoryId, this._territories);
|
||||
};
|
||||
|
||||
@@ -116,7 +127,8 @@ define([
|
||||
if (desc.parentId === this._currentNodeId) {
|
||||
this.addedIds[desc.id] = true;
|
||||
return EasyDAGControl.prototype._onLoad.call(this, gmeId);
|
||||
} else if (this.isContainedInActive(desc.parentId) && desc.isDataPort) {
|
||||
} else if (desc.parentId !== null &&
|
||||
this.isContainedInActive(desc.parentId) && desc.isDataPort) {
|
||||
// port added!
|
||||
this.addedIds[desc.id] = true;
|
||||
this._widget.addPort(desc);
|
||||
@@ -142,6 +154,19 @@ define([
|
||||
} // Ignore any other updates - ie, Inputs/Outputs containers
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype._getNodeDecorator = function (nodeObj) {
|
||||
var decoratorManager = this._client.decoratorManager,
|
||||
decorator,
|
||||
decoratorClass;
|
||||
|
||||
var base = this._client.getNode(nodeObj.getMetaTypeId()),
|
||||
baseName = base && base.getAttribute('name');
|
||||
|
||||
decorator = DECORATORS[baseName] || this.DEFAULT_DECORATOR;
|
||||
decoratorClass = decoratorManager.getDecoratorForWidget(decorator, WIDGET_NAME);
|
||||
return decoratorClass;
|
||||
};
|
||||
|
||||
// Override the getSuccessors method to look up successors by operations
|
||||
// with input nodes of the selected node's output type (prioritize the
|
||||
// valid nodes that are using an unused output type, if one exists, ow
|
||||
@@ -418,5 +443,27 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype._getTargetDirs = function (typeIds) {
|
||||
// Find the directories containing these types
|
||||
return this._client.getNode(CONSTANTS.PROJECT_ROOT_ID).getChildrenIds()
|
||||
// No referencing data meta types
|
||||
.filter(id => {
|
||||
var cMeta = this._client.getChildrenMeta(id),
|
||||
validChildIds;
|
||||
|
||||
if (!cMeta) {
|
||||
return false;
|
||||
}
|
||||
|
||||
validChildIds = cMeta.items.map(item => item.id);
|
||||
for (var i = typeIds.length; i--;) {
|
||||
if (validChildIds.indexOf(typeIds[i]) !== -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
return PipelineEditorControl;
|
||||
});
|
||||
|
||||
@@ -113,10 +113,25 @@ define([
|
||||
|
||||
};
|
||||
|
||||
var Delete = function(params) {
|
||||
EasyDAGButtons.DeleteOne.call(this, params);
|
||||
};
|
||||
|
||||
_.extend(Delete.prototype, EasyDAGButtons.DeleteOne.prototype);
|
||||
|
||||
Delete.prototype._onClick = function(item) {
|
||||
// Check if it is a pointer or
|
||||
if (item.desc.isPointer) {
|
||||
this.removePtr(item.name);
|
||||
} else {
|
||||
this.deleteNode(item.id);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
AddOutput: AddOutput,
|
||||
AddInput: AddInput,
|
||||
AddRef: AddRef,
|
||||
Delete: EasyDAGButtons.Delete
|
||||
Delete: Delete
|
||||
};
|
||||
});
|
||||
|
||||
@@ -91,13 +91,5 @@ define([
|
||||
this.addRefTo(target.node.id);
|
||||
};
|
||||
|
||||
OperationInterfaceEditorWidget.prototype.removeItem = function(item) {
|
||||
if (item.desc.isPointer) {
|
||||
this.removePtr(item.name);
|
||||
} else {
|
||||
this.removeSubtreeAt(item.id);
|
||||
}
|
||||
};
|
||||
|
||||
return OperationInterfaceEditorWidget;
|
||||
});
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*globals define, WebGMEGlobal*/
|
||||
define([
|
||||
'widgets/EasyDAG/Buttons'
|
||||
], function(
|
||||
EasyDAGButtons
|
||||
) {
|
||||
|
||||
// Create a GoToBase button
|
||||
var client = WebGMEGlobal.Client,
|
||||
LocalOps = {
|
||||
ArtifactLoader: true,
|
||||
Save: true
|
||||
};
|
||||
|
||||
var GoToBase = function(params) {
|
||||
// Check if it should be disabled
|
||||
var baseId = this._getBaseId(params.item),
|
||||
base = client.getNode(baseId);
|
||||
|
||||
params.disabled = base ? base.isLibraryElement() : false;
|
||||
EasyDAGButtons.ButtonBase.call(this, params);
|
||||
};
|
||||
|
||||
GoToBase.SIZE = 10;
|
||||
GoToBase.BORDER = 5;
|
||||
GoToBase.prototype.BTN_CLASS = 'add';
|
||||
GoToBase.prototype = new EasyDAGButtons.ButtonBase();
|
||||
|
||||
GoToBase.prototype._render = function() {
|
||||
var lineRadius = GoToBase.SIZE - GoToBase.BORDER,
|
||||
btnColor = '#90caf9',
|
||||
lineColor = '#7986cb';
|
||||
|
||||
if (this.disabled) {
|
||||
btnColor = '#e0e0e0';
|
||||
lineColor = '#9e9e9e';
|
||||
}
|
||||
|
||||
this.$el
|
||||
.append('circle')
|
||||
.attr('r', GoToBase.SIZE)
|
||||
.attr('fill', btnColor);
|
||||
|
||||
this.$el
|
||||
.append('circle')
|
||||
//.attr('cx', -)
|
||||
//.attr('cy', 0)
|
||||
.attr('r', GoToBase.SIZE/3)
|
||||
.attr('stroke-width', 3)
|
||||
.attr('stroke', lineColor);
|
||||
|
||||
this.$el
|
||||
.append('line')
|
||||
.attr('y1', 0)
|
||||
.attr('y2', 0)
|
||||
.attr('x1', -lineRadius)
|
||||
.attr('x2', lineRadius)
|
||||
.attr('stroke-width', 3)
|
||||
.attr('stroke', lineColor);
|
||||
|
||||
};
|
||||
|
||||
GoToBase.prototype._onClick = function(item) {
|
||||
var node = client.getNode(item.id),
|
||||
baseId = node.getBaseId();
|
||||
|
||||
window.DeepForge = window.DeepForge || {};
|
||||
window.DeepForge.lastPipeline = item.desc.parentId;
|
||||
|
||||
WebGMEGlobal.State.registerActiveObject(baseId);
|
||||
};
|
||||
|
||||
GoToBase.prototype._getBaseId = function(item) {
|
||||
var n = client.getNode(item.id);
|
||||
return n.getBaseId();
|
||||
};
|
||||
|
||||
return {
|
||||
DeleteOne: EasyDAGButtons.DeleteOne,
|
||||
GoToBase: GoToBase
|
||||
};
|
||||
});
|
||||
@@ -60,6 +60,20 @@ define([
|
||||
this._visiblePorts = null;
|
||||
};
|
||||
|
||||
OperationNode.prototype.removePort = function(id) {
|
||||
// Find the given port and remove it
|
||||
[this.inputs, this.outputs] // Look for the port in both lists
|
||||
.forEach(ports => {
|
||||
var port = ports.find(p => p.id === id),
|
||||
i;
|
||||
|
||||
if (port) {
|
||||
i = ports.indexOf(port);
|
||||
ports.splice(i, 1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
OperationNode.prototype.updatePort = function(/*desc*/) {
|
||||
// TODO
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
define([
|
||||
'widgets/EasyDAG/SelectionManager',
|
||||
'widgets/EasyDAG/Buttons',
|
||||
'./Buttons',
|
||||
'underscore'
|
||||
], function(
|
||||
EasyDAGSelectionManager,
|
||||
@@ -17,7 +17,7 @@ define([
|
||||
|
||||
_.extend(SelectionManager.prototype, EasyDAGSelectionManager.prototype);
|
||||
|
||||
SelectionManager.prototype.createActionButtons = function(/*width, height*/) {
|
||||
SelectionManager.prototype.createActionButtons = function(width/*, height*/) {
|
||||
// move the 'x' to the top left
|
||||
new Buttons.DeleteOne({
|
||||
context: this._widget,
|
||||
@@ -26,6 +26,15 @@ define([
|
||||
x: 0,
|
||||
y: 0
|
||||
});
|
||||
// If the operation has a user-defined base type,
|
||||
// show a button for jumping to the base def
|
||||
new Buttons.GoToBase({
|
||||
context: this._widget,
|
||||
$pEl: this.$selection,
|
||||
item: this.selectedItem,
|
||||
x: width,
|
||||
y: 0
|
||||
});
|
||||
};
|
||||
|
||||
SelectionManager.prototype.deselect = function() {
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
<div class="col s2 m4">
|
||||
<div class="card blue lighten-2">
|
||||
<div class="col s2 m4" id="card-node<%= htmlId %>" data-rank="<%= rank %>">
|
||||
<div class="card <%= color %> <%= shade %>">
|
||||
<div class="card-content">
|
||||
<% if (typeof icon !== 'undefined') {%>
|
||||
<div><i class="large material-icons"><%=icon%></i></div>
|
||||
<%}%>
|
||||
<span class="card-title"><%= title %></span>
|
||||
<div
|
||||
<p><%= description %></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -30,6 +30,10 @@ define([
|
||||
|
||||
// Load the component settings
|
||||
this._config = {
|
||||
defaults: {
|
||||
color: 'blue',
|
||||
shade: 'lighten-2'
|
||||
},
|
||||
nodes:[]
|
||||
};
|
||||
ComponentSettings.resolveWithWebGMEGlobal(this._config, this.getComponentId());
|
||||
@@ -69,7 +73,7 @@ define([
|
||||
node = this.validNodes[desc[attr]];
|
||||
|
||||
if (node) {
|
||||
_.extend(desc, node);
|
||||
_.extend(desc, this._config.defaults, node);
|
||||
desc.title = desc.title || desc.name;
|
||||
this.addPanel(desc);
|
||||
}
|
||||
@@ -77,15 +81,40 @@ define([
|
||||
};
|
||||
|
||||
RootVizWidget.prototype.addPanel = function (desc) {
|
||||
var html = $(NodeTpl(desc));
|
||||
var html;
|
||||
|
||||
// Create the html from template
|
||||
if (this.nodes[desc.id]) {
|
||||
if (this.nodes[desc.id]) { // refresh, if already exists
|
||||
this.removeNode(desc.id);
|
||||
}
|
||||
|
||||
// Create the html from template
|
||||
this.$container.append(html);
|
||||
desc.htmlId = desc.id.replace('/', '-');
|
||||
html = $(NodeTpl(desc));
|
||||
|
||||
// Find the child just before the given one
|
||||
var children = this.$container.children(),
|
||||
rank = -Infinity,
|
||||
id;
|
||||
|
||||
desc.rank = +desc.rank;
|
||||
if (children.length) { // Add it in order
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
rank = +children[i].getAttribute('data-rank');
|
||||
if (rank > desc.rank) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < children.length) {
|
||||
id = children[i].getAttribute('id');
|
||||
this.$container.find('#' + id).before(html);
|
||||
} else {
|
||||
this.$container.append(html);
|
||||
}
|
||||
} else {
|
||||
this.$container.append(html);
|
||||
}
|
||||
|
||||
html.on('click', () => {
|
||||
this.onNodeClick(desc.id);
|
||||
event.stopPropagation();
|
||||
|
||||
@@ -24,8 +24,11 @@ define([
|
||||
this._el = container;
|
||||
this._el.css({height: '100%'});
|
||||
this.editor = ace.edit(this._el[0]);
|
||||
this.editor.getSession().setMode('ace/mode/lua');
|
||||
|
||||
this.editor.getSession().setOptions({
|
||||
mode: 'ace/mode/lua',
|
||||
tabSize: 3,
|
||||
useSoftTabs: true
|
||||
});
|
||||
// Get the config from component settings for themes
|
||||
// TODO
|
||||
this.editor.setOptions({
|
||||
|
||||
@@ -87,10 +87,9 @@ describe('GenerateArchitecture', function () {
|
||||
var cases = [
|
||||
['/4', 'basic.lua'],
|
||||
['/T', 'basic-transfers.lua'],
|
||||
['/t', 'concat-parallel.lua'],
|
||||
['/w', 'googlenet.lua'],
|
||||
['/W', 'overfeat.lua']
|
||||
// TODO: Add more tests
|
||||
// Need a concat test
|
||||
// TODO
|
||||
];
|
||||
|
||||
var runTest = function(pair, done) {
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*jshint node:true, mocha:true*/
|
||||
/**
|
||||
* Generated by PluginGenerator 1.7.0 from webgme on Sat Jun 04 2016 18:01:54 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
var testFixture = require('../../globals');
|
||||
|
||||
describe.skip('GenerateExecFile', function () {
|
||||
var gmeConfig = testFixture.getGmeConfig(),
|
||||
expect = testFixture.expect,
|
||||
logger = testFixture.logger.fork('GenerateExecFile'),
|
||||
PluginCliManager = testFixture.WebGME.PluginCliManager,
|
||||
projectName = 'testProject',
|
||||
pluginName = 'GenerateExecFile',
|
||||
project,
|
||||
gmeAuth,
|
||||
storage,
|
||||
commitHash;
|
||||
|
||||
before(function (done) {
|
||||
testFixture.clearDBAndGetGMEAuth(gmeConfig, projectName)
|
||||
.then(function (gmeAuth_) {
|
||||
gmeAuth = gmeAuth_;
|
||||
// This uses in memory storage. Use testFixture.getMongoStorage to persist test to database.
|
||||
storage = testFixture.getMemoryStorage(logger, gmeConfig, gmeAuth);
|
||||
return storage.openDatabase();
|
||||
})
|
||||
.then(function () {
|
||||
var importParam = {
|
||||
projectSeed: testFixture.path.join(testFixture.SEED_DIR, 'EmptyProject.webgmex'),
|
||||
projectName: projectName,
|
||||
branchName: 'master',
|
||||
logger: logger,
|
||||
gmeConfig: gmeConfig
|
||||
};
|
||||
|
||||
return testFixture.importProject(storage, importParam);
|
||||
})
|
||||
.then(function (importResult) {
|
||||
project = importResult.project;
|
||||
commitHash = importResult.commitHash;
|
||||
return project.createBranch('test', commitHash);
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
storage.closeDatabase()
|
||||
.then(function () {
|
||||
return gmeAuth.unload();
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
it('should run plugin and update the branch', function (done) {
|
||||
var manager = new PluginCliManager(null, logger, gmeConfig),
|
||||
pluginConfig = {
|
||||
},
|
||||
context = {
|
||||
project: project,
|
||||
commitHash: commitHash,
|
||||
branchName: 'test',
|
||||
activeNode: '/960660211',
|
||||
};
|
||||
|
||||
manager.executePlugin(pluginName, pluginConfig, context, function (err, pluginResult) {
|
||||
expect(err).to.equal(null);
|
||||
expect(typeof pluginResult).to.equal('object');
|
||||
expect(pluginResult.success).to.equal(true);
|
||||
|
||||
project.getBranchHash('test')
|
||||
.then(function (branchHash) {
|
||||
expect(branchHash).to.not.equal(commitHash);
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,79 @@
|
||||
/*jshint node:true, mocha:true*/
|
||||
/**
|
||||
* Generated by PluginGenerator 1.7.0 from webgme on Tue Jun 07 2016 11:25:09 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
var testFixture = require('../../globals');
|
||||
|
||||
describe.skip('ImportArtifact', function () {
|
||||
var gmeConfig = testFixture.getGmeConfig(),
|
||||
expect = testFixture.expect,
|
||||
logger = testFixture.logger.fork('ImportArtifact'),
|
||||
PluginCliManager = testFixture.WebGME.PluginCliManager,
|
||||
projectName = 'testProject',
|
||||
pluginName = 'ImportArtifact',
|
||||
project,
|
||||
gmeAuth,
|
||||
storage,
|
||||
commitHash;
|
||||
|
||||
before(function (done) {
|
||||
testFixture.clearDBAndGetGMEAuth(gmeConfig, projectName)
|
||||
.then(function (gmeAuth_) {
|
||||
gmeAuth = gmeAuth_;
|
||||
// This uses in memory storage. Use testFixture.getMongoStorage to persist test to database.
|
||||
storage = testFixture.getMemoryStorage(logger, gmeConfig, gmeAuth);
|
||||
return storage.openDatabase();
|
||||
})
|
||||
.then(function () {
|
||||
var importParam = {
|
||||
projectSeed: testFixture.path.join(testFixture.SEED_DIR, 'EmptyProject.webgmex'),
|
||||
projectName: projectName,
|
||||
branchName: 'master',
|
||||
logger: logger,
|
||||
gmeConfig: gmeConfig
|
||||
};
|
||||
|
||||
return testFixture.importProject(storage, importParam);
|
||||
})
|
||||
.then(function (importResult) {
|
||||
project = importResult.project;
|
||||
commitHash = importResult.commitHash;
|
||||
return project.createBranch('test', commitHash);
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
storage.closeDatabase()
|
||||
.then(function () {
|
||||
return gmeAuth.unload();
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
it('should run plugin and update the branch', function (done) {
|
||||
var manager = new PluginCliManager(null, logger, gmeConfig),
|
||||
pluginConfig = {
|
||||
},
|
||||
context = {
|
||||
project: project,
|
||||
commitHash: commitHash,
|
||||
branchName: 'test',
|
||||
activeNode: '/960660211',
|
||||
};
|
||||
|
||||
manager.executePlugin(pluginName, pluginConfig, context, function (err, pluginResult) {
|
||||
expect(err).to.equal(null);
|
||||
expect(typeof pluginResult).to.equal('object');
|
||||
expect(pluginResult.success).to.equal(true);
|
||||
|
||||
project.getBranchHash('test')
|
||||
.then(function (branchHash) {
|
||||
expect(branchHash).to.not.equal(commitHash);
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
require 'nn'
|
||||
|
||||
local net = nn.Sequential()
|
||||
net:add(nn.Reshape(100))
|
||||
|
||||
local net_2 = nn.Sequential()
|
||||
net_2:add(nn.Linear(100, 150))
|
||||
net_2:add(nn.Tanh())
|
||||
net_2:add(nn.Linear(150, 50))
|
||||
|
||||
local net_3 = nn.Sequential()
|
||||
net_3:add(nn.Linear(100, 150))
|
||||
net_3:add(nn.Tanh())
|
||||
net_3:add(nn.Linear(150, 30))
|
||||
|
||||
local concat_7 = nn.Concat(1)
|
||||
concat_7:add(net_3)
|
||||
concat_7:add(net_2)
|
||||
|
||||
net:add(concat_7)
|
||||
net:add(nn.Tanh())
|
||||
net:add(nn.Linear(80, 7))
|
||||
|
||||
return net
|
||||
@@ -0,0 +1,341 @@
|
||||
require 'nn'
|
||||
|
||||
local net = nn.Sequential()
|
||||
net:add(nn.SpatialConvolution(3, 64, 7, 7, 2, 2))
|
||||
net:add(nn.ReLU())
|
||||
net:add(nn.SpatialMaxPooling(3, 3, 2, 2))
|
||||
net:add(nn.SpatialConvolution(64, 64, 1, 1, 1, 1))
|
||||
net:add(nn.ReLU())
|
||||
net:add(nn.SpatialConvolution(64, 192, 3, 3, 1, 1))
|
||||
net:add(nn.ReLU())
|
||||
net:add(nn.SpatialMaxPooling(3, 3, 2, 2))
|
||||
|
||||
local net_2 = nn.Sequential()
|
||||
net_2:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_2:add(nn.SpatialAveragePooling(3, 3, 1, 1))
|
||||
net_2:add(nn.SpatialConvolution(192, 32, 1, 1, 1, 1))
|
||||
net_2:add(nn.ReLU())
|
||||
|
||||
local net_3 = nn.Sequential()
|
||||
net_3:add(nn.SpatialConvolution(192, 64, 1, 1, 1, 1))
|
||||
net_3:add(nn.ReLU())
|
||||
|
||||
local net_4 = nn.Sequential()
|
||||
net_4:add(nn.SpatialConvolution(192, 64, 1, 1, 1, 1))
|
||||
net_4:add(nn.ReLU())
|
||||
net_4:add(nn.SpatialConvolution(64, 64, 3, 3, 1, 1))
|
||||
net_4:add(nn.ReLU())
|
||||
|
||||
local net_5 = nn.Sequential()
|
||||
net_5:add(nn.SpatialConvolution(192, 64, 1, 1, 1, 1))
|
||||
net_5:add(nn.ReLU())
|
||||
net_5:add(nn.SpatialConvolution(64, 96, 3, 3, 1, 1))
|
||||
net_5:add(nn.ReLU())
|
||||
net_5:add(nn.SpatialConvolution(96, 96, 3, 3, 1, 1))
|
||||
net_5:add(nn.ReLU())
|
||||
|
||||
local concat_24 = nn.Concat(2)
|
||||
concat_24:add(net_5)
|
||||
concat_24:add(net_4)
|
||||
concat_24:add(net_3)
|
||||
concat_24:add(net_2)
|
||||
|
||||
net:add(concat_24)
|
||||
|
||||
local net_6 = nn.Sequential()
|
||||
net_6:add(nn.SpatialConvolution(256, 64, 1, 1, 1, 1))
|
||||
net_6:add(nn.ReLU())
|
||||
|
||||
local net_7 = nn.Sequential()
|
||||
net_7:add(nn.SpatialConvolution(256, 64, 1, 1, 1, 1))
|
||||
net_7:add(nn.ReLU())
|
||||
net_7:add(nn.SpatialConvolution(64, 96, 3, 3, 1, 1))
|
||||
net_7:add(nn.ReLU())
|
||||
|
||||
local net_8 = nn.Sequential()
|
||||
net_8:add(nn.SpatialConvolution(256, 64, 1, 1, 1, 1))
|
||||
net_8:add(nn.ReLU())
|
||||
net_8:add(nn.SpatialConvolution(64, 96, 3, 3, 1, 1))
|
||||
net_8:add(nn.ReLU())
|
||||
net_8:add(nn.SpatialConvolution(96, 96, 3, 3, 1, 1))
|
||||
net_8:add(nn.ReLU())
|
||||
|
||||
local net_9 = nn.Sequential()
|
||||
net_9:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_9:add(nn.SpatialAveragePooling(3, 3, 1, 1))
|
||||
net_9:add(nn.SpatialConvolution(256, 64, 1, 1, 1, 1))
|
||||
net_9:add(nn.ReLU())
|
||||
|
||||
local concat_41 = nn.Concat(2)
|
||||
concat_41:add(net_9)
|
||||
concat_41:add(net_8)
|
||||
concat_41:add(net_7)
|
||||
concat_41:add(net_6)
|
||||
|
||||
net:add(concat_41)
|
||||
|
||||
local net_10 = nn.Sequential()
|
||||
net_10:add(nn.SpatialConvolution(320, 128, 1, 1, 1, 1))
|
||||
net_10:add(nn.ReLU())
|
||||
net_10:add(nn.SpatialConvolution(128, 160, 3, 3, 1, 1))
|
||||
net_10:add(nn.ReLU())
|
||||
|
||||
local net_11 = nn.Sequential()
|
||||
net_11:add(nn.SpatialConvolution(320, 64, 1, 1, 1, 1))
|
||||
net_11:add(nn.ReLU())
|
||||
net_11:add(nn.SpatialConvolution(64, 96, 3, 3, 1, 1))
|
||||
net_11:add(nn.ReLU())
|
||||
net_11:add(nn.SpatialConvolution(96, 96, 3, 3, 1, 1))
|
||||
net_11:add(nn.ReLU())
|
||||
|
||||
local net_12 = nn.Sequential()
|
||||
net_12:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_12:add(nn.SpatialMaxPooling(3, 3, 1, 1))
|
||||
|
||||
local concat_54 = nn.Concat(2)
|
||||
concat_54:add(net_12)
|
||||
concat_54:add(net_11)
|
||||
concat_54:add(net_10)
|
||||
|
||||
net:add(concat_54)
|
||||
net:add(nn.SpatialConvolution(576, 576, 2, 2, 2, 2))
|
||||
|
||||
local net_13 = nn.Sequential()
|
||||
net_13:add(nn.SpatialConvolution(576, 64, 1, 1, 1, 1))
|
||||
net_13:add(nn.ReLU())
|
||||
net_13:add(nn.SpatialConvolution(64, 96, 3, 3, 1, 1))
|
||||
net_13:add(nn.ReLU())
|
||||
|
||||
local net_14 = nn.Sequential()
|
||||
net_14:add(nn.SpatialConvolution(576, 224, 1, 1, 1, 1))
|
||||
net_14:add(nn.ReLU())
|
||||
|
||||
local net_15 = nn.Sequential()
|
||||
net_15:add(nn.SpatialConvolution(576, 96, 1, 1, 1, 1))
|
||||
net_15:add(nn.ReLU())
|
||||
net_15:add(nn.SpatialConvolution(96, 128, 3, 3, 1, 1))
|
||||
net_15:add(nn.ReLU())
|
||||
net_15:add(nn.SpatialConvolution(128, 128, 3, 3, 1, 1))
|
||||
net_15:add(nn.ReLU())
|
||||
|
||||
local net_16 = nn.Sequential()
|
||||
net_16:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_16:add(nn.SpatialAveragePooling(3, 3, 1, 1))
|
||||
net_16:add(nn.SpatialConvolution(576, 128, 1, 1, 1, 1))
|
||||
net_16:add(nn.ReLU())
|
||||
|
||||
local concat_72 = nn.Concat(2)
|
||||
concat_72:add(net_16)
|
||||
concat_72:add(net_15)
|
||||
concat_72:add(net_14)
|
||||
concat_72:add(net_13)
|
||||
|
||||
net:add(concat_72)
|
||||
|
||||
local net_17 = nn.Sequential()
|
||||
net_17:add(nn.SpatialConvolution(576, 192, 1, 1, 1, 1))
|
||||
net_17:add(nn.ReLU())
|
||||
|
||||
local net_18 = nn.Sequential()
|
||||
net_18:add(nn.SpatialConvolution(576, 96, 1, 1, 1, 1))
|
||||
net_18:add(nn.ReLU())
|
||||
net_18:add(nn.SpatialConvolution(96, 128, 3, 3, 1, 1))
|
||||
net_18:add(nn.ReLU())
|
||||
|
||||
local net_19 = nn.Sequential()
|
||||
net_19:add(nn.SpatialConvolution(576, 96, 1, 1, 1, 1))
|
||||
net_19:add(nn.ReLU())
|
||||
net_19:add(nn.SpatialConvolution(96, 128, 3, 3, 1, 1))
|
||||
net_19:add(nn.ReLU())
|
||||
net_19:add(nn.SpatialConvolution(128, 128, 3, 3, 1, 1))
|
||||
net_19:add(nn.ReLU())
|
||||
|
||||
local net_20 = nn.Sequential()
|
||||
net_20:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_20:add(nn.SpatialAveragePooling(3, 3, 1, 1))
|
||||
net_20:add(nn.SpatialConvolution(576, 128, 1, 1, 1, 1))
|
||||
net_20:add(nn.ReLU())
|
||||
|
||||
local concat_89 = nn.Concat(2)
|
||||
concat_89:add(net_20)
|
||||
concat_89:add(net_19)
|
||||
concat_89:add(net_18)
|
||||
concat_89:add(net_17)
|
||||
|
||||
net:add(concat_89)
|
||||
|
||||
local net_21 = nn.Sequential()
|
||||
net_21:add(nn.SpatialConvolution(576, 160, 1, 1, 1, 1))
|
||||
net_21:add(nn.ReLU())
|
||||
|
||||
local net_22 = nn.Sequential()
|
||||
net_22:add(nn.SpatialConvolution(576, 128, 1, 1, 1, 1))
|
||||
net_22:add(nn.ReLU())
|
||||
net_22:add(nn.SpatialConvolution(128, 160, 3, 3, 1, 1))
|
||||
net_22:add(nn.ReLU())
|
||||
|
||||
local net_23 = nn.Sequential()
|
||||
net_23:add(nn.SpatialConvolution(576, 128, 1, 1, 1, 1))
|
||||
net_23:add(nn.ReLU())
|
||||
net_23:add(nn.SpatialConvolution(128, 160, 3, 3, 1, 1))
|
||||
net_23:add(nn.ReLU())
|
||||
net_23:add(nn.SpatialConvolution(160, 160, 3, 3, 1, 1))
|
||||
net_23:add(nn.ReLU())
|
||||
|
||||
local net_24 = nn.Sequential()
|
||||
net_24:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_24:add(nn.SpatialAveragePooling(3, 3, 1, 1))
|
||||
net_24:add(nn.SpatialConvolution(576, 96, 1, 1, 1, 1))
|
||||
net_24:add(nn.ReLU())
|
||||
|
||||
local concat_106 = nn.Concat(2)
|
||||
concat_106:add(net_24)
|
||||
concat_106:add(net_23)
|
||||
concat_106:add(net_22)
|
||||
concat_106:add(net_21)
|
||||
|
||||
net:add(concat_106)
|
||||
|
||||
local net_25 = nn.Sequential()
|
||||
net_25:add(nn.SpatialConvolution(576, 96, 1, 1, 1, 1))
|
||||
net_25:add(nn.ReLU())
|
||||
|
||||
local net_26 = nn.Sequential()
|
||||
net_26:add(nn.SpatialConvolution(576, 128, 1, 1, 1, 1))
|
||||
net_26:add(nn.ReLU())
|
||||
net_26:add(nn.SpatialConvolution(128, 192, 3, 3, 1, 1))
|
||||
net_26:add(nn.ReLU())
|
||||
|
||||
local net_27 = nn.Sequential()
|
||||
net_27:add(nn.SpatialConvolution(576, 160, 1, 1, 1, 1))
|
||||
net_27:add(nn.ReLU())
|
||||
net_27:add(nn.SpatialConvolution(160, 192, 3, 3, 1, 1))
|
||||
net_27:add(nn.ReLU())
|
||||
net_27:add(nn.SpatialConvolution(192, 192, 3, 3, 1, 1))
|
||||
net_27:add(nn.ReLU())
|
||||
|
||||
local net_28 = nn.Sequential()
|
||||
net_28:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_28:add(nn.SpatialAveragePooling(3, 3, 1, 1))
|
||||
net_28:add(nn.SpatialConvolution(576, 96, 1, 1, 1, 1))
|
||||
net_28:add(nn.ReLU())
|
||||
|
||||
local concat_123 = nn.Concat(2)
|
||||
concat_123:add(net_28)
|
||||
concat_123:add(net_27)
|
||||
concat_123:add(net_26)
|
||||
concat_123:add(net_25)
|
||||
|
||||
net:add(concat_123)
|
||||
|
||||
local net_29 = nn.Sequential()
|
||||
net_29:add(nn.SpatialConvolution(576, 192, 1, 1, 1, 1))
|
||||
net_29:add(nn.ReLU())
|
||||
net_29:add(nn.SpatialConvolution(192, 256, 3, 3, 1, 1))
|
||||
net_29:add(nn.ReLU())
|
||||
net_29:add(nn.SpatialConvolution(256, 256, 3, 3, 1, 1))
|
||||
net_29:add(nn.ReLU())
|
||||
|
||||
local net_30 = nn.Sequential()
|
||||
net_30:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_30:add(nn.SpatialMaxPooling(3, 3, 1, 1))
|
||||
|
||||
local net_31 = nn.Sequential()
|
||||
net_31:add(nn.SpatialAveragePooling(5, 5, 3, 3))
|
||||
net_31:add(nn.SpatialConvolution(576, 128, 1, 1, 1, 1))
|
||||
net_31:add(nn.View(2048))
|
||||
net_31:add(nn.Linear(2048, 768))
|
||||
net_31:add(nn.ReLU())
|
||||
net_31:add(nn.Linear(768, 4))
|
||||
net_31:add(nn.LogSoftMax())
|
||||
|
||||
local net_32 = nn.Sequential()
|
||||
net_32:add(nn.SpatialConvolution(576, 128, 1, 1, 1, 1))
|
||||
net_32:add(nn.ReLU())
|
||||
net_32:add(nn.SpatialConvolution(128, 192, 3, 3, 1, 1))
|
||||
net_32:add(nn.ReLU())
|
||||
|
||||
local concat_136 = nn.Concat(2)
|
||||
concat_136:add(net_32)
|
||||
concat_136:add(net_30)
|
||||
concat_136:add(net_29)
|
||||
|
||||
net:add(concat_136)
|
||||
local net_33 = nn.Sequential()
|
||||
net_33:add(nn.SpatialConvolution(1024, 1024, 2, 2, 2, 2))
|
||||
|
||||
local net_34 = nn.Sequential()
|
||||
net_34:add(nn.SpatialConvolution(1024, 352, 1, 1, 1, 1))
|
||||
net_34:add(nn.ReLU())
|
||||
|
||||
local net_35 = nn.Sequential()
|
||||
net_35:add(nn.SpatialConvolution(1024, 192, 1, 1, 1, 1))
|
||||
net_35:add(nn.ReLU())
|
||||
net_35:add(nn.SpatialConvolution(192, 320, 3, 3, 1, 1))
|
||||
net_35:add(nn.ReLU())
|
||||
|
||||
local net_36 = nn.Sequential()
|
||||
net_36:add(nn.SpatialConvolution(1024, 160, 1, 1, 1, 1))
|
||||
net_36:add(nn.ReLU())
|
||||
net_36:add(nn.SpatialConvolution(160, 224, 3, 3, 1, 1))
|
||||
net_36:add(nn.ReLU())
|
||||
net_36:add(nn.SpatialConvolution(224, 224, 3, 3, 1, 1))
|
||||
net_36:add(nn.ReLU())
|
||||
|
||||
local net_37 = nn.Sequential()
|
||||
net_37:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_37:add(nn.SpatialAveragePooling(3, 3, 1, 1))
|
||||
net_37:add(nn.SpatialConvolution(1024, 128, 1, 1, 1, 1))
|
||||
net_37:add(nn.ReLU())
|
||||
|
||||
local concat_154 = nn.Concat(2)
|
||||
concat_154:add(net_37)
|
||||
concat_154:add(net_36)
|
||||
concat_154:add(net_35)
|
||||
concat_154:add(net_34)
|
||||
|
||||
net_33:add(concat_154)
|
||||
|
||||
local net_38 = nn.Sequential()
|
||||
net_38:add(nn.SpatialConvolution(1024, 352, 1, 1, 1, 1))
|
||||
net_38:add(nn.ReLU())
|
||||
|
||||
local net_39 = nn.Sequential()
|
||||
net_39:add(nn.SpatialConvolution(1024, 192, 1, 1, 1, 1))
|
||||
net_39:add(nn.ReLU())
|
||||
net_39:add(nn.SpatialConvolution(192, 320, 3, 3, 1, 1))
|
||||
net_39:add(nn.ReLU())
|
||||
|
||||
local net_40 = nn.Sequential()
|
||||
net_40:add(nn.SpatialConvolution(1024, 192, 1, 1, 1, 1))
|
||||
net_40:add(nn.ReLU())
|
||||
net_40:add(nn.SpatialConvolution(192, 224, 3, 3, 1, 1))
|
||||
net_40:add(nn.ReLU())
|
||||
net_40:add(nn.SpatialConvolution(224, 224, 3, 3, 1, 1))
|
||||
net_40:add(nn.ReLU())
|
||||
|
||||
local net_41 = nn.Sequential()
|
||||
net_41:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_41:add(nn.SpatialMaxPooling(3, 3, 1, 1))
|
||||
net_41:add(nn.SpatialConvolution(1024, 128, 1, 1, 1, 1))
|
||||
net_41:add(nn.ReLU())
|
||||
|
||||
local concat_171 = nn.Concat(2)
|
||||
concat_171:add(net_41)
|
||||
concat_171:add(net_40)
|
||||
concat_171:add(net_39)
|
||||
concat_171:add(net_38)
|
||||
|
||||
net_33:add(concat_171)
|
||||
net_33:add(nn.SpatialAveragePooling(7, 7, 1, 1))
|
||||
net_33:add(nn.View(1024))
|
||||
net_33:add(nn.Linear(1024, 4))
|
||||
net_33:add(nn.LogSoftMax())
|
||||
|
||||
local concat_183 = nn.Concat(2)
|
||||
concat_183:add(net_33)
|
||||
concat_183:add(net_31)
|
||||
|
||||
net:add(concat_183)
|
||||
|
||||
return net
|
||||
@@ -28,6 +28,14 @@
|
||||
"CreateExecution": {
|
||||
"src": "src/plugins/CreateExecution",
|
||||
"test": "test/plugins/CreateExecution"
|
||||
},
|
||||
"GenerateExecFile": {
|
||||
"src": "src/plugins/GenerateExecFile",
|
||||
"test": "test/plugins/GenerateExecFile"
|
||||
},
|
||||
"ImportArtifact": {
|
||||
"src": "src/plugins/ImportArtifact",
|
||||
"test": "test/plugins/ImportArtifact"
|
||||
}
|
||||
},
|
||||
"layouts": {},
|
||||
@@ -122,6 +130,13 @@
|
||||
"panel": "src/visualizers/panels/DeserializeEditor",
|
||||
"secondary": false,
|
||||
"widget": "src/visualizers/widgets/DeserializeEditor"
|
||||
},
|
||||
"Footer": {
|
||||
"src": "panels/Footer/FooterPanel",
|
||||
"title": "Footer",
|
||||
"panel": "src/visualizers/panels/Footer",
|
||||
"secondary": false,
|
||||
"widget": "src/visualizers/widgets/Footer"
|
||||
}
|
||||
},
|
||||
"addons": {},
|
||||
@@ -137,6 +152,9 @@
|
||||
},
|
||||
"OpIntPtrDecorator": {
|
||||
"src": "src/decorators/OpIntPtrDecorator"
|
||||
},
|
||||
"DcOpDecorator": {
|
||||
"src": "src/decorators/DcOpDecorator"
|
||||
}
|
||||
},
|
||||
"seeds": {
|
||||
@@ -163,6 +181,9 @@
|
||||
},
|
||||
"project": {
|
||||
"src": "src/seeds/project"
|
||||
},
|
||||
"minimal": {
|
||||
"src": "src/seeds/minimal"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário