Initial commit
This commit is contained in:
Коммит
ef30788382
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"directory": "/client/app/bower_components"
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
node_modules/
|
||||
client/app/bower_components/
|
||||
client/app/js/bundled.js
|
||||
npm-debug.log
|
||||
.DS_Store
|
||||
dist
|
Двоичный файл не отображается.
Двоичный файл не отображается.
|
@ -0,0 +1,8 @@
|
|||
Copyright (C) 2010-2014 by Revolution Analytics Inc.
|
||||
|
||||
This program is licensed to you under the terms of Version 2.0 of the
|
||||
Apache License. This program is distributed WITHOUT
|
||||
ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
|
||||
Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0) for more
|
||||
details.
|
|
@ -0,0 +1,306 @@
|
|||
js-example-fraud-score
|
||||
======================
|
||||
|
||||
Example use of DeployR as a real-time, R analytics scoring engine.
|
||||
|
||||
## Example Quick Start
|
||||
|
||||
By default, the example assumes an instance of the **DeployR server** is running
|
||||
on `localhost`. If your instance of DeployR is running at some other IP address
|
||||
then please udpate the `host` location property in the configuration file
|
||||
`config/config.json`.
|
||||
|
||||
|
||||
1. Download and install [Node.js](http://nodejs.org/download/), which ships with
|
||||
npm.
|
||||
|
||||
2. Clone the repository:
|
||||
|
||||
```
|
||||
$ git clone https://github.com/deployr/js-example-fraud-score.git
|
||||
$ cd js-example-fraud-score
|
||||
```
|
||||
|
||||
3. Install the global dependencies:
|
||||
|
||||
```
|
||||
$ npm install -g gulp bower browserify
|
||||
```
|
||||
|
||||
You might need `sudo` for globally installed packages, in that case:
|
||||
|
||||
```
|
||||
$ sudo npm install -g gulp bower browserify
|
||||
```
|
||||
|
||||
4. Install the local dependencies:
|
||||
|
||||
```
|
||||
$ npm install
|
||||
```
|
||||
|
||||
5. Set the DeployR server `host` location *if* not running at `localhost` in the
|
||||
configuration file `config/config.json`
|
||||
|
||||
6. Run locally:
|
||||
|
||||
```
|
||||
$ gulp
|
||||
```
|
||||
|
||||
7. Point your browser to `http://localhost:9080`
|
||||
|
||||
|
||||
## About
|
||||
|
||||
This example demonstrates the use of
|
||||
[DeployR](http://deployr.revolutionanalytics.com) as a real-time, R analytics
|
||||
scoring engine.
|
||||
|
||||
The example scenario mimics a real world application where employees at a
|
||||
fictitious bank can request _fraud scores_ for one or more bank account records
|
||||
to help detect fraudulent account activity.
|
||||
|
||||
This example is built using the _DeployR_ [RBroker
|
||||
Framework](http://deployr.revolutionanalytics.com/dev), the simplest way to
|
||||
integrate R analytics inside any Java, JavaScript or .NET application.
|
||||
|
||||
This example consists of three distinct parts:
|
||||
|
||||
1. Example R Analytics
|
||||
2. Example Server Application
|
||||
3. Example Client Application
|
||||
|
||||
The final section of this document provides additional details regarding the
|
||||
_DeployR integration_ implemented for this example.
|
||||
|
||||
## Example R Analytics
|
||||
|
||||
```
|
||||
Source: analytics/*
|
||||
```
|
||||
|
||||
This example uses an R model built to score fictitious bank account data to help
|
||||
uncover fraudulent account activity. The model used is found here:
|
||||
|
||||
```
|
||||
analytics/fraudModel.rData
|
||||
```
|
||||
|
||||
The model uses three variables associated with individual bank accounts:
|
||||
|
||||
1. The number of transactions on the account
|
||||
2. The account balance
|
||||
3. The credit line on the account
|
||||
|
||||
This example makes use of a scoring function that uses the model to help
|
||||
determine the likelihood of _fraud_ on a given account based on these
|
||||
data inputs. The scoring function is found here:
|
||||
|
||||
```
|
||||
analytics/ccFraudScore.R
|
||||
```
|
||||
|
||||
The R scripts and data models used by this example application are
|
||||
bundled by default within the DeployR 7.3 repository, inside the
|
||||
example-fraud-score directory owned by testuser.
|
||||
|
||||
However, if for any reason your DeployR repository does not contain
|
||||
these files you can add them using the DeployR Repository Manager as
|
||||
follows:
|
||||
|
||||
1. Log in as testuser into the Repository Manager
|
||||
2. Create a new repository directory called example-fraud-score
|
||||
3. Upload analytics/fraudModel.rData to the example-fraud-score
|
||||
directory
|
||||
4. Upload analytics/ccFraudScore.R to the example-fraud-score directory
|
||||
|
||||
## Example Server Application
|
||||
|
||||
Source:
|
||||
|
||||
```
|
||||
server.js
|
||||
|
||||
server/**/*
|
||||
```
|
||||
|
||||
The example server application represents a real world application, capable of
|
||||
processing client requests for _fraud scores_ on one or more bank account
|
||||
records.
|
||||
|
||||
The example server application is implemented as a simple
|
||||
[Express](http://expressjs.com/) Node.js Web application.
|
||||
|
||||
The example server application exposes a simple REST API through which client
|
||||
applications can submit _fraud scoring_ requests:
|
||||
|
||||
```
|
||||
/fraud/score/{num_of_records}
|
||||
```
|
||||
|
||||
The example server application handles client requests internally using the
|
||||
[RBroker Framework](http://deployr.revolutionanalytics.com/dev) to run
|
||||
the required R analytics that _scores_ each requested bank account record.
|
||||
|
||||
The _score_, generated by the R analytics and returned to the server via
|
||||
the _RBroker Framework_, is then pushed by the server application, using
|
||||
[WebSockets](https://www.npmjs.org/package/ws) through an abstraction layer for
|
||||
real-time communication called [Primus](https://github.com/primus/primus) to
|
||||
client applications that have subscribed as listeners on:
|
||||
|
||||
```
|
||||
/fraudengine/topic/fraud
|
||||
```
|
||||
|
||||
## Example Client Application
|
||||
|
||||
```
|
||||
Source: client/app/*
|
||||
```
|
||||
|
||||
The example client application simulates a computer system made available to
|
||||
employees at a fictitious bank.
|
||||
|
||||
The example client application is implemented as a simple, single page
|
||||
[AngularJS](https://angularjs.org) application. The single page is divided into
|
||||
two distinct sections:
|
||||
|
||||
1. RBroker Runtime Window
|
||||
|
||||
This window gives the user a live view of all activity that
|
||||
is taking place through the _RBroker Framework_ on behalf of the client
|
||||
application. The runtime data provided indicates among other things the
|
||||
live throughput performance being delivered by _DeployR_ behaving as a
|
||||
real-time R analytics scoring engine.
|
||||
|
||||
Note: The details presented in the RBroker Runtime Window would not
|
||||
typically appear in a real-world client application. These data are presented
|
||||
here simply to aid developers understand by observation how an
|
||||
_RBroker Framework_integration works.
|
||||
|
||||
2. Bank Account Fraud Score Result Window
|
||||
|
||||
This window displays the _fraud score_ results generated by the
|
||||
real-time R analytics scoring engine powered by _DeployR_. The end user
|
||||
can also use the _Execute_ button in this window to launch one or more
|
||||
_fraud scoring_ requests.
|
||||
|
||||
The data for example bank account records is randomly generated by the
|
||||
application. Requests are submitted by the client application through
|
||||
the server application REST API.
|
||||
|
||||
The _score_ generated per request is returned to the client application within a
|
||||
JSON message delivered over a WebSocket channel.
|
||||
|
||||
## Running the Example
|
||||
|
||||
A [gulp.js](http://gulpjs.com/) build script is provided to run the example:
|
||||
|
||||
```
|
||||
gulpfile.js
|
||||
```
|
||||
|
||||
By default, the build configuration assumes an instance of the DeployR server
|
||||
is running on `localhost`. If your instance of DeployR is running at some
|
||||
other IP address then please update the `host` property in the configuration
|
||||
file `config/config.json` as appropriate:
|
||||
|
||||
```
|
||||
{
|
||||
"host": "http://localhost:7300",
|
||||
"port": "9080",
|
||||
"credentials": {
|
||||
"username": "testuser",
|
||||
"password": "changeme"
|
||||
},
|
||||
"logging": false,
|
||||
"constants" : {
|
||||
"REPO_OWNER": "testuser",
|
||||
"REPO_SCRIPT": "ccFraudScore.R",
|
||||
"REPO_DIRECTORY": "example-fraud-score",
|
||||
"FRAUD_MODEL": "fraudModel.rData"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To run this example application:
|
||||
|
||||
```
|
||||
$ gulp
|
||||
```
|
||||
|
||||
Observe the console output in your terminal window to determine if the server
|
||||
application has started successfully. Once started, open the client application
|
||||
in your Web browser:
|
||||
|
||||
```
|
||||
http://localhost:9080
|
||||
```
|
||||
|
||||
## Multiple Users Running the Example
|
||||
|
||||
By default, the example build configuration defaults to using *testuser* account
|
||||
credentials when authenticating with the DeployR server. If two or more users
|
||||
intend running this example application at the same time against the same
|
||||
DeployR server instance then:
|
||||
|
||||
1. Each user must update the `username` property in their `config/config.json`
|
||||
configuration file, each indicating the *username* of their own user account.
|
||||
|
||||
2. The _Access Control_ setting for each of the R analytics file dependencies in
|
||||
the DeployR repository must be changed from _Private_ access to _Shared_ access.
|
||||
|
||||
## DeployR Integration Details
|
||||
|
||||
#### R Analytics Dependencies
|
||||
|
||||
DeployR-powered applications typically depend on repository-managed R analytics
|
||||
scripts, models and/or data files. See the _DeployR_ [Repository Manager](http://deployr.revolutionanalytics.com/documents/help/repo-man/) for details on how best to manage your own R analytics dependencies.
|
||||
|
||||
This example depends on two repository-managed files:
|
||||
|
||||
1. /testuser/example-fraud-score/fraudModel.rData
|
||||
2. /testuser/example-fraud-score/ccFraudScore.R
|
||||
|
||||
Both files, an R model and scoring function respectively, are owned by
|
||||
_testuser_ and can be found in the _example-fraud-score_ repository-managed
|
||||
directory owned by _testuser_.
|
||||
|
||||
These example file dependencies ship, pre-deployed in the _DeployR_ repository
|
||||
so there is no further action for you to take in order for this example to use
|
||||
them.
|
||||
|
||||
#### RBroker Framework - Pooled Task Runtime
|
||||
|
||||
This examples uses the [RBroker Framework](http://deployr.revolutionanalytics.com/documents/dev/rbroker/)
|
||||
to integrate _DeployR_ real-time scoring capabilities inside the example server
|
||||
application.
|
||||
|
||||
Specifically, this example uses the [Pooled Task Runtime](http://deployr.revolutionanalytics.com/documents/dev/rbroker/#pooled)
|
||||
provided by the _RBroker Framework_.
|
||||
|
||||
#### RBroker Framework - Throughput
|
||||
|
||||
The _Resize_ button in the _RBroker Runtime Window_ in the example client
|
||||
application lets the end user experiment with the size of the pool of R sessions
|
||||
associated with the _Pooled Task Runtime_.
|
||||
|
||||
We recommend experimenting with the size of the pool and observing the effect
|
||||
this has on throughput. See the following sections of the _RBroker Framework_
|
||||
tutorial for related details:
|
||||
|
||||
- [Client Application Simulations](http://deployr.revolutionanalytics.com/documents/dev/rbroker/#simulation)
|
||||
- [Client Application Profiling](http://deployr.revolutionanalytics.com/documents/dev/rbroker/#profiling)
|
||||
- [Grid Resource Management](http://deployr.revolutionanalytics.com/documents/dev/rbroker/#gridprimer)
|
||||
|
||||
## License ##
|
||||
|
||||
Copyright (C) 2010-2014 by Revolution Analytics Inc.
|
||||
|
||||
This program is licensed to you under the terms of Version 2.0 of the
|
||||
Apache License. This program is distributed WITHOUT
|
||||
ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
|
||||
Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0) for more
|
||||
details.
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
### SCORING THE MODEL
|
||||
require(RevoScriptTools)
|
||||
revoInput('{"name": "bal", "render":"integer", "default": 5000, "min" : 0, "max": 25000 }')
|
||||
revoInput('{"name": "trans", "render":"integer", "default": 12, "min" : 0, "max": 100 }')
|
||||
revoInput('{"name": "credit", "render":"integer", "default": 8, "min" : 0, "max": 75 }')
|
||||
|
||||
if(!exists('fraudModel')){load('fraudModel.rData')}
|
||||
score<-data.frame(balance=bal,numTrans=trans,creditLine=credit)
|
||||
x<-predict(fraudModel, score)
|
Двоичный файл не отображается.
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "js-example-fraud-score",
|
||||
"version": "0.0.1",
|
||||
"authors": [ "DeployR - Revolution Analytics Inc." ],
|
||||
"license": "Apache License 2.0",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"client/app/bower_components",
|
||||
"test",
|
||||
"tests"
|
||||
],
|
||||
"dependencies": {
|
||||
"bootstrap": "~3.2.0",
|
||||
"angular": "~1.2.22",
|
||||
"angular-animate": "~1.2.22",
|
||||
"angular-route": "~1.2.22",
|
||||
"animate.css": "~3.2.0",
|
||||
"angular-bootstrap": "~0.11.2",
|
||||
"fontawesome": "~4.1.0"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2014 by Revolution Analytics Inc.
|
||||
*
|
||||
* This program is licensed to you under the terms of Version 2.0 of the
|
||||
* Apache License. This program is distributed WITHOUT
|
||||
* ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
|
||||
* Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0) for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
.runtime {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 1000px;
|
||||
}
|
||||
.results {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 1000px;
|
||||
}
|
||||
.stats {
|
||||
margin-left: 20px;
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<html ng-app="FraudApp">
|
||||
<head lang="en">
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<title>R Analytics Fraud Score Example</title>
|
||||
<!-- styles -->
|
||||
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css"/>
|
||||
<link rel="stylesheet" href="bower_components/fontawesome/css/font-awesome.css"/>
|
||||
<link rel="stylesheet" href="bower_components/animate.css/animate.css"/>
|
||||
<link rel="stylesheet" href="./css/main.css"/>
|
||||
<script src="/primus/primus.io.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="#">R Analytics Fraud Score Example Application - <small>Powered by DeployR RBroker Framework</small></a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="container">
|
||||
<!-- views -->
|
||||
<div ng-view></div>
|
||||
</div>
|
||||
<!-- scripts -->
|
||||
<script src="bower_components/angular/angular.min.js"></script>
|
||||
<script src="bower_components/angular-route/angular-route.min.js"></script>
|
||||
<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
|
||||
<script src="./js/bundled.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2014 by Revolution Analytics Inc.
|
||||
*
|
||||
* This program is licensed to you under the terms of Version 2.0 of the
|
||||
* Apache License. This program is distributed WITHOUT
|
||||
* ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
|
||||
* Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0) for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JavaScript Fraud Detection Example Application
|
||||
*
|
||||
* AngularJS ng-controller
|
||||
*
|
||||
* Initialization:
|
||||
*
|
||||
* Establishes WS connection on /fraudengine, subscribes on /topic/fraud.
|
||||
*
|
||||
* Events:
|
||||
*
|
||||
* FRAUDSCORE - RTask result message.
|
||||
* RUNTIMESTATS - RBroker runtime statistics message.
|
||||
* CLIENTALERT - RBroker runtime (error) notification message.
|
||||
*
|
||||
* User driven (index.html) events:
|
||||
*
|
||||
* Resize click -> $scope.resizePool() -> POST:/fraud/pool/init/{size}
|
||||
*
|
||||
* Execute click -> $scope.executeTasks() -> GET:/fraud/score/{tasks}
|
||||
*
|
||||
*/
|
||||
module.exports = function($scope, $http, $location) {
|
||||
|
||||
//
|
||||
// ng-controller model on $scope.
|
||||
//
|
||||
$scope.brokerInitialized = false;
|
||||
$scope.alertMessage = null;
|
||||
|
||||
$scope.fraudScoreResults = [];
|
||||
$scope.poolSize = 1;
|
||||
$scope.taskCount = 1;
|
||||
|
||||
$scope.runtimeStats = {
|
||||
requestedPoolSize: 1,
|
||||
allocatedPoolSize: 1,
|
||||
submittedTasks: 0,
|
||||
successfulTasks: 0,
|
||||
failedTasks: 0,
|
||||
averageCodeExecution: 0,
|
||||
averageServerOverhead: 0,
|
||||
averageNetworkLatency: 0
|
||||
};
|
||||
|
||||
$scope.targetTaskThroughput = 0;
|
||||
$scope.currentTaskThroughput = 0;
|
||||
$scope.startTaskThroughput = 0;
|
||||
$scope.secondTaskThroughput = 0;
|
||||
$scope.minuteTaskThroughput = 0;
|
||||
|
||||
//
|
||||
// Resize Button Handler:
|
||||
//
|
||||
$scope.resizePool = function() {
|
||||
$scope.alertMessage = 'RBroker pool is initializing. ' +
|
||||
'Requested ' + $scope.poolSize + ' R session(s) in the pool. ' +
|
||||
'This may take some time. Please wait.';
|
||||
$scope.brokerInitialized = false;
|
||||
|
||||
console.log('Attempt to resize pool succeeded, new size=' + $scope.poolSize);
|
||||
|
||||
$http.post('/fraud/pool/init/' + $scope.poolSize)
|
||||
.success(function(data, status, headers, config) {
|
||||
$scope.alertMessage = null;
|
||||
console.log('Attempt to resize pool succeeded, new size=' + $scope.poolSize);
|
||||
}).error(function(data, status, headers, config) {
|
||||
$scope.errorMessage = 'Attempt to resize pool failed, error=' + data;
|
||||
}).finally(function() {
|
||||
$scope.fraudScoreResults = [];
|
||||
$scope.brokerInitialized = true;
|
||||
$scope.currentTaskThroughput = 0;
|
||||
$scope.secondTaskThroughput = 0;
|
||||
$scope.minuteTaskThroughput = 0;
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
//
|
||||
// Execute Button Handler:
|
||||
//
|
||||
$scope.executeTasks = function() {
|
||||
$scope.currentTaskThroughput = 0;
|
||||
$scope.secondTaskThroughput = 0;
|
||||
$scope.minuteTaskThroughput = 0;
|
||||
$scope.targetTaskThroughput = $scope.taskCount;
|
||||
$scope.startTaskThroughput = Date.now();
|
||||
|
||||
$http.get('/fraud/score/' + $scope.taskCount)
|
||||
.success(function(data, status, headers, config) {
|
||||
console.log('Attempt to execute tasks succeeded, taskCount=' + $scope.taskCount);
|
||||
}).error(function(data, status, headers, config) {
|
||||
$scope.errorMessage = 'Can\'t retrieve scores list!';
|
||||
$scope.errorMessage = 'Attempt to execute tasks failed, error=' + data;
|
||||
});
|
||||
};
|
||||
|
||||
var primus = Primus.connect('ws://localhost:' + $location.port());
|
||||
|
||||
// Subscribe for events on /topic/fraud.
|
||||
primus.on('open', function() {
|
||||
|
||||
primus.on('/topic/fraud', function(msgObj) {
|
||||
|
||||
if (msgObj.msgType === 'FRAUDSCORE') {
|
||||
|
||||
var elapsedTime = Date.now() - $scope.startTaskThroughput;
|
||||
|
||||
// $apply to propgate change to model.
|
||||
$scope.$apply(function() {
|
||||
|
||||
$scope.currentTaskThroughput += 1;
|
||||
var throughput =
|
||||
(1000 / elapsedTime) * $scope.currentTaskThroughput;
|
||||
$scope.secondTaskThroughput =
|
||||
+(Math.round((throughput - (throughput % 0.01)) + 'e+2') + 'e-2');
|
||||
$scope.minuteTaskThroughput =
|
||||
Math.round($scope.secondTaskThroughput * 60);
|
||||
|
||||
// Discard older fraudScore from fraudScoreResults
|
||||
// list to prevent browser rendering exhaustion.
|
||||
if ($scope.fraudScoreResults.length > 300) {
|
||||
$scope.fraudScoreResults.length = 150;
|
||||
}
|
||||
$scope.fraudScoreResults.unshift(msgObj);
|
||||
});
|
||||
|
||||
} else if (msgObj.msgType === 'RUNTIMESTATS') {
|
||||
// $apply to propogate change to model.
|
||||
$scope.$apply(function() {
|
||||
$scope.alertMessage = null;
|
||||
$scope.runtimeStats = msgObj;
|
||||
});
|
||||
} else if (msgObj.msgType === 'CLIENTALERT') {
|
||||
// $apply to propogate change to model.
|
||||
$scope.$apply(function() {
|
||||
$scope.alertMessage = msgObj.msg;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
// Initialize initial RBroker pool on application startup.
|
||||
//
|
||||
$scope.resizePool();
|
||||
});
|
||||
};
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2014 by Revolution Analytics Inc.
|
||||
*
|
||||
* This program is licensed to you under the terms of Version 2.0 of the
|
||||
* Apache License. This program is distributed WITHOUT
|
||||
* ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
|
||||
* Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0) for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
|
||||
'use strict';
|
||||
|
||||
var mainCtrl = require('./controllers/main-controller');
|
||||
|
||||
angular.module('FraudApp', ['ngRoute', 'ui.bootstrap'])
|
||||
|
||||
.config([
|
||||
'$locationProvider',
|
||||
'$routeProvider',
|
||||
function($locationProvider, $routeProvider) {
|
||||
$locationProvider.hashPrefix('!');
|
||||
// routes
|
||||
$routeProvider
|
||||
.when("/", {
|
||||
templateUrl: "./partials/stats.html",
|
||||
controller: "MainController"
|
||||
})
|
||||
.otherwise({
|
||||
redirectTo: '/'
|
||||
});
|
||||
}
|
||||
])
|
||||
|
||||
// Load controller
|
||||
.controller('MainController', ['$scope', '$http', '$location', mainCtrl]);
|
||||
}());
|
|
@ -0,0 +1,167 @@
|
|||
<div class="row col-md-12">
|
||||
<div class="panel panel-default runtime">
|
||||
<div class="panel-heading clearfix">
|
||||
<h5 class="panel-title pull-left">
|
||||
<a tooltip-placement="bottom" tooltip="An RBroker runtime manages all aspects of RTask queueing, execution and result handling on behalf of client applicaitons integrating with DeployR.">
|
||||
RBroker Runtime
|
||||
</a>
|
||||
</h5>
|
||||
<span ng-show="runtimeStats.username">
|
||||
<span style="margin-left:160px;font-size:14px; font-weight:bold">{{ runtimeStats.username }} @ {{ runtimeStats.endpoint }}</span>
|
||||
</span>
|
||||
<div class="pull-right">
|
||||
<span><b>Pool Size:</b>
|
||||
</span>
|
||||
<input type="number" name="ps" ng-model="poolSize" ng-disabled="!brokerInitialized" min="1" max="500" step="1" value="1" />
|
||||
<a class="btn btn-primary btn-xs" ng-disabled="!brokerInitialized" tooltip-placement="bottom" tooltip="Resize the pool of R sessions dedicated to the RBroker runtime in use by this demo application. The larger the pool, the higher the expected throughput. Note, the max pool size any application can acquire is ultimately determined by the size and configuration of the DeployR grid." ng-disabled="!brokerInitialized" ng-click="resizePool()">Resize
|
||||
<span class="glyphicon glyphicon-refresh"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12" style="height:4px;">
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row stats">
|
||||
<div class="col-md-12">
|
||||
<h5>
|
||||
Pool
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row stats">
|
||||
<div class="col-md-4">
|
||||
<a tooltip-placement="bottom" tooltip="Number of dedicated R sessions requested by the RBroker runtime.">
|
||||
Requested Size:
|
||||
</a>
|
||||
<span style="font-size:16px;color:gray">{{runtimeStats.requestedPoolSize}}</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<a tooltip-placement="bottom" tooltip="Number of dedicated R sessions allocated by DeployR to the RBroker runtime.">
|
||||
Allocated Size:
|
||||
</a>
|
||||
<span style="font-size:16px;color:gray">{{runtimeStats.allocatedPoolSize}}</span>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<a tooltip-placement="bottom" tooltip="Maximum number of RTask that can execute in parallel on the RBroker runtime. Note, the max concurrency of the RBroker (pooled) runtime always equals the number of dedicated R sessions allocated by DeployR to the runtime.">
|
||||
Max Concurrency:
|
||||
</a>
|
||||
<span style="font-size:16px;color:gray">{{runtimeStats.allocatedPoolSize}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12" style="height:4px;">
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row stats">
|
||||
<div class="col-md-12">
|
||||
<h5>Tasks</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row stats">
|
||||
<div class="col-md-4">
|
||||
<a tooltip-placement="bottom" tooltip="Number of RTask that have been submitted to the RBroker runtime.">
|
||||
Submitted Tasks:
|
||||
</a>
|
||||
<span style="font-size:16px;color:gray">{{runtimeStats.submittedTasks}}</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<a tooltip-placement="bottom" tooltip="Number of RTask that have been successfully executed by the RBroker runtime.">
|
||||
Successful Tasks:
|
||||
</a>
|
||||
<span style="font-size:16px;color:gray">{{runtimeStats.successfulTasks}}</span>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<a tooltip-placement="bottom" tooltip="Number of RTask that have resulted in error when executed by the RBroker runtime. A failure may occur for a number of reasons. For example, if any required input values to your R script are missing or invalid, if there is an error in the syntax or logic of your R script or if your instance of the RBroker runtime loses its connection to the DeployR server due to a dropped network connection.">
|
||||
Failed Tasks:
|
||||
</a>
|
||||
<span style="font-size:16px;color:gray">{{runtimeStats.failedTasks}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12" style="height:4px;">
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row stats">
|
||||
<div class="col-md-12">
|
||||
<h5>Fraud Task Throughput</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row stats">
|
||||
<div class="col-md-4">
|
||||
<a tooltip-placement="bottom" tooltip="Number of RTask executed following the most recent click on the Execute button.">
|
||||
Executed Tasks:
|
||||
</a>
|
||||
<span style="font-size:16px;color:gray">{{currentTaskThroughput}}</span>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<a tooltip-placement="bottom" tooltip="Estimated RTask throughput, measured in tasks per second, based on the observed RBroker runtime performance for tasks executing following the most recent click on the Execute button.">
|
||||
Tasks Per Second:
|
||||
</a>
|
||||
<span style="font-size:16px;color:gray">{{secondTaskThroughput}}</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<a tooltip-placement="bottom" tooltip="Estimated RTask throughput, measured in tasks per minute, based on the observed RBroker runtime performance for tasks executing following the most recent click on the Execute button.">
|
||||
Tasks Per Minute:
|
||||
</a>
|
||||
<span style="font-size:16px;color:gray">{{minuteTaskThroughput}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12" style="height:10px;">
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" ng-show="alertMessage">
|
||||
<div class="col-md-12 alert alert-info">{{alertMessage}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row col-md-12">
|
||||
<div class="panel panel-default runtime">
|
||||
<div class="panel-heading clearfix">
|
||||
<h5 class="panel-title pull-left">
|
||||
<a tooltip-placement="bottom" tooltip="This demo application performs real-time scoring on user account data to determine the risk of fraudulent transactions.">
|
||||
Fraud Analysis
|
||||
</a>
|
||||
</h5>
|
||||
<div class="pull-right">
|
||||
<span><b>Task Count:</b>
|
||||
</span>
|
||||
<input name="tc" ng-model="taskCount" ng-disabled="!brokerInitialized" type="number" min="1" max="100000" step="1" value="1" />
|
||||
<a class="btn btn-primary btn-xs" ng-disabled="!brokerInitialized" tooltip-placement="bottom" tooltip="Submit simulated account data for real-time scoring. Each set of account data is executed as an RTask using the RBroker runtime where a fraud score is generated and returned." ng-disabled="!brokerInitialized" ng-click="executeTasks()">Execute
|
||||
<span class="glyphicon glyphicon-repeat"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12" style="height:4px;">
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
<table class="table table-hover table-striped table-condensed">
|
||||
<thead>
|
||||
<th class="col-md-3">Account Balance</th>
|
||||
<th class="col-md-3">Transactions</th>
|
||||
<th class="col-md-3">Credit</th>
|
||||
<th class="col-md-3">Fraud Score</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="fraudScoreResult in fraudScoreResults">
|
||||
<td>{{fraudScoreResult.balance}}</td>
|
||||
<td>{{fraudScoreResult.transactions}}</td>
|
||||
<td>{{fraudScoreResult.credit}}</td>
|
||||
<td>{{fraudScoreResult.score}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"host": "http://localhost:7300",
|
||||
"port": "9080",
|
||||
"credentials": {
|
||||
"username": "testuser",
|
||||
"password": "changeme"
|
||||
},
|
||||
"logging": false,
|
||||
"constants" : {
|
||||
"REPO_OWNER": "testuser",
|
||||
"REPO_SCRIPT": "ccFraudScore.R",
|
||||
"REPO_DIRECTORY": "example-fraud-score",
|
||||
"FRAUD_MODEL": "fraudModel.rData"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2014 by Revolution Analytics Inc.
|
||||
*
|
||||
* This program is licensed to you under the terms of Version 2.0 of the
|
||||
* Apache License. This program is distributed WITHOUT
|
||||
* ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
|
||||
* Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0) for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
var gulp = require('gulp'),
|
||||
jshint = require('gulp-jshint'),
|
||||
browserify = require('gulp-browserify'),
|
||||
concat = require('gulp-concat'),
|
||||
server = require('gulp-express'),
|
||||
unzip = require('gulp-unzip');
|
||||
|
||||
gulp.task('deployr-deps', function(){
|
||||
gulp.src('./.modules/*.zip')
|
||||
.pipe(unzip())
|
||||
.pipe(gulp.dest('./node_modules'))
|
||||
});
|
||||
|
||||
gulp.task('lint', function() {
|
||||
gulp.src([ '!./client/app/js/bundled.js',
|
||||
'./client/app/**/*.js',
|
||||
'!./client/app/bower_components/**/*',
|
||||
'!./client/app/js/vendor/**/*' ])
|
||||
.pipe(jshint())
|
||||
.pipe(jshint.reporter('default'))
|
||||
.pipe(jshint.reporter('fail'));
|
||||
});
|
||||
|
||||
gulp.task('browserify', function() {
|
||||
gulp.src(['client/app/js/main.js'])
|
||||
.pipe(browserify({
|
||||
insertGlobals: true,
|
||||
debug: true
|
||||
}))
|
||||
.pipe(concat('bundled.js'))
|
||||
.pipe(gulp.dest('./client/app/js'))
|
||||
});
|
||||
|
||||
gulp.task('server', function () {
|
||||
//start the server at the beginning of the task
|
||||
server.run({
|
||||
file: 'server.js'
|
||||
});
|
||||
|
||||
//restart the server when file changes
|
||||
gulp.watch(['client/app/**/*.html'], server.notify);
|
||||
gulp.watch(['client/app/js/**/*.js'], ['lint', 'browserify']);
|
||||
gulp.watch(['client/app/css/**/*.css']);
|
||||
});
|
||||
|
||||
gulp.task('default', ['lint', 'browserify', 'server'] );
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"name": "js-example-fraud-score",
|
||||
"version": "0.0.1",
|
||||
"description": "R Analytics Fraud Score Example Application - Powered by DeployR RBroker Framework",
|
||||
"repository": "https://github.com/deployr/js-example-fraud-score.git",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"postinstall": "bower install && gulp deployr-deps"
|
||||
},
|
||||
"main": "gulpfile.js",
|
||||
"author": "DeployR - Revolution Analytics Inc.",
|
||||
"main": "server.js",
|
||||
"dependencies": {
|
||||
"gulp": "^3.8.7",
|
||||
"gulp-jshint": "^1.8.4",
|
||||
"gulp-concat": "^2.3.4",
|
||||
"gulp-unzip": "^0.1.2",
|
||||
"gulp-browserify": "^0.5.0",
|
||||
"bower": "^1.3.9",
|
||||
"browserify": "^5.10.0",
|
||||
"primus": "^2.4.8",
|
||||
"express": "^4.9.5",
|
||||
"ws": "^0.4.32",
|
||||
"primus.io": "^3.1.2",
|
||||
"primus-multiplex": "^3.0.3",
|
||||
"primus-emitter": "^3.0.3",
|
||||
"primus-rooms": "^3.1.0",
|
||||
"gulp-express": "^0.1.0"
|
||||
},
|
||||
"license": "Apache License 2.0"
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2014 by Revolution Analytics Inc.
|
||||
*
|
||||
* This program is licensed to you under the terms of Version 2.0 of the
|
||||
* Apache License. This program is distributed WITHOUT
|
||||
* ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
|
||||
* Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0) for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
var express = require('express'),
|
||||
Primus = require('primus.io'),
|
||||
config = require('./config/config'),
|
||||
FraudService = require('./server/service/fraud-service'),
|
||||
app = express(),
|
||||
router = express.Router();
|
||||
|
||||
app.use('/', router);
|
||||
app.use(express.static(__dirname + '/client/app'));
|
||||
|
||||
// -- Start Primus server --
|
||||
var server = require('http').createServer(app);
|
||||
var primus = new Primus(server, { transformer: 'websockets', parser: 'JSON' });
|
||||
|
||||
primus.on('connection', function (spark) {
|
||||
var fraudService = new FraudService(primus);
|
||||
|
||||
router.get('/fraud/score/:tasks', function(req, res) {
|
||||
var tasks = req.params.tasks === 0 ? 1 : req.params.tasks;
|
||||
console.log('REST:/fraud/score/' + tasks + ' called.');
|
||||
|
||||
for(var i = 0; i < tasks; i++) {
|
||||
fraudService.submit(fraudService.buildTask());
|
||||
}
|
||||
|
||||
res.json({ success: true });
|
||||
});
|
||||
|
||||
router.post('/fraud/pool/init/:size', function (req, res) {
|
||||
var size = req.params.size === 0 ? 1 : req.params.size;
|
||||
console.log('REST:/pool/init/' + size + ' called.');
|
||||
|
||||
fraudService.buildPool(size);
|
||||
res.json({ success: true });
|
||||
});
|
||||
});
|
||||
|
||||
primus.on('disconnection', function () {
|
||||
console.log('disconnect...');
|
||||
});
|
||||
|
||||
// -- Start server --
|
||||
server.listen(config.port, function(){
|
||||
console.log('\033[96mlistening on localhost:' + config.port +' \033[39m');
|
||||
});
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2014 by Revolution Analytics Inc.
|
||||
*
|
||||
* This program is licensed to you under the terms of Version 2.0 of the
|
||||
* Apache License. This program is distributed WITHOUT
|
||||
* ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
|
||||
* Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0) for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var rbroker = require('rbroker'),
|
||||
RIn = require('deployr').RInput,
|
||||
print = require('../util/rbroker-print-helper'),
|
||||
config = require('../../config/config');
|
||||
|
||||
var FRAUDMSGTOPIC = '/topic/fraud',
|
||||
MSG_TYPES = {
|
||||
runtime: 'RUNTIMESTATS',
|
||||
score: 'FRAUDSCORE',
|
||||
error: 'CLIENTALERT'
|
||||
};
|
||||
|
||||
var round = function(num) {
|
||||
return +(Math.round(num + 'e+2') + 'e-2');
|
||||
};
|
||||
|
||||
function FraudService(primus) {
|
||||
this.primus = primus;
|
||||
this.broker = null;
|
||||
this.lastAllocatedPoolSize = 0;
|
||||
this.brokerConfig = {
|
||||
maxConcurrentTaskLimit: 0,
|
||||
host: config.host,
|
||||
credentials: config.credentials,
|
||||
releaseGridResources: true,
|
||||
logging: config.logging,
|
||||
pool: {
|
||||
preloadobjectname: config.constants.FRAUD_MODEL,
|
||||
preloadobjectauthor: config.constants.REPO_OWNER,
|
||||
preloadobjectdirectory: config.constants.REPO_DIRECTORY
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
FraudService.prototype = {
|
||||
|
||||
buildPool: function(poolSize) {
|
||||
var self = this;
|
||||
this.brokerConfig.maxConcurrentTaskLimit = poolSize;
|
||||
|
||||
if (!this.broker) {
|
||||
this.attachBroker();
|
||||
} else {
|
||||
this.broker.shutdown()
|
||||
.then(function() {
|
||||
console.log('Pooled: RBroker shutdown `successful`.');
|
||||
self.attachBroker();
|
||||
}, function() {
|
||||
console.log('Pooled: RBroker has shutdown `failure`.');
|
||||
});
|
||||
}
|
||||
|
||||
this.broadcast(this.runtimeStats());
|
||||
},
|
||||
|
||||
buildTask: function(task) {
|
||||
var bal = Math.abs(Math.random() * 25000),
|
||||
trans = Math.abs(Math.random() * 100),
|
||||
credit = Math.abs(Math.random() * 75);
|
||||
|
||||
return rbroker.pooledTask({
|
||||
filename: config.constants.REPO_SCRIPT,
|
||||
directory: config.constants.REPO_DIRECTORY,
|
||||
author: config.constants.REPO_OWNER,
|
||||
routputs: ['x'],
|
||||
rinputs: [RIn.numeric('bal', bal),
|
||||
RIn.numeric('trans', trans),
|
||||
RIn.numeric('credit', credit)
|
||||
]
|
||||
});
|
||||
},
|
||||
|
||||
submit: function(task) {
|
||||
if (this.broker && task) {
|
||||
this.broker.submit(task);
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
if (this.broker) {
|
||||
this.broker.shutdown()
|
||||
.then(function() {
|
||||
console.log('Pooled: RBroker shutdown `successful`.');
|
||||
self.attachBroker();
|
||||
}, function() {
|
||||
console.log('Pooled: RBroker has shutdown `failure`.');
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Push RuntimeStats message over STOMP Web Socket to clients
|
||||
* listening on FRAUDMSGTOPIC.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
broadcast: function(message) {
|
||||
this.primus.send(FRAUDMSGTOPIC, message);
|
||||
},
|
||||
|
||||
/**
|
||||
* Attach and listen on a new PooledTaskBroker.
|
||||
* @api private
|
||||
*/
|
||||
attachBroker: function() {
|
||||
var self = this;
|
||||
|
||||
this.broker = rbroker.pooledTaskBroker(this.brokerConfig)
|
||||
.complete(function(rTask, rTaskResult) {
|
||||
print.results(rTask, rTaskResult);
|
||||
|
||||
// -- notify successful result --
|
||||
self.broadcast(self.buildFraudScore(rTask, rTaskResult));
|
||||
})
|
||||
.error(function(err) {
|
||||
print.error(err);
|
||||
|
||||
// -- notify error --
|
||||
self.broadcast({
|
||||
msgType: MSG_TYPES.error,
|
||||
cause: err,
|
||||
msg: 'The RBroker runtime has indicated an unexpected ' +
|
||||
' runtime error has occured. Cause: ' + err
|
||||
});
|
||||
})
|
||||
.progress(function(stats) {
|
||||
print.stats(stats);
|
||||
self.broadcast(self.runtimeStats(stats));
|
||||
});
|
||||
|
||||
this.lastAllocatedPoolSize = this.broker.maxConcurrency();
|
||||
|
||||
console.log('RBroker pool initialized with ' +
|
||||
this.lastAllocatedPoolSize + ' R sessions.');
|
||||
},
|
||||
|
||||
/**
|
||||
* Private helper methods.
|
||||
* @api private
|
||||
*/
|
||||
runtimeStats: function(stats) {
|
||||
|
||||
var runtime = {
|
||||
msgType: MSG_TYPES.runtime,
|
||||
requestedPoolSize: this.brokerConfig.maxConcurrentTaskLimit,
|
||||
allocatedPoolSize: this.lastAllocatedPoolSize,
|
||||
endpoint: this.brokerConfig.host
|
||||
};
|
||||
|
||||
if (this.brokerConfig.credentials) {
|
||||
runtime.username = this.brokerConfig.credentials.username;
|
||||
}
|
||||
|
||||
if (stats) {
|
||||
runtime.submittedTasks = stats.totalTasksRun;
|
||||
runtime.successfulTasks = stats.totalTasksRunToSuccess;
|
||||
runtime.failedTasks = stats.totalTasksRunToFailure;
|
||||
|
||||
runtime.averageCodeExecution = 0;
|
||||
runtime.averageServerOverhead = 0;
|
||||
runtime.averageNetworkLatency = 0;
|
||||
|
||||
if (stats.totalTasksRunToSuccess > 0) {
|
||||
runtime.averageCodeExecution =
|
||||
round(stats.totalTimeTasksOnCode / stats.totalTasksRunToSuccess);
|
||||
|
||||
var avgTimeOnServer =
|
||||
stats.totalTimeTasksOnServer / stats.totalTasksRunToSuccess;
|
||||
|
||||
runtime.averageServerOverhead =
|
||||
round(avgTimeOnServer - runtime.averageCodeExecution);
|
||||
|
||||
var avgTimeOnCall =
|
||||
stats.totalTimeTasksOnCall / stats.totalTasksRunToSuccess;
|
||||
|
||||
runtime.averageNetworkLatency =
|
||||
round(avgTimeOnCall - avgTimeOnServer);
|
||||
}
|
||||
}
|
||||
|
||||
return runtime;
|
||||
},
|
||||
|
||||
/**
|
||||
* Private helper methods.
|
||||
* @api private
|
||||
*/
|
||||
buildFraudScore: function(rTask, rTaskResult) {
|
||||
var rinputs = rTask.toJSON().rinputs;
|
||||
|
||||
return {
|
||||
msgType: MSG_TYPES.score,
|
||||
success: rTaskResult ? true : false,
|
||||
balance: Math.round(rinputs[0].value),
|
||||
transactions: Math.round(rinputs[1].value),
|
||||
credit: Math.round(rinputs[2].value),
|
||||
score: rTaskResult ? rTaskResult.generatedObjects[0].value : -1
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
module.exports = FraudService;
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2014 by Revolution Analytics Inc.
|
||||
*
|
||||
* This program is licensed to you under the terms of Version 2.0 of the
|
||||
* Apache License. This program is distributed WITHOUT
|
||||
* ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
|
||||
* Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0) for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
var taskType = {
|
||||
DISCRETE: 'DISCRETE',
|
||||
POOLED: 'POOLED',
|
||||
BACKGROUND: 'BACKGROUND'
|
||||
};
|
||||
|
||||
/*
|
||||
* RBroker runtime summary statistics (print) helper class.
|
||||
*/
|
||||
module.exports = {
|
||||
|
||||
/**
|
||||
* Prints RBroker Runtime Stats to console output.
|
||||
*/
|
||||
stats: function(stats) {
|
||||
var displayAvgTimeOnCode = 0,
|
||||
displaySAvgTimeOnServer = 0,
|
||||
displayAvgTimeOnCall = 0,
|
||||
maxConcurrency = stats.maxConcurrency;
|
||||
|
||||
console.log('[progress]-----------------------------------------');
|
||||
console.log('RBroker Activity Summary');
|
||||
console.log('RBroker: Max Concurrency [ ' + maxConcurrency + ' ]');
|
||||
console.log('RBroker: Total Tasks Run [ ' +
|
||||
stats.totalTasksRun + ' ]');
|
||||
console.log('RBroker: Tasks Ok [ ' +
|
||||
stats.totalTasksRunToSuccess + ' ] Fail [ ' +
|
||||
stats.totalTasksRunToFailure + ' ]');
|
||||
|
||||
if (stats.totalTasksRunToSuccess > 0) {
|
||||
displayAvgTimeOnCode =
|
||||
stats.totalTimeTasksOnCode / stats.totalTasksRunToSuccess;
|
||||
displayAvgTimeOnServer =
|
||||
stats.totalTimeTasksOnServer / stats.totalTasksRunToSuccess;
|
||||
displayAvgTimeOnCall =
|
||||
stats.totalTimeTasksOnCall / stats.totalTasksRunToSuccess;
|
||||
}
|
||||
|
||||
console.log('RBroker: Task Average Time On Code [ ' +
|
||||
displayAvgTimeOnCode + ' ]');
|
||||
console.log('RBroker: Task Average Time On Server [ ' +
|
||||
displayAvgTimeOnServer + ' ]');
|
||||
console.log('RBroker: Task Average Time On Call [ ' +
|
||||
displayAvgTimeOnCall + ' ]\n');
|
||||
|
||||
console.log('---------------------------------------------------');
|
||||
},
|
||||
|
||||
/**
|
||||
* Prints errors to console output.
|
||||
*/
|
||||
error: function(err) {
|
||||
console.log('[error]--------------------------------------------');
|
||||
console.log('Status[fail]: cause= ' + err);
|
||||
console.log('---------------------------------------------------');
|
||||
},
|
||||
|
||||
/**
|
||||
* Prints RTaskResult to console output.
|
||||
*/
|
||||
results: function(task, result) {
|
||||
console.log('[completed]----------------------------------------');
|
||||
console.log('Task: ' + task);
|
||||
|
||||
switch (result.type) {
|
||||
|
||||
case taskType.DISCRETE:
|
||||
if (result.success) {
|
||||
console.log('Status[ok]: [ code : ' +
|
||||
result.timeOnCode + ' , server : ' +
|
||||
result.timeOnServer + ' , call : ' +
|
||||
result.timeOnCall + ' ]');
|
||||
} else {
|
||||
console.log('Status[fail]: cause=' + result.failure);
|
||||
}
|
||||
break;
|
||||
|
||||
case taskType.POOLED:
|
||||
if (result.success) {
|
||||
console.log('Status[ok]: [ code : ' +
|
||||
result.timeOnCode + ' , server : ' +
|
||||
result.timeOnServer + ' , call : ' +
|
||||
result.timeOnCall + ' ]');
|
||||
} else {
|
||||
console.log('Status[fail]: cause=' + result.failure);
|
||||
}
|
||||
break;
|
||||
|
||||
case taskType.BACKGROUND:
|
||||
if (result.success) {
|
||||
console.log('Status[ok]: [ server : ' +
|
||||
result.timeOnServer + ' , call : ' +
|
||||
result.timeOnCall + ' ]');
|
||||
} else {
|
||||
console.log('Status[fail]: cause=' + result.failure);
|
||||
}
|
||||
break;
|
||||
}
|
||||
console.log('---------------------------------------------------');
|
||||
}
|
||||
};
|
Загрузка…
Ссылка в новой задаче