1
0
Fork 0
liza/src/server/rater/DslRater.js

230 lines
6.1 KiB
JavaScript

/**
* Handles rating with local, JS-compiled TAME-written raters
*
* Copyright (C) 2010-2019 R-T Specialty, LLC.
*
* This file is part of the Liza Data Collection Framework.
*
* liza is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
var Class = require( 'easejs' ).Class,
EventEmitter = require( '../../events' ).EventEmitter,
DslRaterContext = require( './DslRaterContext' );
module.exports = Class( 'DslRater' )
.extend( EventEmitter,
{
/**
* List of raters
* @type {Array.<Object.<rate>>}
*/
'private _raters': [],
/**
* ResultSet constructor (used in place of a factory)
* @type {Function}
*/
'private _ResultSet': null,
__construct: function( raters, ResultSet )
{
this._raters = raters;
this._ResultSet = ResultSet;
},
'public rate': function( context )
{
if ( this._raters.length === 0 )
{
// TODO: this is a BS answer
callback(
Error( 'No raters are available at this time.' ),
null
);
return this;
}
if ( !( Class.isA( DslRaterContext, context ) ) )
{
throw TypeError( "Invalid DslRaterContext provided" );
}
this._doRate( this._raters.slice( 0 ), context );
},
'private _queueNext': function()
{
var _self = this,
args = arguments;
process.nextTick( function()
{
_self._doRate.apply( _self, args );
} );
},
/**
* Process next available supplier until complete
*/
'private _doRate': function( queue, context )
{
var _self = this,
args = arguments;
var rater = queue.pop();
if ( rater === undefined )
{
this._complete( context );
return;
}
// null means that the rater failed to load
if ( rater === null )
{
// TODO: log error
this._queueNext.apply( this, args );
return;
}
var name = rater.supplier,
meta = rater.rater.meta,
set = this._ResultSet( name );
// give context the chance to augment the data and determine how many
// times we should rate with a given supplier; this continuation will be
// called for each time that the context wishes to perform rating
var data = context.rate( name, meta, function( data, rcontext )
{
try
{
var can_term = context.canTerm();
var single = rater( data, can_term );
// ensures that any previous eligibility errors are cleared out
single.ineligible = '';
single.submit = '';
}
catch ( e )
{
// ineligible.
single = {
ineligible: e.message,
submit: '',
premium: 0.00,
};
}
// give the context to process the result of the rating before we
// perform any of our own processing (that way they can trigger
// submits, etc)
single = context.processResult( single, meta, rcontext );
_self._processSubmits( rater, single, context, data, rcontext )
._flagEligibility( single )
._cleanResult( single );
// purposely omitted third argument
set.addResult( single, rcontext );
}, complete );
// to be called by context when rating is complete for this rater
function complete()
{
context.addResultSet( name, set );
_self._queueNext.apply( _self, args );
}
},
'private _processSubmits': function(
rater, single, context, data, rcontext
)
{
// ineligible results cannot submit, as they did not complete rating
if ( single.ineligible )
{
return this;
}
// submission processing may be disabled (e.g. via a runtime flag)
if ( !( context.canSubmit( single, data, rcontext ) ) )
{
return this;
}
var c = single.__classes;
if ( !( c.submit ) )
{
return this;
}
var submits = [];
for ( cname in c )
{
// Process submit classifications if they are *true*. Classes
// that are suffixed with a dash represent a generated rule that
// should _not_ be displayed to the user
if ( /^submit-.*[^-]$/.test( cname ) && c[ cname ] )
{
submits.push( this.getCdesc( cname, rater, data ) );
}
}
single.submit = submits.join( '; ' );
return this;
},
'private _flagEligibility': function( single )
{
// from a broker's perspective
single._unavailable = ( single.submit || single.ineligible )
? '1'
: '0';
return this;
},
'private _cleanResult': function( result )
{
return this;
},
'virtual public getCdesc': function( cname, rater, data, default_value )
{
default_value = ( default_value === undefined )
? cname
: default_value;
return rater.rater.classify.desc[ cname ] || default_value;
},
'private _complete': function( context )
{
// let the context know that we're finished rating
context.complete();
},
} );