Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Socket
Sign inDemoInstall

clues

Package Overview
Dependencies
Maintainers
1
Versions
158
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

clues - npm Package Compare versions

Comparing version 2.1.0-beta2 to 2.1.0

util/bluebird.js

13

clues.js

@@ -26,3 +26,3 @@ // clues.js (c) 2009-2014 Ziggy.jonsson.nyc@gmail.com @license MIT

function clues(logic,facts) {
function clues(logic,facts,options) {
if (!(this instanceof clues))

@@ -32,2 +32,3 @@ return new clues(logic,facts);

this.facts = facts || {};
this.options = options || {};
this.self = this;

@@ -50,6 +51,8 @@ }

if (self.logic[ref] === undefined) {
if (local[ref] !== undefined) return self.Promise.fulfilled(local[ref]);
else if (self[ref] !== undefined && typeof self[ref] !== 'function') return self.Promise.fulfilled(self[ref]);
else if (ref === 'local') return self.Promise.fulfilled(local);
else return self.Promise.rejected({ref: ref, caller: caller, message: ref+' not defined', name: 'Undefined'});
if (caller !== '__user__') {
if (local[ref] !== undefined) return self.Promise.fulfilled(local[ref]);
if (self[ref] !== undefined && typeof self[ref] !== 'function') return self.Promise.fulfilled(self[ref]);
}
if (typeof(self.options.fallback) === 'function') return self.facts[ref] = self.options.fallback.call(this,ref,local,caller);
return self.Promise.rejected({ref: ref, caller: caller, message: ref+' not defined', name: 'Undefined'});
}

@@ -56,0 +59,0 @@

{
"name": "clues",
"version": "2.1.0-beta2",
"version": "2.1.0",
"description": "Lightweight logic tree solver using promises.",

@@ -5,0 +5,0 @@ "keywords": [

@@ -25,3 +25,3 @@ ##Breaking changes in version 2.0:

### `clues([logic],[facts])`
### `clues([logic],[facts],[options])`
Creates a new clues object based on a particular logic (set of functions and values by reference) and facts (associative arrays of known values). Logic and fact objects can be defined/modified later as they are public variables of the clues object.

@@ -33,2 +33,4 @@

An optional fallback function can be defined in the options object. This function will be called whenever a reference can not be found in current fact/logic space and must return a promise.
### `clues.logic = {}`

@@ -35,0 +37,0 @@ Key/value dictionary of logic functions and/or values. Functions in the logic object must only contain arguments names that correspond to either facts or as other logic functions/values. Each logic function must either return a value or a promise.

@@ -6,3 +6,3 @@ var clues = require("../clues"),

var f = {a: 1, b: 2},
l = {c: 3, d: 4, l : function(local) { return local; }},
l = {c: 3, d: 4, l : function(a,b) { return {a: a,b: b}; }},
c = clues(l,f);

@@ -9,0 +9,0 @@

var clues = require('../clues'),
Promise = require('bluebird');
function stringifyError(e) {
return {
message : e.message,
ref : e.ref,
caller : e.caller,
stack : e.stack,
error : true
};
}
module.exports = function(api,options) {
api = api || {};
options = options || {};
function stringifyError(e) {
var message = {
message : (!options.debug && e.stack) ? 'Internal Error' : e.message,
ref : e.ref,
error : true
};
function multi(data,self,res,req) {
res.setHeader('content-type','application/ocetstream');
res.write('{\n\t"multi":true\t\n');
if (options.debug) {
message.stack = e.stack;
message.caller = e.caller;
}
data = data.split(',')
.map(function(ref) {
return self.solve(ref)
.catch(stringifyError)
.then(function(d) {
res.write(', "'+ref+'" : '+JSON.stringify(d)+'\t\n');
});
});
return message;
}
req.on('close',function() {
data.forEach(function(d) {
d.cancel();
});
});
return function(req,res) {
req.body = req.body || {};
res.set('Transfer-Encoding','chunked');
res.set('Content-Type', 'application/json; charset=UTF-8');
res.set('Cache-Control', 'no-cache, no-store, max-age=0');
res.write('{ \t\n\n');
if (typeof(res.flush) == 'function') res.flush();
return Promise.all(data)
.then(function(d) {
res.write('}');
res.end();
});
}
Object.keys(req.query || {})
.forEach(function(key) {
req.body[key] = req.query[key];
});
if (options.safe) {
Object.keys(req.body).forEach(function(key) {
if (api[key]) delete req.body[key];
});
}
function help(self) {
return Object.keys(self.logic);
}
var c = clues(api,req.body);
module.exports = function(api) {
api = api || {};
api.multi = multi;
api.help = help;
var data = req.param("fn")
.split(',')
.map(function(ref) {
return c.solve(ref,{res:res,req:req},'__user__')
.catch(stringifyError)
.then(function(d) {
res.write(' "'+ref+'" : '+JSON.stringify(d)+',\t\n');
if (typeof(res.flush) == 'function') res.flush();
});
});
return function(req,res) {
res.set('Content-Type','application/json');
clues(api,req.query)
.solve(req.param("fn"),{req:req,res:res})
.catch(stringifyError)
req.on('close',function() {
data.forEach(function(d) {
d.cancel();
});
});
return Promise.all(data)
.then(function(d) {
if (d && !d.error && req.param('select')) {
req.param('select')
.split('.')
.forEach(function(key) {
d = d && d[key];
});
}
res.end(JSON.stringify(d,null,2));
res.write(' "__end__" : true\t\n}');
res.end();
});
};
};
/* global angular, self, d3, dpl, Promise */
//start
(function() {
var UNIQUE_ID=0;
var weight = 0.4;
var reptile = {widgets:{}};
var reptile = self.reptile = {widgets:{}};
var reArgs = /function.*?\((.*?)\).*/;
function matchArgs(fn) {
if (fn.__args__) return fn.__args__;
var match = reArgs.exec(fn.prototype.constructor.toString());
return fn.__args__ = match[1].replace(/\s/g,'').split(",");
}
angular.module('reptile',[]);
Promise.onPossiblyUnhandledRejection(function(){});
/* global reptile,self,report*/
var reArgs = /function.*?\((.*?)\).*/;
function matchArgs(fn) {
if (fn.__args__) return fn.__args__;
var match = reArgs.exec(fn.prototype.constructor.toString());
return fn.__args__ = match[1].replace(/\s/g,'').split(",");
}
function serialize(obj) {
var str = [];
for(var p in obj)
if (obj.hasOwnProperty(p)) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
}
/* global Promise,d3*/
function serialize(obj) {
var str = [];
for(var p in obj)
if (obj.hasOwnProperty(p)) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
}
function api(inputs,applyFn) {

@@ -50,3 +19,2 @@ var queue = [],

inputs = inputs || {};

@@ -69,3 +37,3 @@

var key = m[1], value = JSON.parse(m[2]);
console.log(key,data)
if (!data[key] || !data[key].promise)

@@ -80,32 +48,24 @@ data[key] = Promise.defer();

}
})
});
}
var r = new XMLHttpRequest();
var buffer = '',last = 0;
r.open('POST','/api/'+fns.join(','),true);
r.setRequestHeader('Content-Type','application/json;charset=UTF-8');
r.send(JSON.stringify(inputs));
r.onprogress = function(d) {
if (r.responseText.length) buffer += r.responseText.slice(last);
var items = buffer.split('\t\n');
processItems(items.slice(0,items.length-1));
buffer = items.slice(items.length-1)[0];
last = r.responseText.length;
};
var r = new XMLHttpRequest();
var buffer = "",last = 0;
r.open('GET','/api/multi?data='+fns.join(',')+'&'+serialize(inputs),true);
r.send()
r.onprogress = function(d) {
console.log(r.responseText)
if (r.responseText.length) buffer += r.responseText.slice(last);
//console.log('progress',buffer)
var items = buffer.split('\t\n');
processItems(items.slice(0,items.length-1));
buffer = items.slice(items.length-1)[0]
last = r.responseText.length
}
r.onload = function() {
console.log(JSON.stringify(last,r.responseText))
if (r.responseText.length) buffer += r.responseText.slice(last);
console.log('buffer',buffer)
processItems(buffer.split('\t\n'));resolve('ok')
};
r.onload = function() {
if (r.responseText.length) buffer += r.responseText.slice(last);
processItems(buffer.split('\t\n'));
resolve('ok');
};
})

@@ -141,12 +101,10 @@ .then(function(d) {

api.renderAll = function(d) {
d = d3.select(d[0]).selectAll('[data-reptile]');
var items = d[0].map(function(element) {
element._reptile_root = d3.select(d[0]);
return api.render(element);
});
var selection = (d || window).querySelectorAll('[data-reptile]'),
items = [].map.call(selection,function(d) {
return api.render(d);
});
return Promise.settle(items);
};
api.render = function(d) {
var element = d3.select(d).node();
api.render = function(element) {
var keys = element.dataset.reptile.split(','),key;

@@ -183,13 +141,8 @@

if (keys.length) return renderKey();
d3.select(element).text(key+' error '+(e.message || e));
element.innerHTML='<p>'+key+' error '+(e.message || e);
throw e;
});
}
return renderKey();
};
return api;

@@ -200,1360 +153,2 @@ }

/* global reptile, d3 */
reptile.format = {
date : function(d) { return d3.time.format('%m/%d/%y')(new Date(d)); },
dround : function(d) { return "$"+d3.format(",.0f")(d); },
round : function(d) { return d3.format(",.2f")(d); },
integ : function(d) { return d3.format(",.f")(d);},
aperc : function(d) { return d3.format(",.2f")(d)+"%";},
perc : d3.format(".2%")
};
/* global reptile, d3 */
// Field headers and reptile.formats
function notZero(d) {
return d;
}
function maxLen(n) {
return function(d) {
return d && d.slice(0,n);
};
}
function dqDate(d) {
if (!d) return '';
d = d.toString();
return d.slice(0,4)+'/'+d.slice(4,6)+'/'+d.slice(6);
}
reptile.fields = {
LOAN_NO : { txt: 'Loan No',fmt:function(d) { return +d;}},
POOL_ID : { txt: 'Pool no'},
CITY : {txt:'City'},
ORIG_DATE : {txt:'Orig. Date',fmt : reptile.format.date},
ORIG_AMT : {txt:'Loan Amount',fmt : reptile.format.dround},
APPRAISAL : {fmt : reptile.format.dround},
MATURITY_DATE : {txt:'Maturity',fmt: reptile.format.date},
ORIG_INTEREST : {txt:'Rate',fmt:reptile.format.aperc},
ORIG_LTV : {txt:'LTV',fmt:reptile.format.aperc},
ORIG_COMB_LTV : {txt:'Combined LTV',fmt:reptile.format.aperc},
FICO : {txt:'FICO'},
SECOND_AMT : {txt:'2nd Lien',fmt:reptile.format.dround,filter:function(d) { return d; }},
FIRST_AMT : {txt:'1st Lien',fmt:reptile.format.dround,filter:function(d) { return d; }},
// Comps
DT : {txt:'Date',fmt: reptile.format.date},
DIST : {txt:'Dist',fmt: reptile.format.round},
PSQFT : {txt:'PSQ',fmt:d3.format(",.0f")},
AMT : {txt:'Price',fmt:reptile.format.dround},
PRICE : {txt:'Price',fmt:reptile.format.dround},
SA_SQFT : {txt:'SQFT',fmt:d3.format(",.0f")},
// Timeline
DIST_DATE : {txt:'Date',fmt:reptile.format.date},
BALANCE : {txt:'Balance',fmt:reptile.format.dround},
INV_BALANCE : {txt:'Inv. Bal.',fmt:reptile.format.dround},
SCH_PNI : {txt:'PNI',fmt:reptile.format.dround},
RATE : {txt:'Rate',fmt:reptile.format.aperc},
LAST_MOD_RATE : {txt:'Last Mod Rate',fmt:reptile.format.aperc},
NEXT_DUE_DATE : {txt:'Due date',fmt:reptile.format.date},
DATE : {fmt:reptile.format.date},
PAYOFF_DATE : {txt:'Payoff Dt',fmt:reptile.format.date},
PAYOFF_AMT : {txt:'Payoff Amt',fmt:reptile.format.dround},
CURR_LOSS : {txt:'Loss',fmt:reptile.format.dround},
CUMUL_LOSS : {txt:'Cumul. Loss',fmt:reptile.format.dround},
CURR_BAL : {txt:'Final Bal',fmt:reptile.format.dround},
CURR_SEV : {txt:'SEV',fmt:reptile.format.perc},
MBA_STATUS : {txt:'Status'},
DLQ_STATUS : {txt:'DLQ'},
OTS : {txt:'OTS'},
EST_ADVANCE : {txt:'Est. Advance',fmt:reptile.format.dround},
CURR_DIST_DATE : {txt:'Dist Date',fmt:reptile.format.date},
// Transactions
SR_BUYER : {txt:'Buyer',fmt:maxLen(15)},
SR_SELLER : {txt:'Seller',fmt:maxLen(15)},
SR_DATE_TRANSFER : {txt:'Transfer',fmt:dqDate},
SR_DATE_FILING : {txt:'Filing',fmt:dqDate},
SR_LNDR_FIRST_NAME_1 : {txt: 'Lender 1'},
SR_LOAN_VAL_1 : {txt:'Loan Amt 1',fmt:reptile.format.dround,filter:notZero},
SR_LOAN_VAL_2 : {txt:'Loan Amt 2',fmt:reptile.format.dround,filter:notZero},
SR_VAL_TRANSFER : {txt:'Transfer Amount',fmt:reptile.format.dround,filter:notZero},
MOD_DATE : {txt:'Date',fmt:reptile.format.date},
PRE_AMT : {txt:'Prior Balance',fmt:reptile.format.dround},
POST_BAL : {txt:'Modified Balance',fmt:reptile.format.dround},
PRE_INT : {txt:'Prior Interest',fmt:reptile.format.aperc},
POST_INT : {txt:'Modified Interest',fmt:reptile.format.aperc},
// Assessor
ADDR : {txt:'Address'},
SA_CITY : {txt:'City'},
SA_STATE : {txt:'State'},
SA_ZIP : {txt:'Zip Code'},
SA_LOTSIZE : {txt:'Lot Size',fmt:reptile.format.dround},
SA_NBR_BATH : {txt:'# Bathrooms'},
SA_NBR_BEDRMS : {txt: '# Bedrooms'},
HOUSE_SQFT : {txt:'House Size (sqft)',fmt:reptile.format.integ},
HOUSE_ACRES : {txt:'Lot Size (acres)',fmt:reptile.format.round},
SA_VAL_ASSD : {txt:'Assessment',fmt:reptile.format.dround},
SA_TAX_VAL : {txt:'Property Tax',fmt:reptile.format.dround},
txt : {txt:'Event'},
SA_YR_BLT : {txt:'Year Built'},
USE_CODE_STD_TXT : {txt:'Property Type'},
SA_BLDG_CODE_TXT : {txt:'Structure'},
SA_EXTERIOR_1_CODE_TXT : {txt:'Exterior'},
SA_FOUNDATION_CODE_TXT : {txt:'Foundation'},
TXT : {txt:'Item'},
BLANK : {txt:' '},
AMOUNT : {txt:'Amount',fmt:reptile.format.dround},
PERC_BAL : {txt:'% Bal.',fmt:reptile.format.perc}
};
// Returns the title for a given field, or a non-capitalized version with spaces, if not defined
reptile.fieldName = function fieldName(field) {
return (reptile.fields[field] && reptile.fields[field].txt) || (field.slice(0,1)+field.slice(1).toLowerCase()).replace(/_/g,' ');
};
// Returns a value for a field, reptile.formatted correctly (if defined)
reptile.value = function value(field,d) {
return (d !== undefined && reptile.fields[field] && reptile.fields[field].fmt) ? reptile.fields[field].fmt(d) : d;
};
// URLEncode an object
function serialize(obj) {
var str = [];
for (var p in obj)
str.push(encodeURIComponent(p)+"="+encodeURIComponent(obj[p]));
return str.join("&");
}
// Extract argument names from a function
var reArgs = /function.*?\((.*?)\).*/;
function matchArgs(fn) {
var match = reArgs.exec(fn.prototype.constructor.toString());
return match && match[1].replace(/\s/g,'').split(",");
}
/* global reptile */
/* global reptile, d3 */
reptile.item = function item(facts) {
d3.select(this).text(facts);
};
/* global reptile, d3 */
// ## List
// Renders input data as an itemized list
reptile.list = function list(data,fields,max) {
fields = fields || Object.keys(data);
data = fields
.filter(function(field) {
if (data[field] === null || data[field] === undefined) return false;
if (reptile.fields[field] && reptile.fields[field].filter && !reptile.fields[field].filter(data[field])) return false;
return true;
})
.map(function(field) {
return [reptile.fieldName(field) , reptile.value(field,data[field])];
})
.slice(0,max || Infinity);
d3.select(this)
.append("table").classed("list",true)
.selectAll("tr")
.data(data)
.enter()
.append("tr")
.selectAll("td")
.data(Object)
.enter()
.append("td").text(Object);
};
/* global reptile, d3 */
// ## Table
// Renders an array as a table. Fields are optional
reptile.table = function table(data,fields,max) {
// If fields are not defined we loop through the whole dataset and fetch all the keys
if (!fields) {
fields = {};
data.forEach(function(d) {
Object.keys(d).forEach(function(d) {
fields[d] = true;
});
});
fields = Object.keys(fields);
}
// Allow the order to be reversed
if (this.dataset && this.dataset.reverse) data = data.reverse();
data = data.slice(0,max || Infinity);
var tbl = d3.select(this).append("table").classed("reptable",true);
tbl.append("thead")
.append("tr")
.selectAll("th")
.data(fields.map(reptile.fieldName))
.enter()
.append("th")
.text(Object);
tbl.append("tbody")
.selectAll("tr")
.data(data)
.enter()
.append("tr")
.selectAll("td")
.data(fields)
.enter()
.append("td")
.html(function(field,i,j) {
return reptile.value(field,data[j][field]);
});
};
function wrap(fn) {
return function(facts) {
facts = facts[this.dataset.input];
var select = this.dataset.select,
fields = this.dataset.fields && this.dataset.fields.split(",");
if (select && select.length) select.split(".")
.forEach(function(key) {
facts = facts[key];
});
fn.call(this,facts,fields,this.dataset.max);
};
}
reptile.widgets.table = wrap(reptile.table);
reptile.widgets.list = wrap(reptile.list);
reptile.widgets.item = wrap(reptile.item);
/* global reptile, d3, L */
var tiledef = {
'SAT' : { link : 'https://{s}.tiles.mapbox.com/v3/zjonsson.hk6i67ff/{z}/{x}/{y}.png' },
'OSM' : { link : 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'},
'MQ' : { link: 'https://{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png'},
'MAPBOX' : { link : 'https://{s}.tiles.mapbox.com/v3/zjonsson.map-8g2l2dg2/{z}/{x}/{y}.png'}
};
var maxZoom = 18;
reptile.widgets.map = function(location) {
var detail = +this.dataset.detail || 1;
d3.select(this).classed("map",true).style("zoom",1/detail);
// Define the map
var map = this.map = this.map || L.map(this,{zoomControl:false,maxZoom:maxZoom});
if (this.bounds) map.fitBounds(this.bounds);
else map.setView({lat:location.lat,lng:location.lng},this.dataset.zoom || 4);
map.attributionControl.setPrefix("");
map._initPathRoot();
var g = d3.select(this).select("svg").append("g").attr("class","canvas");
var tiles = this.dataset.tiles;
tiles = (tiledef[tiles] && tiledef[tiles].link) || tiles || 'https://{s}.tiles.mapbox.com/v3/zjonsson.map-6qn6dl9t/{z}/{x}/{y}.png';
// Set map tiles
if (tiles == "vector") {
new L.TileLayer.d3_geoJSON('http://{s}.tile.openstreetmap.us/vectiles-highroad/{z}/{x}/{y}.json',{class:"road"})
.addTo(map);
new L.TileLayer.d3_geoJSON('http://tile.openstreetmap.us/vectiles-water-areas/{z}/{x}/{y}.json',{class:"water"})
.addTo(map);
} else L.tileLayer(tiles).addTo(map);
// Icon of the main house
var size = 30 * detail;
var main_house = g.append("image")
.attr("height",size).attr("width",size)
.attr("xlink:href","/img/house_icon.svg");
function refresh() {
// Update location of main house
var point = map.latLngToLayerPoint({lat:location.lat,lng:location.lng});
main_house.attr("transform","translate("+(point.x-size/2)+","+(point.y-size/2)+")");
}
map.on("moveend",refresh);
refresh();
return map;
};
/* global reptile, d3 */
reptile.widgets.comps_table = function(comps) {
var self = d3.select(this);
self.append("span").classed("caption",true).text("Relevant Comps - Detail");
reptile.table.call(this,comps.RECORDS,['NO','DIST','DT','AMT','SA_SQFT','PSQFT'],+this.dataset.max);
};
reptile.widgets.comps_orig_table = function(comps_orig) {
var self = d3.select(this);
self.append("span").classed("caption",true).text("Comps at origination - Detail");
reptile.table.call(this,comps_orig.RECORDS,['NO','DIST','DT','AMT','SA_SQFT','PSQFT'],+this.dataset.max);
};
reptile.widgets.comps_payoff_table = function(comps_payoff) {
if (comps_payoff.err) return d3.select(this).text(comps_payoff.err);
var self = d3.select(this);
self.append("span").classed("caption",true).text("Comps");
reptile.table.call(this,comps_payoff.RECORDS,['NO','DIST','DT','AMT','SA_SQFT','PSQFT']);
};
reptile.widgets.comps_mod_table = function(comps_mod) {
if (comps_mod.err) return d3.select(this).text(comps_mod.err);
var self = d3.select(this);
self.append("span").classed("caption",true).text("Comps");
reptile.table.call(this,comps_mod.RECORDS,['NO','DIST','DT','AMT','SA_SQFT','PSQFT']);
};
function comps_summary(comps) {
d3.select(this).append("div").classed("caption",true).text("Comps Summary");
var table = d3.select(this).append("table");
table.append("thead")
.append("tr")
.selectAll("th")
.data(["","Transaction","Using Comps"])
.enter()
.append("th")
.text(Object);
var data = [ ["Price / Sqft",reptile.format.round(comps.PSQFT.STATED),reptile.format.round(comps.PSQFT.COMPS)] ];
if (comps.LTV) data.push(["LTV",reptile.format.perc(comps.LTV.STATED),reptile.format.perc(comps.LTV.COMPS)]);
data.push(["Value",reptile.format.dround(comps.VALUE.STATED),reptile.format.dround(comps.VALUE.COMPS)]);
data.push(["Difference",reptile.format.dround(comps.VALUE.STATED - comps.VALUE.COMPS),""]);
table.append("tbody")
.selectAll("tr")
.data(data)
.enter()
.append("tr")
.selectAll("td")
.data(Object)
.enter()
.append("td")
.text(Object);
}
reptile.widgets.comps_ltv_summary = function(comps,sqft,mtg_last) {
d3.select(this).append("div").classed("caption",true).text("Comps Summary");
var table = d3.select(this).append("table");
table.append("tbody")
.selectAll("tr")
.data([
["Price / Sqft",reptile.format.round(comps.median)],
["Value",reptile.format.dround(sqft*comps.median)],
["Balance",reptile.format.dround(mtg_last.BALANCE)],
["LTV",reptile.format.perc(mtg_last.BALANCE / (sqft*comps.median))]
])
.enter()
.append("tr")
.selectAll("td")
.data(Object)
.enter()
.append("td")
.text(Object);
};
reptile.widgets.comps_orig_summary = function(comps_orig,sqft,mtg_timeline,mtg_orig) {
comps_summary.call(this,comps_orig,sqft,mtg_timeline,mtg_orig);
};
reptile.widgets.comps_summary = function(comps,sqft) {
comps.PSQFT = {COMPS : comps.MEDIAN};
comps.LTV = {};
comps.VALUE = {COMPS: comps.ESTIMATE};
comps_summary.call(this,comps,sqft);
};
reptile.widgets.comps_payoff_summary = function(comps_payoff,sqft,mtg_timeline,mtg_orig) {
comps_summary.call(this,comps_payoff,sqft,mtg_timeline,mtg_orig);
};
reptile.widgets.comps_mod_summary = function(comps_mod,sqft,mtg_timeline,mtg_orig) {
comps_summary.call(this,comps_mod,sqft,mtg_timeline,mtg_orig);
};
function comps_map(comps,location) {
var b,o;
var charge = +d3.select(this).attr('data-charge') || 130;
var detail = +this.dataset.detail || 1;
if (comps.err) return d3.select(this).text(comps.err);
var select = this.dataset.select || "RECORDS";
var records = comps;
if (select) select.split(".")
.forEach(function(key) {
records = records[key];
});
records = records.slice(0,this.dataset.max || Infinity);
// Calculate boundaries
var latB = d3.extent(records,function(d) { return d.LAT;}),
lngB = d3.extent(records,function(d) { return d.LNG;}),
bounds = [[latB[0],lngB[0]],[latB[1],lngB[1]]];
this.bounds = bounds;
var map = reptile.widgets.map.call(this,location);
var g = d3.select(this).select(".canvas");
// Define the labelForce
var radius = 10;
var labelForce = d3.force_labels()
.linkDistance(0)
.gravity(0)
.charge(-charge*Math.pow(detail,2))
.friction(0.8)
.on("tick",function() {
anchors.each(function(d) {
d = d.labelPos;
d.x = Math.min(Math.max(b.min.x+radius,d.x),b.max.x-radius);
d.y = Math.min(Math.max(b.min.y+radius,d.y),b.max.y-radius);
});
});
// Place anchors of the comps
var anchors = g.selectAll(".comp_house")
.data(records).enter()
.append("circle")
.attr("class",function(d) { return "comp_house "+(d.PSQFT > comps.BENCHMARK ? "over" : (d.PSQFT <= comps.BENCHMARK ) ? "under" : "none"); })
.attr("r",4)
.style("stroke","black")
.style("stroke-width","0.5px");
// Define links and labels
var links = g.selectAll(".link")
.data(records).enter()
.append("line")
.attr("class","link")
.style("stroke-width","0.5px")
.style("stroke","black");
var labels = g.selectAll(".labels")
.data(records).enter()
.append("g")
.classed("labels",true)
.attr("class",function(d) { return "labels "+(d.PSQFT > comps.BENCHMARK ? "over" : (d.PSQFT <= comps.BENCHMARK) ? "under" : "none"); });
labels.append("circle")
.attr("r",radius)
.style("stroke","black");
labels.append("text")
.text(function(d,i) { return i+1;})
.style("text-anchor","middle")
.style("font-size","80%")
.attr("dy","0.4em");
function refresh() {
// Update pixel points of all the comps
records.forEach(function(d) {
d.point = map.latLngToLayerPoint({lat:d.LAT,lng:d.LNG});
});
// Calculate the pixel bounding box and min/max
b = map.getPixelBounds();
o = map.getPixelOrigin();
var p= 30;
b.max.y -= o.y;
b.min.y -= o.y;
b.min.x -= o.x+p;
b.max.x -= o.x+p;
// Relocate the anchors
anchors.attr("cx",function(d) { return d.point.x;})
.attr("cy",function(d) { return d.point.y;})
.call(labelForce.update);
// Tick the labelForce
labelForce.start();
// while (labelForce.alpha()>0.05 && i++ < 100) labelForce.tick();
function relocate() {
// Relocate labels and links
labels.attr("transform",function(d) { return "translate("+d.labelPos.x+" "+d.labelPos.y+") scale("+detail+")"; });
links.attr("x1",function(d) { return d.labelPos.x;})
.attr("y1",function(d) { return d.labelPos.y;})
.attr("x2",function(d) { return d.anchorPos.x;})
.attr("y2",function(d) { return d.anchorPos.y;});
}
labelForce.on('tick',relocate);
}
map.on("moveend",refresh);
refresh();
}
reptile.widgets.comps_map = function(comps,location) {
this.dataset.input = comps;
comps.BENCHMARK = comps.BENCHMARK || comps.MEDIAN;
comps_map.call(this,comps,location);
};
reptile.widgets.comps_payoff_map = function(comps_payoff,location) {
this.dataset.input = comps_payoff;
comps_map.call(this,comps_payoff,location);
};
reptile.widgets.comps_orig_map = function(comps_orig,location) {
d3.select(this).classed('compsorig',true);
this.dataset.input = comps_orig;
comps_map.call(this,comps_orig,location);
};
reptile.widgets.comps_mod_map = function(comps_mod,location) {
this.dataset.input = comps_mod;
comps_map.call(this,comps_mod,location);
};
/* global reptile, d3 */
reptile.widgets.est_rent = function(est_rent) {
var svg = d3.select(this).append("div").append("svg").attr("height","350").attr("width","350");
var data = est_rent.map(function(d) {
return {x:new Date(d.DT),y:d.EST_RENT};
});
var chart = reptile.baseChart(svg)
.setTitle("chart","Estimated Monthly Rent")
.scale("x",d3.time.scale());
chart.enter([data]).append("path").attr("class","line");
chart.render();
};
/* global d3, reptile */
var UNIQUE_ID = 0;
var weight = 0.4;
reptile.widgets.capstructure = function(mtg_orig,mtg_timeline,property_history) {
UNIQUE_ID++;
mtg_timeline = [{DIST_DATE:mtg_orig.ORIG_DATE,BALANCE:mtg_orig.ORIG_AMT}].concat(mtg_timeline.slice());
property_history = property_history.filter(function(d) {
return d.YM > 290;
});
var lastDate;
var max=0,lastPrice,step = 1.2;
var history = property_history.map(function(d) {
if (!lastPrice) lastPrice = d.PRICE;
lastPrice = weight * Math.max(lastPrice/step, Math.min(d.PRICE,lastPrice*step)) + (1-weight) * lastPrice;
max = Math.max(max,lastPrice);
lastDate = new Date(1980,d.YM,1);
return {
x : new Date(1980,d.YM,1),
y0 : 0,
y1 : lastPrice
};
});
if (mtg_timeline.length == 1) mtg_timeline.push({DIST_DATE:lastDate,BALANCE:mtg_orig.ORIG_AMT});
history = history.filter(function(d) {
return d.x.valueOf() > new Date(mtg_orig.ORIG_DATE) && d.x < new Date(mtg_timeline[mtg_timeline.length-1].DIST_DATE);
});
var prepaid;
mtg_timeline = mtg_timeline.filter(function(d) {
if (prepaid) return false;
if (d.MBA_STAT == '0') prepaid = true;
return new Date(d.DIST_DATE) <= lastDate;
});
var capital = mtg_timeline.map(function(d) {
var bal = d.INV_BALANCE || d.BALANCE,
first = (mtg_orig.LIEN == 2) ? mtg_orig.OTHER_AMT : bal,
second = (mtg_orig.LIEN == 2) ? bal : mtg_orig.OTHER_AMT;
max = Math.max(max,first+second);
return {
x : new Date(d.DIST_DATE),
y0 : 0,
y1 : first+second,
first : first,
second : second
};
});
var firstLien = capital.map(function(d) {
return {x:d.x,y0:0,y1:d.first};
}),
secondLien = capital.map(function(d) {
return {x:d.x,y0:d.first,y1:d.y1};
}),
clipCapitalup = capital.map(function(d) {
return {x:d.x, y0:d.y1,y1:max};
}),
clipHistoryUp = history.map(function(d) {
return {x:d.x,y0:d.y1,y1:max};
}),
clipHistoryDown = history.map(function(d) {
return {x:d.x,y0:0,y1:d.y1};
});
var svg = d3.select(this);
var chart = reptile.baseChart(svg)
.setTitle("chart","Est. Capital Structure")
.scale("x",d3.time.scale())
.add([clipCapitalup],function(g) {
g.append("clipPath")
.attr("id","capitalup"+UNIQUE_ID)
.append("path");
})
.add([clipHistoryUp],function(g) {
g.append("clipPath")
.attr("id","historyup"+UNIQUE_ID)
.append("path");
})
.add([clipHistoryDown],function(g) {
g.append("clipPath")
.attr("id","historydown"+UNIQUE_ID)
.append("path");
})
.add([history],function(g) {
g.append("path")
.attr("class","line")
.style("fill","green")
.attr("data-legend","Positive Equity")
.attr("clip-path","url("+document.location+"#capitalup"+UNIQUE_ID+")");
})
.add([capital],function(g) {
g.append("path")
.attr("class","line")
.attr("data-legend","Negative Equity")
.attr("clip-path","url("+document.location+"#historyup"+UNIQUE_ID+")")
.style("fill","red");
})
.add([firstLien],function(g) {
g.append("path")
.style("fill","blue")
.attr("data-legend","First Lien")
.attr("clip-path","url("+document.location+"#historydown"+UNIQUE_ID+")");
})
.add([firstLien],function(g) {
g.append("path")
.attr("class","line");
});
if (capital[0].second > 100 ) {
chart = chart
.add([secondLien],function(g) {
g.append("path")
.style("fill","LightSkyBlue")
.attr("data-legend","Second Lien")
.attr("clip-path","url("+document.location+"#historydown"+UNIQUE_ID+")");
})
.add([secondLien],function(g) {
g.append("path")
.attr("class","line");
})
.add([history],function(g) {
g.append("path")
.attr("class","line");
})
.add((mtg_orig.LIEN == 2) ? [firstLien] : [secondLien],function(g) {
g.append('path')
.style('fill','white')
.attr('opacity',0.3);
});
}
chart.axis('x',function(d) { d.ticks(6); })
.tickFormat('y',d3.format('.2s'))
.render();
};
/* global reptile, d3 */
reptile.widgets.transaction_orig = function(_transaction_orig) {
var self = d3.select(this);
self.append("div").classed("caption",true).text('Matched Transaction');
var div = self.append("div");
reptile.list.call(div.node(),_transaction_orig,['SR_BUYER','SR_SELLER','SR_VAL_TRANSFER','SR_DATE_TRANSFER','SR_DATE_FILING','SR_LNDR_FIRST_NAME_1','SR_LOAN_VAL_1']);
};
reptile.widgets.transaction_payoff = function(transaction_payoff) {
d3.select(this).append("div").classed("caption",true).text('Matched Liquidation');
var div = d3.select(this).append("div");
reptile.list.call(div.node(),transaction_payoff,['SR_BUYER','SR_SELLER','SR_VAL_TRANSFER','SR_DATE_TRANSFER','SR_DATE_FILING','SR_LNDR_FIRST_NAME_1','SR_LOAN_VAL_1','CITY','STATE','ZIP']);
};
reptile.widgets.transaction_mod = function(comps_mod) {
d3.select(this).append("div").classed("caption",true).text('Modification Detail');
var div = d3.select(this).append("div");
reptile.list.call(div.node(),comps_mod.MOD,['MOD_DATE','PRE_AMT','POST_BAL','PRE_INT','POST_INT']);
};
reptile.widgets.assessor = function(_assessor,_assessor_address,mtg_orig) {
var self = d3.select(this);
var data = {};
_assessor = _assessor || {};
_assessor_address = _assessor_address || {};
//_assessor_address = _assessor_address || {};
Object.keys(_assessor).forEach(function(key) { data[key] = _assessor[key];});
Object.keys(mtg_orig).forEach(function(key) { data[key] = mtg_orig[key];});
Object.keys(_assessor_address).forEach(function(key) { data[key] = _assessor_address[key];});
if (data.FULL_ADDRESS) data.ADDR = data.FULL_ADDRESS;
else data.ADDR = 'Undetermined';
data.HOUSE_SQFT = data.SA_SQFT;
data.HOUSE_ACRES = data.SA_LOTSIZE / 43560;
self.append("div").classed("caption",true).text('Matched Property');
var div = self.append('div');
reptile.list.call(div.node(),data,['ADDR','CITY','STATE','ZIP','USE_CODE_STD_TXT','HOUSE_SQFT','HOUSE_ACRES','SA_YR_BLT','SA_NBR_BEDRMS','SA_NBR_BATH','SA_BLDG_CODE_TXT','SA_EXTERIOR_1_CODE_TXT','SA_FOUNDATION_CODE_TXT']);
};
/* global reptile, d3, dpl */
reptile.widgets.joint = function(mbs_timeline,property_history,equifax) {
var svg = d3.select(this).append("svg");
var svg1 = svg.append("svg")
.datum({x0:0,y1:0,y0:0.30,width:1})
.attr({id:'svg1','data-scale-x':'cw','data-scale-y':'ch','data-static':true})
.call(dpl.render);
var s1 = reptile.widgets.capstructure.call(svg1.node(),mbs_timeline,property_history)
.tickFormat('x',function() {})
.axis('x',function(d) { d.ticks(10);})
.margin({left:50,right:0,top:3,bottom:3})
.render();
var svg2 =svg.append("svg")
.datum({x0:0,y1:0.3,y0:0.60,width:1})
.attr({id:'svg2','data-scale-x':'cw','data-scale-y':'ch','data-static':true})
.call(dpl.render);
var s2 = reptile.widgets.dlq.call(svg2.node(),mbs_timeline)
.tickFormat('x',function() {})
.axis('x',function(d) { d.ticks(10);})
.margin({left:50,right:0,top:3,bottom:3})
.render();
var svg3 = svg.append('svg')
.datum({x0:0,y1:0.6,y0:0.9,width:1})
.attr({id:'svg2','data-scale-x':'cw','data-scale-y':'ch','data-static':true})
.call(dpl.render);
var s3 = reptile.widgets.vantage.call(svg3.node(),equifax)
.margin({left:50,right:0,top:3,bottom:10})
.axis('x',function(d) { d.ticks(10);})
.render();
var e1 = s1.scale('x').domain(),
e2 = s2.scale('x').domain();
var extent = [Math.min(e1[0],e2[0]),Math.max(e1[1],e2[1])];
s1.scale('x').domain(extent);
s1.on('resize.autofit',function() {}).render();
s2.scale('x').domain(extent);
s2.on('resize.autofit',function() {}).render();
s3.scale('x').domain(extent);
s3.on('resize.autofit',function() {}).render();
svg.selectAll("svg").attr("viewbox","").call(dpl.render);
};
/* global reptile,d3 */
reptile.widgets.property_history = function(property_history) {
if (!property_history.length) return;
property_history = property_history.filter(function(d) {
return d.YM > 288;
});
var lastDate,
maxPrice=0,
step = 1.2,
weight = 0.4,
lastPrice;
var history = property_history.map(function(d) {
if (!lastPrice) lastPrice = d.PRICE;
lastPrice = weight * Math.max(lastPrice/step, Math.min(d.PRICE,lastPrice*step)) + (1-weight) * lastPrice;
maxPrice = Math.max(maxPrice,lastPrice);
lastDate = new Date(1980,d.YM,1);
return {
x : new Date(1980,d.YM,1),
y0 : 0,
y1 : lastPrice
};
})
.filter(function(d) {
return d.x > new Date(2006,6,1);
});
var svg = d3.select(this);
return reptile.baseChart(svg)
.setTitle("chart","AVM Estimate")
.scale("x",d3.time.scale())
.add([history],function(g) {
g.append("path")
.attr("class","line")
.style("fill","green")
.style('opacity','0.85');
})
.axis('x',function(d) { d.ticks(6); })
.tickFormat('y',d3.format('.2s'))
.render();
};
reptile.widgets.assessor_history = function(assessor_history) {
var self = d3.select(this);
self.append("span").classed("caption",true).text("Assessor History");
reptile.table.call(this,assessor_history,['YEAR','SA_VAL_ASSD','SA_TAX_VAL']);
};
/* global reptile, d3 */
reptile.widgets.building_permits = function(building_permits) {
if (!building_permits.length) return;
building_permits = building_permits.slice(24).map(function(d) {
return {
x : new Date(d.YEAR,d.MONTH-1,1),
y1: d.COST_12M || 0,
y0:0
};
})
.filter(function(d) {
return d.x > new Date(2006,6,1);
});
var svg = d3.select(this);
return reptile.baseChart(svg)
.setTitle("chart","Building Permits")
.scale("x",d3.time.scale())
.add([building_permits],function(g) {
g.append("path")
.attr("class","line")
.style("fill","green")
.style('opacity','0.85');
})
.axis('x',function(d) { d.ticks(6); })
.tickFormat('y',d3.format('.2s'))
.render();
};
/* global reptile, d3 */
reptile.widgets.orig = function(mtg_orig) {
var self = d3.select(this);
self.append("div").classed("caption",true).text("Loan Origination");
var loan = mtg_orig;
var div = self.append("div");
reptile.list.call(div.node(),loan,['ORIG_AMT','LIEN_POSITION','APPRAISAL','ORIG_DATE','MATURITY_DATE','ORIG_INTEREST','FICO','OCCUPANCY','PURPOSE','FIRST_AMT','SECOND_AMT','ORIG_LTV','ORIG_COMB_LTV']);
};
/* global reptile, d3 */
var Problems = {
APPRAISAL : 'Appraisal issue',
LIQUIDATION : 'Liquidation Issue',
MOD : 'Modification Issue',
OWNER_OCC : 'Owner Occupancy Issue',
FAILED_FC : 'Failed Foreclosure',
FAILED_REO : 'Failed REO',
LONG_DLQ : 'Unresolved Delinquency',
EPD : 'Early Payments Default'
};
reptile.widgets.problems = function(problems) {
var self = d3.select(this);
self.append("div").classed("caption",true).text("Potential Issues");
var tr = self.append("table")
.selectAll("tr")
.data(Object.keys(Problems).filter(function(key) {
return true; //problems[key] !== undefined;
}))
.enter()
.append("tr");
tr.append("td")
.append("input")
.attr("type","checkbox")
.property("checked",function(d) {
return (problems[d] === 1) && !problems[d].err;
})
.property("disabled",function(d) {
return (problems[d] === null) && "disabled";
});
tr.append("td").text(function(d) { return Problems[d];});
};
/* global reptile, d3 */
reptile.widgets.mtg_timeline = function(mtg_timeline) {
reptile.table.call(this,mtg_timeline,['DIST_DATE','INV_BALANCE','SCH_PNI','RATE','MBA_STATUS','EST_ADVANCE','CURR_LOSS','CUMUL_LOSS'],+this.dataset.max);
};
reptile.widgets.timeline = function(timeline) {
d3.select(this).classed('timeline',true);
var self = d3.select(this);
self.append("div").classed("caption",true).text("Timeline of Events");
reptile.table.call(self.append('div').node(),timeline,['NO','DT','txt']);
};
/* global reptile, d3 */
var loss_titles = {
INV_BALANCE : 'Inv. Balance',
PROCEEDS : ' - Proceeds',
EST_ADVANCE : ' + Est. Advance',
LIQ_COST : ' + Other Cost',
LIQ_LOSS : '= Liq. Loss',
PRIOR_LOSS : ' + Mod. Loss',
TOTAL_LOSS : '= Total Loss'
};
reptile.widgets.loss_analysis = function(_loss_analysis,mtg_timeline) {
var self = d3.select(this),
last = mtg_timeline[mtg_timeline.length-1],
data;
var balance = (_loss_analysis && _loss_analysis.INV_BALANCE || last.INV_BALANCE);
last.CUMUL_LIQ_LOSS = last.CUMUL_LIQ_LOSS || last.CUMUL_LOSS;
last.CUMUL_MOD_LOSS = last.CUMUL_MOD_LOSS || 0;
if (!_loss_analysis)
data = [
{BLANK:'Est. Advance',AMOUNT: last.EST_ADVANCE},
{BLANK:'Liq Loss',AMOUNT:last.CUMUL_LIQ_LOSS},
{BLANK:'Net Proceeds',AMOUNT:last.CUMUL_LIQ_LOSS-last.EST_ADVANCE},
{BLANK:'Mod Loss',AMOUNT:last.CUMUL_MOD_LOSS},
{BLANK:'Total Loss',AMOUNT:last.CUMUL_LOSS}
];
else data = Object.keys(_loss_analysis)
.filter(function(d) {
return d !== 'LIQ_DATE';
})
.map(function(txt) {
return {BLANK:'<span style="white-space:pre-wrap">'+loss_titles[txt]+'</span>',AMOUNT:_loss_analysis[txt],PERC_BAL:_loss_analysis[txt]/_loss_analysis.INV_BALANCE};
});
data.forEach(function(d) {
d.PERC_BAL = d.AMOUNT / balance;
});
self.append('div').classed('caption',true).text('Loss Analysis');
reptile.table.call(this,data,['BLANK','AMOUNT','PERC_BAL']);
};
reptile.widgets.active_status = function(mtg_timeline) {
var self = d3.select(this);
var last = mtg_timeline[mtg_timeline.length-1];
mtg_timeline.slice().reverse().forEach(function(d) {
if (!last.LAST_MOD_RATE && d.POST_INT) last.LAST_MOD_RATE = d.POST_INT;
});
self.append("div").classed("caption",true).text("Last Status");
reptile.list.call(this,last,['BALANCE','INV_BALANCE','SCH_PI','MBA_STATUS','EST_ADVANCE','RATE','LAST_MOD_RATE','CUMUL_LOSS']);
};
reptile.widgets.last_status = function(loan_no,mtg_timeline,_loss_analysis) {
var last = mtg_timeline[mtg_timeline.length-1];
if (!last) return reptile.widgets.active_status.call(this,[{MBA_STATUS:'Not reported'}]);
if ((!last.MBA_STATUS || last.MBA_STATUS == '0') && last.CUMUL_LOSS && last.CUMUL_SEV)
reptile.widgets.loss_analysis.call(this,_loss_analysis,mtg_timeline);
else
reptile.widgets.active_status.call(this,mtg_timeline);
};
/* global reptile, d3 */
var statusCaption = {
'D' : 'Delinquent',
'C' : 'Current',
'F' : 'Foreclosure',
'M' : 'Modification',
'0' : 'Liquidated',
'R' : 'REO',
'B' : 'Bankrupcy',
'U' : 'Not Reported'
};
reptile.widgets.dlq = function(mtg_timeline,mtg_orig) {
var dlq = [],
curr = {},
last;
mtg_timeline = [{DIST_DATE : mtg_orig.ORIG_DATE, STATUS : 'U',BALANCE : mtg_orig.ORIG_AMT}].concat(mtg_timeline.slice());
if (mtg_timeline.length == 1) mtg_timeline.push({DIST_DATE:new Date(),STATUS:'U',BALANCE:mtg_orig.ORIG_AMT});
mtg_timeline.forEach(function(d) {
var status = d.STATUS;
if (!status) status = 'O';
if (!isNaN(status) && status != '0') status = 'D';
curr.x1 = new Date(d.DIST_DATE);
if (curr.STATUS != status) {
curr = {
STATUS:status,
x0:new Date(d.DIST_DATE),
x1:new Date(d.DIST_DATE),
y1 : 0,
y0 : 1
};
dlq.push(curr);
last = d;
}
});
last = dlq[dlq.length-1];
if (last.x0.valueOf() == last.x1.valueOf()) last.x1 = new Date(last.x0.getFullYear(),last.x0.getMonth()+1,last.x0.getDate());
var estAdv = mtg_timeline.map(function(d) {
return {
x: new Date(d.DIST_DATE),
y: d.EST_ADVANCE || 0
};
});
var svg = d3.select(this).classed('dlq',true);
reptile.baseChart(svg)
.showAxes(['x','y','y2'])
.setTitle("chart","Est. Servicer Advance")
.axis('x',function(d) { d.ticks(7); })
.tickFormat('x',reptile.timeFormat)
.tickFormat('y',d3.format('.2s'))
.tickFormat('y2',d3.format('.1%'))
.setTitle('y_top','$Adv')
.setTitle('y2_top','%Loan')
.add(dlq,function(g) {
g.append("rect")
.attr("class",function(d) { return "rect S"+d.STATUS;})
.attr("data-scale-y","ch")
.attr("data-legend",function(d) { return statusCaption[d.STATUS] || d.STATUS;});
})
.add([estAdv],function(g) {
g.append("path").attr("class","whiteline");
})
.add([estAdv],function(g) {
g.append("path").attr("class","line");
})
.on('resize.y2',function() {
var extent = this.scale('y').domain();
this.scale('y2').domain([extent[0]/last.BALANCE,extent[1]/last.BALANCE]);
})
.render();
};
/* global dpl, reptile, d3, Promise */
reptile.widgets.info1_icons = function(info1_icons) {
if (!info1_icons.length) return;
var g = d3.select(this);
g.append("div")
.classed("caption",true)
.text("Household Characteristics");
g.selectAll('img')
.data(info1_icons)
.enter()
.append('img')
.attr('src',function(d) {return '/infoicon/'+d+'.svg';})
.style({height:"5%",width:"5%"});
};
reptile.widgets.vantage = function(equifax) {
var svg = d3.select(this);
var data = equifax.map(function(d) {
return {x:new Date(d.date),y:d.vantage};
});
var chart = reptile.baseChart(svg)
.showAxes(['x','y'])
.setTitle("chart","Vantage Score")
.scale("x",d3.time.scale())
.tickFormat('y',d3.format('.2s'));
chart.enter([data])
.append("path")
.attr("class","line")
.render();
return chart;
};
reptile.widgets.vantage2 = function(transunion) {
if (!transunion.length) throw "# No Data";
var svg = d3.select(this);
var data = transunion.map(function(d) {
return {x:new Date(d.FILE_DATE),y:d.VTG2ATOT};
});
var chart = reptile.baseChart(svg)
.showAxes(['x','y'])
.setTitle("chart","Vantage Score")
.scale("x",d3.time.scale())
.tickFormat('y',d3.format('.2s'));
chart.enter([data])
.append("path")
.attr("class","line");
chart.render();
return chart;
};
reptile.widgets.tu_income = function(transunion) {
var svg = d3.select(this);
var data = transunion.map(function(d) {
return {x:new Date(d.FILE_DATE),y:d.TIE03TOT};
});
var chart = reptile.baseChart(svg)
.showAxes(['x','y'])
.setTitle("chart","Estimated Income")
.scale("x",d3.time.scale())
.tickFormat('y',d3.format('.2s'));
chart.enter([data])
.append("path")
.attr("class","line");
chart.render();
return chart;
};
var baltypes = [
['MT','Mortgage'],
['RE','Revolving'],
['BC','Credit Cards'],
['HI','Home Equity Loan'],
['HR','HELOC'],
['IN','Installment']
];
reptile.widgets.balance = function(transunion) {
var res = {};
baltypes.forEach(function(d) {
res[d] = [];
});
transunion.forEach(function(d,i) {
baltypes.forEach(function(tp) {
var code = tp[0],
cu = ((d[code+'33'] > -1 && d[code+'33']) || (res[tp][i-1] && res[tp][i-1].val) || 0);
});
});
};
function credit(transunion,code,title) {
var svg = d3.select(this);
var curr=[],dlq=[];
transunion.forEach(function(d,i) {
var dt = new Date(d.FILE_DATE),
dl = (d[code+'57'] > -1 && d[code+'57']) || (dlq[i-1] && dlq[i-1].val) || 0,
cu = ((d[code+'33'] > -1 && d[code+'33']) || (curr[i-1] && curr[i-1].val) || 0);
dlq.push( { x: dt, y0:0, val:dl, y1 : dl});
curr.push( {x: dt, y0:dl, val:cu, y1: cu});
});
var max = 0;
curr.forEach(function(d) {
max = Math.max(max,d.y1);
});
if (!max) throw "#no data";
var chart = reptile.baseChart(svg)
.setTitle('chart',title)
.showAxes(['x','y'])
.scale("x",d3.time.scale())
.tickFormat('y',d3.format('.2s'));
chart.enter([dlq])
.append("path")
.attr("class","area")
.style('fill','red')
.attr("data-legend",'Delinquent');
chart.enter([curr])
.append("path")
.attr("class","area")
.style('fill','green')
.attr("data-legend",'Current');
chart.render();
return chart;
}
reptile.widgets.tu_revolving = function(transunion) {
return credit.call(this,transunion,'RE','Revolving');
};
reptile.widgets.tu_cards = function(transunion) {//
return credit.call(this,transunion,'BC','Credit Cards');
};
reptile.widgets.tu_hi = function(transunion) {//
return credit.call(this,transunion,'HI','Home Equity Loan');
};
reptile.widgets.tu_heloc = function(transunion) {//
return credit.call(this,transunion,'HR','HELOC');
};
reptile.widgets.tu_in = function(transunion) {
return credit.call(this,transunion,'IN','Installment');
};
reptile.widgets.tu_mt = function(transunion) {//
return credit.call(this,transunion,'MT','Mortgage');
};
var categories = {
'RE' : 'Revolving',
'CB' : 'Credit Cards',
'HI' : 'Home Equity Loan',
'HR' : 'HELOC',
'IN' : 'Installment',
'MT' : 'Mortgage'
};
reptile.widgets.credit = function(transunion,timeline) {
var self = this;
var keys = ['dlq','capstructure','vantage2','tu_mt','tu_revolving','tu_hi','tu_heloc','tu_in','tu_cards'];
var svg = d3.select(this).append('svg').style({height:'100%',width:'100%'});
var height = svg.property("offsetHeight");
var width = svg.property("offsetWidth");
var charts = keys.map(function(key,i) {
var chart = svg.append('svg').attr({x:0,y:height/keys.length*i,height:height*1/keys.length,width:width}).attr('data-reptile',key);
return self._reptile_api.render(chart.node());
});
var x = [Infinity,-Infinity],totalWeight = 0;
return Promise.settle(charts)
.then(function(obj) {
charts = obj.filter(function(d) {
return !d.isRejected();
})
.map(function(d,i) {
d = d.value();
totalWeight += (d.weight = (i<2) ? 1.5 : 1);
var extent = dpl.chart(d).scale('x').domain();
x[0] = Math.min(extent[0],x[0].valueOf());
x[1] = Math.max(extent[1],x[1].valueOf());
return d;
});
var y = 0;
charts.forEach(function(svg,i) {
var h = svg.weight / totalWeight * height;
svg = d3.select(svg);
svg.attr({x:0,y:y,height:h});
y += h;
var chart = dpl.chart(svg);
chart.scale('x').domain(x);
chart.on('resize.setX',function() {
chart.scale('x').domain([x[0], x[1]]);
});
chart.on('render.autobbox',function() {});
var text = svg.select('.chart.title').text();
svg.selectAll('.title').remove();
chart.setTitle('y2',text);
svg.select('.y2.title').style('font-size','90%');
chart.axis('y').ticks(5);
chart.on("render.autobbox",function() {});
chart.on('render.autoviewbox',function() {});
//if (i < charts.length-1) svg.selectAll('.x.axis text').remove()
chart.render();
//if (chart.tickFormat('y')) chart.tickFormat('y2',d3.format('.2s'))
if (i < charts.length-1) {
chart.margin({left:50,right:5,bottom:3,top:3});
svg.selectAll('.x.axis').selectAll('text').remove();
} else {
chart.margin({left:50,right:5,bottom:20,top:3});
}
//svg.select('.y.title').style('font-size','70%')
//chart.margin({bottom:1});
chart.render();
svg.attr('viewBox',null);
});
timeline.forEach(function(d,i) {
if (d.CHART) {
var g = d3.select(self)
.selectAll('[data-reptile="'+d.CHART+'"]').select('.graph')
.append('g');
if (d.Y) g.datum({x:new Date(d.DT),y:d.Y});
else g.datum({x:new Date(d.DT),y:Math.random()}).attr('data-scale-y','ch');
g.call(function(g) {
g.append('circle').attr('r',10).style({fill:'white',stroke:'black','fill-opacity':0.8});
g.append('text').text(i+1).attr({dy:'0.4em','text-anchor':'middle'});
})
.call(dpl.render);
}
});
})
}
;
/* jshint multistr:true */
reptile.timeFormat = d3.time.format.multi([
["%b %d", function(d) { return d.getDate() != 1; }],
["%b", function(d) { return d.getMonth(); }],
["%Y", function() { return true; }]
]);
reptile.baseChart = function(svg) {
if (svg.node().tagName !== 'svg') svg = svg.append('svg');
svg.style({height: "100%",width: "100%"});
var chart = dpl.chart(svg)
.showAxes(['x','y'])
.scale("x",d3.time.scale())
.tickFormat('x',reptile.timeFormat)
.margin(10)
.on('render.autoviewbox',function() {
var svg = this.g,
bbox = svg.node().getBBox();
if (!svg.attr('data-static'))
svg.attr("viewBox",bbox.x+" "+bbox.y+" "+bbox.width+" "+bbox.height);
});
angular.element(window).on('resize',function() {
chart.render();
});
return chart;
};
})();
var express = require('express'),
bodyParser = require('body-parser'),
compression = require('compression'),
serveStatic = require('serve-static'),
Promise = require('bluebird');

@@ -18,12 +21,31 @@

"c" : function(b) {
int('a')
console.log('error')
throw 'this is an error'
},
"d" : function(test) {
return test+3;
},
"e" : function(input) {
return input * 10
}
}
var ec = require('./express-clues')(api,{safe:true})
express()
.get('/api/:fn',require('./express-clues')(api))
//.use(compression())
.use(bodyParser.json())
.get('/api/:fn',ec())
.post('/api/:fn',ec())
.get('/list',ec('a,b,c'))
.get('/test',function(req,res) {res.sendFile('/clues/util/test.html')})
.use(serveStatic('./'))
.use(serveStatic('../'))
.listen(3008);
console.log('listening on 3008')
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc