<commit_before>import { dbconnectionManager } from './DBConnectionManager';
import { transactionHelper } from './TransactionHelper';
import { settingsHelper } from './SettingsHelper';
import { blockChainVerifier } from './BlockChainVerifier';
import { observable } from 'mobx';
import { Long } from 'mongodb';
import crypto from 'crypto';
import moment from 'moment'

class DisputeHelper {

    constructor() { }

    getDisputes(filters) {
        //filters will be an object including all the selected filters in the UI, like transactionId,raisedBy etc.
        //Draft records will come from the db and Open/Closed ones will be fetched using oneBcClient apis
        let me = this;
        return new Promise((resolve, reject) => {
            let query = {};
            if (filters) {
                query = this.createFilterQuery(filters);
            }

            dbconnectionManager.getConnection().collection('DraftDisputes').find(query)
                .sort({ creationDate: -1 })
                .toArray(function (err, result) {
                    if (err) {
                        console.error("Error occurred while fetching transations by sequencenos." + err);
                        reject(err);
                    } else {
                        var promisesToWaitOn = [];
                        for (var i = 0; i < result.length; i++) {
                            let dispute = result[i];
                            //Fetch transaction data if exists
                            var prms = new Promise(function (resolve, reject) {
                                transactionHelper.getTransactionById(dispute.transactionId, (err, transaction) => {
                                    if (transaction) {
                                        if (filters && JSON.parse(filters.transactionRelatedFilter)) {
                                            dispute = me.applyTransactionRelatedFilters(dispute, transaction, filters);
                                        } else {
                                            dispute.transaction = transaction; //Transaction is in the database.
                                        }
                                    }
                                    resolve(dispute);
                                });
                            });
                            promisesToWaitOn.push(prms);
                        }
                        Promise.all(promisesToWaitOn).then(function (disputes) {
                            resolve(disputes);
                        });
                    }
                });
        });
    }

    createFilterQuery(filters) {
        let query = {};
        if (this.isValueNotNull(filters.status)) {
            query.status = { $in: JSON.parse(filters.status) };
        }
        if (this.isValueNotNull(filters.searchTnxId)) {
            query.transactionId = filters.searchTnxId;
        }
        if (this.isValueNotNull(filters.searchDisputeId)) {
            query.id = filters.searchDisputeId;
        }

        if (this.isValueNotNull(filters.disputeSubmitFromDate)) {
            query.submittedDate = { $gte: JSON.parse(filters.disputeSubmitFromDate) };
        }

        if (this.isValueNotNull(filters.disputeSubmitToDate)) {
            query.submittedDate = { $lte: JSON.parse(filters.disputeSubmitToDate) };
        }

        if (this.isValueNotNull(filters.disputeCloseFromDate)) {
            query.closedDate = { $gte: JSON.parse(filters.disputeCloseFromDate) };
        }

        if (this.isValueNotNull(filters.disputeCloseToDate)) {
            query.closedDate = { $lte: JSON.parse(filters.disputeCloseToDate) };
        }
        // commenting. Now we are not storing raisedByName in draftdisputes collection.
        //TODO Send entNAmeofLoggedUser from UI and search its address in a BackChainAddressMapping  collection.
        // if not found don't do anything.
        // if (this.isValueNotNull(filters.raisedBy)) {
        //     query.raisedByName = filters.raisedBy;
        // }

        if (this.isValueNotNull(filters.reasonCodes)) {
            query.reasonCode = { $in: JSON.parse(filters.reasonCodes) };
        }
        return query;
    }

    isValueNotNull(value) {
        if (value != null && value != 'null' && value != undefined && value != '') {
            return true;
        }
        return false;
    }

    applyTransactionRelatedFilters(dispute, transaction, filters) {
        if (this.isValueNotNull(filters.searchBtId)) {
            let found = false;
            for (let i = 0; i < transaction.transactionSlices.length; i++) {
                let transactionSlice = transaction.transactionSlices[i];
                if (transactionSlice.businessTransactionIds.indexOf(filters.searchBtId) > -1) {
                    dispute.transaction = transaction;
                    found = true;
                    break;
                }
            }
            if (!found) {
                dispute = null;
            }
        }
        if (this.isValueNotNull(filters.tnxFromDate)) {
            if (transaction.date >= JSON.parse(filters.tnxFromDate)) {
                dispute.transaction = transaction;
            } else if (dispute.transaction.id == transaction.id) {
                dispute = null;
            }
        }
        if (this.isValueNotNull(filters.tnxToDate)) {
            if (transaction.date <= JSON.parse(filters.tnxToDate)) {
                dispute.transaction = transaction;
            } else if (dispute.transaction.id == transaction.id) {
                dispute = null;
            }
        }
        return dispute;
    }

    getOpenDisputeCount(transactionId) {
        /**
         * Remove the callback function. Use a promise object instead
         * iff transactionId is null, this should fetch records from:
         *   - getDraftCount() => DraftDisputes count
         *   - onechain-back-client will have an api for this. For now you can skip this one
         * iff transactionId is given, this should fetch records from:
         *   - getDraftCount(transactionId) => DraftDisputes filtered by transactionId
         *   - onechain-back-client's api will have an option to filter by transactionId. We'll add this later.
         * resolve or reject depending on the result
         */
        return new Promise((resolve, reject) => {
            if (transactionId == null) {
                this.getDraftCount()
                    .then((count) => {
                        resolve(count);
                    })
                    .catch((err) => {
                        console.error("Error occurred while fetching open dispute count." + err);
                        reject(err);
                    });
            } else {
                this.getDraftCount(transactionId)
                    .then((count) => {
                        resolve(count);
                    })
                    .catch((err) => {
                        console.error("Error occurred while fetching open dispute count." + err);
                        reject(err);
                    });
            }
        });
    }

    getDraftCount(transactionId) {
        /**
         * Should return a promise
         * iff transactionId is null, fetch the total count of DraftDisputes collections
         * iff transactionId is given, fetch the total count of DraftDisputes per transaction from the collection.
         * resolve or reject depending on the result
         */
        return new Promise((resolve, reject) => {
            if (transactionId == null) {
                dbconnectionManager.getConnection().collection('DraftDisputes').count()
                    .then((count) => {
                        resolve(count);
                    })
                    .catch((err) => {
                        console.error("Error occurred while fetching draft count." + err);
                        reject(err);
                    });
            } else {
                dbconnectionManager.getConnection().collection('DraftDisputes').find({ "transactionId": transactionId }).count()
                    .then((count) => {
                        resolve(count);
                    })
                    .catch((err) => {
                        console.error("Error occurred while fetching draft count." + err);
                        reject(err);
                    });
            }
        });
    }

    disputeExists(transactionId) {
        // TODO check if dispute exists in blockchain
        return new Promise((resolve, reject) => {
            dbconnectionManager.getConnection().collection('DraftDisputes').findOne({ "transactionId": transactionId })
            .then((result) => {
                if(result) {
                    resolve({success:true, exists:true, status:result.status});
                } else {
                    resolve({ success: true, exists: false});
                }
            })
            .catch((err) => {
                console.error("Error occurred while fetching DraftDisputes" + err);
                reject(err);
            });
        });
    }

    saveAsDraft(dispute) {
        var me = this;
        return new Promise((resolve, reject) => {
            this.disputeExists(dispute.transactionId)
            .then(function(response) {
                if(response.exists) {
                    resolve(response);
                } else {
                    me.insertDraft(dispute)
                    .then(function(response){
                        if(response.success) {
                        resolve(response);
                    }
                    }, function(error){
                        console.error(error);
                        reject(error);
                    });
                }
            }, function(error) {
                console.error(error);
                reject(error);
            });
        });
    }

    insertDraft(dispute) {
        return new Promise((resolve, reject) => {
            dbconnectionManager.getConnection().collection('DraftDisputes').insert(dispute)
            .then(() => {
                resolve({success: true});
            })
            .catch((err) => {
                console.error("Error occurred while saving dispute as draft: " + err);
                reject(err);
            });
        });
    }

    generateDisputeId(plainText) {
        return({success: true, generatedDisputeId : crypto.createHash('sha256').update(plainText).digest('hex')});
    }

    discardDraftDispute(disputeId) {
        return new Promise((resolve, reject) => {
            dbconnectionManager.getConnection().collection('DraftDisputes').deleteOne({id:disputeId})
            .then((result) => {
                resolve({success: true});
            })
            .catch((err) => {
                console.error("Error occurred while discarding dispute as draft: " + err);
                reject(err);
            });
        });
    }

    submitDispute(dispute) {
        let me = this;
        return new Promise((resolve, reject) => {
            settingsHelper.getApplicationSettings()
            .then(result => {
                if(result && result.blockChain.disputeSubmissionWindowInMinutes) {
                    let disputeSubmissionWindowInMinutes = result.blockChain.disputeSubmissionWindowInMinutes;
                    transactionHelper.getTransactionById(dispute.transactionId, (err, transaction) => {
                        if (transaction) {
                            let duration = moment.duration(moment(new Date()).diff(moment(new Date(transaction.date))));
                            let mins = Math.ceil(duration.asMinutes());
                            if(mins < disputeSubmissionWindowInMinutes) {
                                /*TODO send dispute to Block chain and on success call this.discardDraftDispute(dispute.id)*/
                                resolve({success:true, submitDisputeMsg: 'submitted dispute'});
                            } else {
                                eject({success:true, submitDisputeMsg: 'Time window to raise a dispute on this transaction has already passed.'});
                            }
                        }
                    });
                }
            })
            .catch(err => {
                console.error("Application Settings can't be read in submitDispute: " + err);
                reject(err);
            });
        });
    }

    closeDispute(disputeId) {
        return new Promise((resolve, reject) => {
            // write code to close dispute
        });
    }

    getRaisedByEnterpriseName(metaMaskAddressOfLoggedUser) {
        return new Promise((resolve, reject) => {
            dbconnectionManager.getConnection().collection('BackChainAddressMapping').find()
                .toArray(function(err, result) {
                    if (err) {
                        reject(err);
                    } else {
                        result = result[0];
                        for (let key in result) {
                            if (result.hasOwnProperty(key)) {
                              if(key == metaMaskAddressOfLoggedUser) {
                                resolve({success : true, entName : result[key]})
                                break;
                              }
                            }
                          }
                    }
                });
        });
    }
}

export const disputeHelper = new DisputeHelper();<commit_msg>correct typo<commit_after>import { dbconnectionManager } from './DBConnectionManager';
import { transactionHelper } from './TransactionHelper';
import { settingsHelper } from './SettingsHelper';
import { blockChainVerifier } from './BlockChainVerifier';
import { observable } from 'mobx';
import { Long } from 'mongodb';
import crypto from 'crypto';
import moment from 'moment'

class DisputeHelper {

    constructor() { }

    getDisputes(filters) {
        //filters will be an object including all the selected filters in the UI, like transactionId,raisedBy etc.
        //Draft records will come from the db and Open/Closed ones will be fetched using oneBcClient apis
        let me = this;
        return new Promise((resolve, reject) => {
            let query = {};
            if (filters) {
                query = this.createFilterQuery(filters);
            }

            dbconnectionManager.getConnection().collection('DraftDisputes').find(query)
                .sort({ creationDate: -1 })
                .toArray(function (err, result) {
                    if (err) {
                        console.error("Error occurred while fetching transations by sequencenos." + err);
                        reject(err);
                    } else {
                        var promisesToWaitOn = [];
                        for (var i = 0; i < result.length; i++) {
                            let dispute = result[i];
                            //Fetch transaction data if exists
                            var prms = new Promise(function (resolve, reject) {
                                transactionHelper.getTransactionById(dispute.transactionId, (err, transaction) => {
                                    if (transaction) {
                                        if (filters && JSON.parse(filters.transactionRelatedFilter)) {
                                            dispute = me.applyTransactionRelatedFilters(dispute, transaction, filters);
                                        } else {
                                            dispute.transaction = transaction; //Transaction is in the database.
                                        }
                                    }
                                    resolve(dispute);
                                });
                            });
                            promisesToWaitOn.push(prms);
                        }
                        Promise.all(promisesToWaitOn).then(function (disputes) {
                            resolve(disputes);
                        });
                    }
                });
        });
    }

    createFilterQuery(filters) {
        let query = {};
        if (this.isValueNotNull(filters.status)) {
            query.status = { $in: JSON.parse(filters.status) };
        }
        if (this.isValueNotNull(filters.searchTnxId)) {
            query.transactionId = filters.searchTnxId;
        }
        if (this.isValueNotNull(filters.searchDisputeId)) {
            query.id = filters.searchDisputeId;
        }

        if (this.isValueNotNull(filters.disputeSubmitFromDate)) {
            query.submittedDate = { $gte: JSON.parse(filters.disputeSubmitFromDate) };
        }

        if (this.isValueNotNull(filters.disputeSubmitToDate)) {
            query.submittedDate = { $lte: JSON.parse(filters.disputeSubmitToDate) };
        }

        if (this.isValueNotNull(filters.disputeCloseFromDate)) {
            query.closedDate = { $gte: JSON.parse(filters.disputeCloseFromDate) };
        }

        if (this.isValueNotNull(filters.disputeCloseToDate)) {
            query.closedDate = { $lte: JSON.parse(filters.disputeCloseToDate) };
        }
        // commenting. Now we are not storing raisedByName in draftdisputes collection.
        //TODO Send entNAmeofLoggedUser from UI and search its address in a BackChainAddressMapping  collection.
        // if not found don't do anything.
        // if (this.isValueNotNull(filters.raisedBy)) {
        //     query.raisedByName = filters.raisedBy;
        // }

        if (this.isValueNotNull(filters.reasonCodes)) {
            query.reasonCode = { $in: JSON.parse(filters.reasonCodes) };
        }
        return query;
    }

    isValueNotNull(value) {
        if (value != null && value != 'null' && value != undefined && value != '') {
            return true;
        }
        return false;
    }

    applyTransactionRelatedFilters(dispute, transaction, filters) {
        if (this.isValueNotNull(filters.searchBtId)) {
            let found = false;
            for (let i = 0; i < transaction.transactionSlices.length; i++) {
                let transactionSlice = transaction.transactionSlices[i];
                if (transactionSlice.businessTransactionIds.indexOf(filters.searchBtId) > -1) {
                    dispute.transaction = transaction;
                    found = true;
                    break;
                }
            }
            if (!found) {
                dispute = null;
            }
        }
        if (this.isValueNotNull(filters.tnxFromDate)) {
            if (transaction.date >= JSON.parse(filters.tnxFromDate)) {
                dispute.transaction = transaction;
            } else if (dispute.transaction.id == transaction.id) {
                dispute = null;
            }
        }
        if (this.isValueNotNull(filters.tnxToDate)) {
            if (transaction.date <= JSON.parse(filters.tnxToDate)) {
                dispute.transaction = transaction;
            } else if (dispute.transaction.id == transaction.id) {
                dispute = null;
            }
        }
        return dispute;
    }

    getOpenDisputeCount(transactionId) {
        /**
         * Remove the callback function. Use a promise object instead
         * iff transactionId is null, this should fetch records from:
         *   - getDraftCount() => DraftDisputes count
         *   - onechain-back-client will have an api for this. For now you can skip this one
         * iff transactionId is given, this should fetch records from:
         *   - getDraftCount(transactionId) => DraftDisputes filtered by transactionId
         *   - onechain-back-client's api will have an option to filter by transactionId. We'll add this later.
         * resolve or reject depending on the result
         */
        return new Promise((resolve, reject) => {
            if (transactionId == null) {
                this.getDraftCount()
                    .then((count) => {
                        resolve(count);
                    })
                    .catch((err) => {
                        console.error("Error occurred while fetching open dispute count." + err);
                        reject(err);
                    });
            } else {
                this.getDraftCount(transactionId)
                    .then((count) => {
                        resolve(count);
                    })
                    .catch((err) => {
                        console.error("Error occurred while fetching open dispute count." + err);
                        reject(err);
                    });
            }
        });
    }

    getDraftCount(transactionId) {
        /**
         * Should return a promise
         * iff transactionId is null, fetch the total count of DraftDisputes collections
         * iff transactionId is given, fetch the total count of DraftDisputes per transaction from the collection.
         * resolve or reject depending on the result
         */
        return new Promise((resolve, reject) => {
            if (transactionId == null) {
                dbconnectionManager.getConnection().collection('DraftDisputes').count()
                    .then((count) => {
                        resolve(count);
                    })
                    .catch((err) => {
                        console.error("Error occurred while fetching draft count." + err);
                        reject(err);
                    });
            } else {
                dbconnectionManager.getConnection().collection('DraftDisputes').find({ "transactionId": transactionId }).count()
                    .then((count) => {
                        resolve(count);
                    })
                    .catch((err) => {
                        console.error("Error occurred while fetching draft count." + err);
                        reject(err);
                    });
            }
        });
    }

    disputeExists(transactionId) {
        // TODO check if dispute exists in blockchain
        return new Promise((resolve, reject) => {
            dbconnectionManager.getConnection().collection('DraftDisputes').findOne({ "transactionId": transactionId })
            .then((result) => {
                if(result) {
                    resolve({success:true, exists:true, status:result.status});
                } else {
                    resolve({ success: true, exists: false});
                }
            })
            .catch((err) => {
                console.error("Error occurred while fetching DraftDisputes" + err);
                reject(err);
            });
        });
    }

    saveAsDraft(dispute) {
        var me = this;
        return new Promise((resolve, reject) => {
            this.disputeExists(dispute.transactionId)
            .then(function(response) {
                if(response.exists) {
                    resolve(response);
                } else {
                    me.insertDraft(dispute)
                    .then(function(response){
                        if(response.success) {
                        resolve(response);
                    }
                    }, function(error){
                        console.error(error);
                        reject(error);
                    });
                }
            }, function(error) {
                console.error(error);
                reject(error);
            });
        });
    }

    insertDraft(dispute) {
        return new Promise((resolve, reject) => {
            dbconnectionManager.getConnection().collection('DraftDisputes').insert(dispute)
            .then(() => {
                resolve({success: true});
            })
            .catch((err) => {
                console.error("Error occurred while saving dispute as draft: " + err);
                reject(err);
            });
        });
    }

    generateDisputeId(plainText) {
        return({success: true, generatedDisputeId : crypto.createHash('sha256').update(plainText).digest('hex')});
    }

    discardDraftDispute(disputeId) {
        return new Promise((resolve, reject) => {
            dbconnectionManager.getConnection().collection('DraftDisputes').deleteOne({id:disputeId})
            .then((result) => {
                resolve({success: true});
            })
            .catch((err) => {
                console.error("Error occurred while discarding dispute as draft: " + err);
                reject(err);
            });
        });
    }

    submitDispute(dispute) {
        let me = this;
        return new Promise((resolve, reject) => {
            settingsHelper.getApplicationSettings()
            .then(result => {
                if(result && result.blockChain.disputeSubmissionWindowInMinutes) {
                    let disputeSubmissionWindowInMinutes = result.blockChain.disputeSubmissionWindowInMinutes;
                    transactionHelper.getTransactionById(dispute.transactionId, (err, transaction) => {
                        if (transaction) {
                            let duration = moment.duration(moment(new Date()).diff(moment(new Date(transaction.date))));
                            let mins = Math.ceil(duration.asMinutes());
                            if(mins < disputeSubmissionWindowInMinutes) {
                                /*TODO send dispute to Block chain and on success call this.discardDraftDispute(dispute.id)*/
                                resolve({success:true, submitDisputeMsg: 'submitted dispute'});
                            } else {
                                reject({success:true, submitDisputeMsg: "Time window to raise a dispute on this transaction has already passed.You have " + disputeSubmissionWindowInMinutes + " minutes to raise disputes on a transaction."});
                            }
                        }
                    });
                }
            })
            .catch(err => {
                console.error("Application Settings can't be read in submitDispute: " + err);
                reject(err);
            });
        });
    }

    closeDispute(disputeId) {
        return new Promise((resolve, reject) => {
            // write code to close dispute
        });
    }

    getRaisedByEnterpriseName(metaMaskAddressOfLoggedUser) {
        return new Promise((resolve, reject) => {
            dbconnectionManager.getConnection().collection('BackChainAddressMapping').find()
                .toArray(function(err, result) {
                    if (err) {
                        reject(err);
                    } else {
                        result = result[0];
                        for (let key in result) {
                            if (result.hasOwnProperty(key)) {
                              if(key == metaMaskAddressOfLoggedUser) {
                                resolve({success : true, entName : result[key]})
                                break;
                              }
                            }
                          }
                    }
                });
        });
    }
}

export const disputeHelper = new DisputeHelper();<|endoftext|>


<commit_before>/**
 * Treasure Global ID
 */

// Modules
var jsonp = require('jsonp')
var _ = require('../utils/lodash')
var invariant = require('invariant')
var cookie = require('cookies-js')

function cacheSuccess (result, cookieName) {
  cookie.set(cookieName, result['global_id'], { expires: 6000 })
  return result['global_id']
}

function configure () {
}

function fetchGlobalID (success, error, forceFetch) {
  success = _.isFunction(success) ? success : _.noop
  error = _.isFunction(error) ? error : _.noop
  var cookieName = this.client.globalIdCookie
  var cachedGlobalId = cookie.get(this.client.globalIdCookie)
  if (cachedGlobalId && !forceFetch) {
    return setTimeout(function() {
      success(cachedGlobalId)
    }, 0)
  }

  var url = this.client.protocol + '//' + this.client.host + '/js/v3/global_id'

  invariant(
    this.client.requestType === 'jsonp',
    'Request type ' + this.client.requestType + ' not supported'
  )

  jsonp(url, {
    prefix: 'TreasureJSONPCallback',
    timeout: 10000 // 10 seconds timeout
  }, function (err, res) {
    return err ? error(err) : success(cacheSuccess(res, cookieName))
  })
}

module.exports = {
  cacheSuccess: cacheSuccess,
  configure: configure,
  fetchGlobalID: fetchGlobalID
}
<commit_msg>linting<commit_after>/**
 * Treasure Global ID
 */

// Modules
var jsonp = require('jsonp')
var _ = require('../utils/lodash')
var invariant = require('invariant')
var cookie = require('cookies-js')

function cacheSuccess (result, cookieName) {
  cookie.set(cookieName, result['global_id'], { expires: 6000 })
  return result['global_id']
}

function configure () {
}

function fetchGlobalID (success, error, forceFetch) {
  success = _.isFunction(success) ? success : _.noop
  error = _.isFunction(error) ? error : _.noop
  var cookieName = this.client.globalIdCookie
  var cachedGlobalId = cookie.get(this.client.globalIdCookie)
  if (cachedGlobalId && !forceFetch) {
    return setTimeout(function () {
      success(cachedGlobalId)
    }, 0)
  }

  var url = this.client.protocol + '//' + this.client.host + '/js/v3/global_id'

  invariant(
    this.client.requestType === 'jsonp',
    'Request type ' + this.client.requestType + ' not supported'
  )

  jsonp(url, {
    prefix: 'TreasureJSONPCallback',
    timeout: 10000 // 10 seconds timeout
  }, function (err, res) {
    return err ? error(err) : success(cacheSuccess(res, cookieName))
  })
}

module.exports = {
  cacheSuccess: cacheSuccess,
  configure: configure,
  fetchGlobalID: fetchGlobalID
}
<|endoftext|>


<commit_before>define( ['dojo/_base/declare',
         'dojo/_base/array',
         'JBrowse/View/Track/Wiggle',
         'JBrowse/Util'
        ],
        function( declare, array, Wiggle, Util ) {

// feature class for the features we make for the calculated coverage
// values
var CoverageFeature = Util.fastDeclare(
    {
        get: function(f) { return this[f]; },
        tags: function() { return [ 'start', 'end', 'score' ]; },
        score: 0,
        constructor: function( args ) {
            this.start = args.start;
            this.end = args.end;
            this.score = args.score;
        }
    });

return declare( Wiggle,
{

    _defaultConfig: function() {
        return Util.deepUpdate(
            dojo.clone( this.inherited(arguments) ),
            {
                min_score: 0,
                max_score: 100
            }
        );
    },

    getGlobalStats: function() {
        return {};
    },

    getFeatures: function( query, featureCallback, finishCallback, errorCallback ) {
        var leftBase  = query.start;
        var rightBase = query.end;
        var scale = query.scale; // px/bp
        var widthBp = rightBase-leftBase;
        var widthPx = widthBp * ( query.scale || 1/query.basesPerSpan);

        var binWidth = Math.ceil( query.basesPerSpan ); // in bp

        var coverageBins = {};
        var bpToBin = function( bp ) {
            return Math.floor( (bp-leftBase) / binWidth );
        };

        this.store.getFeatures(
            query,
            dojo.hitch( this, function( feature ) {
                            var startBin = bpToBin( feature.get('start') );
                            var endBin   = bpToBin( feature.get('end')-1 );
                            for( var i = startBin; i <= endBin; i++ ) {
                                if ( coverageBins[i] ) {
                                    coverageBins[i]['matchCoverage']++;
                                }
                                else {
                                    coverageBins[i] = {};
                                    coverageBins[i]['matchCoverage'] = 1;
                                }
                            }
                            // Calculate SNP coverage
                            var mdTag = feature.get('MD');
                            if(mdTag) {
                                var SNPs = this._mdToMismatches(feature, mdTag);
                                // loops through mismatches and updates coverage variables accordingly.
                                for (var i = 0; i<SNPs.length; i++) {
                                    var pos = bpToBin( feature.get('start') + SNPs[i].start );
                                    // Note: we reduce matchCoverage so the sum is the total coverage
                                    coverageBins[pos]['matchCoverage']--;
                                    if ( coverageBins[pos][SNPs[i].bases] ) {
                                        coverageBins[pos][SNPs[i].bases]++;
                                    }
                                    else {
                                        coverageBins[pos][SNPs[i].bases] = 1;
                                    }
                                }
                            }
                        }),
            function () {
                // make fake features from the coverage
                for( var i = 0; i < Math.ceil( widthBp/binWidth ); i++ ) {
                    var bpOffset = leftBase+binWidth*i;
                    featureCallback( new CoverageFeature({
                        start: bpOffset,
                        end:   bpOffset+binWidth,
                        score: coverageBins[i] || {'matchCoverage': 0}
                     }));
                }
                finishCallback();
            }
        );
    },

    /*
     * Draw a set of features on the canvas.
     * @private
     */
    _drawFeatures: function( scale, leftBase, rightBase, block, canvas, features, featureRects, dataScale ) {
        var context = canvas.getContext('2d');
        var canvasHeight = canvas.height;
        var toY = dojo.hitch( this, function( val ) {
           return canvasHeight * ( 1-dataScale.normalize.call(this, val) );
        });
        var originY = toY( dataScale.origin );

        var barColor  = {'matchCoverage':'#999', 'A':'#00BF00', 'T':'red', 'C':'#4747ff', 'G':'#d5bb04'}; // base colors from "main.css"
        var negColor  = this.config.style.neg_color;
        var clipColor = this.config.style.clip_marker_color;
        var bgColor   = this.config.style.bg_color;
        var disableClipMarkers = this.config.disable_clip_markers;

        var drawRectangle = function(ID, yPos, height, fRect) {
            // draw the background color if we are configured to do so
            if( bgColor && yPos >= 0 ) {
                context.fillStyle = bgColor;
                context.fillRect( fRect.l, 0, fRect.w, canvasHeight );
            }

            if( yPos <= canvasHeight ) { // if the rectangle is visible at all

                if( yPos <= originY ) {
                    // bar goes upward
                    context.fillStyle = barColor[ID] || 'black';
                    context.fillRect( fRect.l, yPos, fRect.w, height);
                    if( !disableClipMarkers && yPos < 0 ) { // draw clip marker if necessary
                        context.fillStyle = clipColor || negColor;
                        context.fillRect( fRect.l, 0, fRect.w, 2 );
                    }
                }
                else {
                    // bar goes downward (Should not be reached)

                    context.fillStyle = negColor;
                    context.fillRect( fRect.l, originY, fRect.w, height );
                    if( !disableClipMarkers && yPos >= canvasHeight ) { // draw clip marker if necessary
                        context.fillStyle = clipColor || barColor[0];
                        context.fillRect( fRect.l, canvasHeight-3, fRect.w, 2 );
                    }
                }
            }
        };

        dojo.forEach( features, function(f,i) {
            var fRect = featureRects[i];
            var score = f.get('score');
            var totalHeight = 0;
            for (counts in score) {
                if (score.hasOwnProperty(counts)) {
                    totalHeight += score[counts];
                }
            }

            // Note: 'matchCoverage' is done first to ensure the grey part of the graph is on top
            drawRectangle('matchCoverage', toY(totalHeight), originY-toY( score['matchCoverage'] )+1, fRect);
            totalHeight -= score['matchCoverage'];

            for (counts in score) {
                if (score.hasOwnProperty(counts) && counts != 'matchCoverage') {
                    drawRectangle( counts, toY(totalHeight), originY-toY( score[counts] )+1, fRect);
                    totalHeight -= score[counts];
                }
            }

        }, this );
    },

    /**
     * parse a SAM MD tag to find mismatching bases of the template versus the reference
     * @returns {Array[Object]} array of mismatches and their positions
     */
    _mdToMismatches: function( feature, mdstring ) {
        var mismatchRecords = [];
        var curr = { start: 0, bases: '' };
        var seq = feature.get('seq');
        var nextRecord = function() {
              mismatchRecords.push( curr );
              curr = { start: curr.start + curr.bases.length, bases: ''};
        };
        array.forEach( mdstring.match(/(\d+|\^[a-z]+|[a-z])/ig), function( token ) {
          if( token.match(/^\d/) ) { // matching bases
              curr.start += parseInt( token );
          }
          else if( token.match(/^\^/) ) { // insertion in the template
              var i = token.length-1;
              while( i-- ) {
                  curr.bases = '*';
                  nextRecord();
              }
          }
          else if( token.match(/^[a-z]/i) ) { // mismatch
              curr.bases = seq.substr( curr.start, token.length );
              nextRecord();
          }
        });
        return mismatchRecords;
    }
});
});<commit_msg>Added mouseover coverage summary.<commit_after>define( ['dojo/_base/declare',
         'dojo/_base/array',
         'JBrowse/View/Track/Wiggle',
         'JBrowse/Util'
        ],
        function( declare, array, Wiggle, Util ) {

// feature class for the features we make for the calculated coverage
// values
var CoverageFeature = Util.fastDeclare(
    {
        get: function(f) { return this[f]; },
        tags: function() { return [ 'start', 'end', 'score' ]; },
        score: 0,
        constructor: function( args ) {
            this.start = args.start;
            this.end = args.end;
            this.score = args.score;
        }
    });

return declare( Wiggle,
{

    _defaultConfig: function() {
        return Util.deepUpdate(
            dojo.clone( this.inherited(arguments) ),
            {
                min_score: 0,
                max_score: 100
            }
        );
    },

    getGlobalStats: function() {
        return {};
    },

    getFeatures: function( query, featureCallback, finishCallback, errorCallback ) {
        var leftBase  = query.start;
        var rightBase = query.end;
        var scale = query.scale; // px/bp
        var widthBp = rightBase-leftBase;
        var widthPx = widthBp * ( query.scale || 1/query.basesPerSpan);

        var binWidth = Math.ceil( query.basesPerSpan ); // in bp

        var coverageBins = {};
        var bpToBin = function( bp ) {
            return Math.floor( (bp-leftBase) / binWidth );
        };

        this.store.getFeatures(
            query,
            dojo.hitch( this, function( feature ) {
                            var startBin = bpToBin( feature.get('start') );
                            var endBin   = bpToBin( feature.get('end')-1 );
                            for( var i = startBin; i <= endBin; i++ ) {
                                if ( coverageBins[i] ) {
                                    coverageBins[i]['matchCoverage']++;
                                }
                                else {
                                    coverageBins[i] = {};
                                    coverageBins[i]['matchCoverage'] = 1;
                                }
                            }
                            // Calculate SNP coverage
                            var mdTag = feature.get('MD');
                            if(mdTag) {
                                var SNPs = this._mdToMismatches(feature, mdTag);
                                // loops through mismatches and updates coverage variables accordingly.
                                for (var i = 0; i<SNPs.length; i++) {
                                    var pos = bpToBin( feature.get('start') + SNPs[i].start );
                                    // Note: we reduce matchCoverage so the sum is the total coverage
                                    coverageBins[pos]['matchCoverage']--;
                                    if ( coverageBins[pos][SNPs[i].bases] ) {
                                        coverageBins[pos][SNPs[i].bases]++;
                                    }
                                    else {
                                        coverageBins[pos][SNPs[i].bases] = 1;
                                    }
                                }
                            }
                        }),
            function () {
                // make fake features from the coverage
                for( var i = 0; i < Math.ceil( widthBp/binWidth ); i++ ) {
                    var bpOffset = leftBase+binWidth*i;
                    featureCallback( new CoverageFeature({
                        start: bpOffset,
                        end:   bpOffset+binWidth,
                        score: coverageBins[i] || {'matchCoverage': 0}
                     }));
                }
                finishCallback();
            }
        );
    },

    /*
     * Draw a set of features on the canvas.
     * @private
     */
    _drawFeatures: function( scale, leftBase, rightBase, block, canvas, features, featureRects, dataScale ) {
        var context = canvas.getContext('2d');
        var canvasHeight = canvas.height;
        var toY = dojo.hitch( this, function( val ) {
           return canvasHeight * ( 1-dataScale.normalize.call(this, val) );
        });
        var originY = toY( dataScale.origin );

        var barColor  = {'matchCoverage':'#999', 'A':'#00BF00', 'T':'red', 'C':'#4747ff', 'G':'#d5bb04'}; // base colors from "main.css"
        var negColor  = this.config.style.neg_color;
        var clipColor = this.config.style.clip_marker_color;
        var bgColor   = this.config.style.bg_color;
        var disableClipMarkers = this.config.disable_clip_markers;

        var drawRectangle = function(ID, yPos, height, fRect) {
            // draw the background color if we are configured to do so
            if( bgColor && yPos >= 0 ) {
                context.fillStyle = bgColor;
                context.fillRect( fRect.l, 0, fRect.w, canvasHeight );
            }

            if( yPos <= canvasHeight ) { // if the rectangle is visible at all

                if( yPos <= originY ) {
                    // bar goes upward
                    context.fillStyle = barColor[ID] || 'black';
                    context.fillRect( fRect.l, yPos, fRect.w, height);
                    if( !disableClipMarkers && yPos < 0 ) { // draw clip marker if necessary
                        context.fillStyle = clipColor || negColor;
                        context.fillRect( fRect.l, 0, fRect.w, 2 );
                    }
                }
                else {
                    // bar goes downward (Should not be reached)

                    context.fillStyle = negColor;
                    context.fillRect( fRect.l, originY, fRect.w, height );
                    if( !disableClipMarkers && yPos >= canvasHeight ) { // draw clip marker if necessary
                        context.fillStyle = clipColor || barColor[ID];
                        context.fillRect( fRect.l, canvasHeight-3, fRect.w, 2 );
                    }
                }
            }
        };

        dojo.forEach( features, function(f,i) {
            var fRect = featureRects[i];
            var score = f.get('score');
            var totalHeight = 0;
            for (counts in score) {
                if (score.hasOwnProperty(counts)) {
                    totalHeight += score[counts];
                }
            }

            // Note: 'matchCoverage' is done first to ensure the grey part of the graph is on top
            drawRectangle('matchCoverage', toY(totalHeight), originY-toY( score['matchCoverage'] )+1, fRect);
            totalHeight -= score['matchCoverage'];

            for (counts in score) {
                if (score.hasOwnProperty(counts) && counts != 'matchCoverage') {
                    drawRectangle( counts, toY(totalHeight), originY-toY( score[counts] )+1, fRect);
                    totalHeight -= score[counts];
                }
            }

        }, this );
    },

    /**
     * parse a SAM MD tag to find mismatching bases of the template versus the reference
     * @returns {Array[Object]} array of mismatches and their positions
     */
    _mdToMismatches: function( feature, mdstring ) {
        var mismatchRecords = [];
        var curr = { start: 0, bases: '' };
        var seq = feature.get('seq');
        var nextRecord = function() {
              mismatchRecords.push( curr );
              curr = { start: curr.start + curr.bases.length, bases: ''};
        };
        array.forEach( mdstring.match(/(\d+|\^[a-z]+|[a-z])/ig), function( token ) {
          if( token.match(/^\d/) ) { // matching bases
              curr.start += parseInt( token );
          }
          else if( token.match(/^\^/) ) { // insertion in the template
              var i = token.length-1;
              while( i-- ) {
                  curr.bases = '*';
                  nextRecord();
              }
          }
          else if( token.match(/^[a-z]/i) ) { // mismatch
              curr.bases = seq.substr( curr.start, token.length );
              nextRecord();
          }
        });
        return mismatchRecords;
    },

    /*
     * The following method is required to override the equivalent method in "WiggleBase.js"
     * It displays more complete data.
     */
    _showPixelValue: function( scoreDisplay, score ) {
        if( typeof score['matchCoverage'] == 'number' ) {
            var scoreSummary = "COVERAGE SUMMARY
Matching Bases: "+score['matchCoverage']+'
';
            for (ID in score) {
                if (score.hasOwnProperty(ID) && ID != 'matchCoverage') {
                    scoreSummary += ID + ': ' +score[ID] +'
';
                }
            }
            scoreDisplay.innerHTML = scoreSummary;
            return true;
        } else {
            return false;
        }
    }
});
});<|endoftext|>


<commit_before>const {Step} = require("prosemirror-transform")

const {Router} = require("./route")
const {schema} = require("../schema")
const {getInstance, instanceInfo} = require("./instance")

const router = new Router

exports.handleCollabRequest = function(req, resp) {
  return router.resolve(req, resp)
}

// Object that represents an HTTP response.
class Output {
  constructor(code, body, type) {
    this.code = code
    this.body = body
    this.type = type || "text/plain"
  }

  static json(data) {
    return new Output(200, JSON.stringify(data), "application/json")
  }

  // Write the response.
  resp(resp) {
    resp.writeHead(this.code, {"Content-Type": this.type})
    resp.end(this.body)
  }
}

// : (stream.Readable, Function)
// Invoke a callback with a stream's data.
function readStreamAsJSON(stream, callback) {
  let data = ""
  stream.on("data", chunk => data += chunk)
  stream.on("end", () => {
    let result, error
    try { result = JSON.parse(data) }
    catch (e) { error = e }
    callback(error, result)
  })
  stream.on("error", e => callback(e))
}

// : (string, Array, Function)
// Register a server route.
function handle(method, url, f) {
  router.add(method, url, (req, resp, ...args) => {
    function finish() {
      let output
      try {
        output = f(...args, req, resp)
      } catch (err) {
        console.log(err.stack)
        output = new Output(err.status || 500, err.toString())
      }
      if (output) output.resp(resp)
    }

    if (method == "PUT" || method == "POST")
      readStreamAsJSON(req, (err, val) => {
        if (err) new Output(500, err.toString()).resp(resp)
        else { args.unshift(val); finish() }
      })
    else
      finish()
  })
}

// The root endpoint outputs a list of the collaborative
// editing document instances.
handle("GET", ["docs"], () => {
  return Output.json(instanceInfo())
})

// Output the current state of a document instance.
handle("GET", ["docs", null], (id, req) => {
  let inst = getInstance(id, reqIP(req))
  return Output.json({doc: inst.doc.toJSON(),
                      users: inst.userCount,
                      version: inst.version,
                      comments: inst.comments.comments,
                      commentVersion: inst.comments.version})
})

function nonNegInteger(str) {
  let num = Number(str)
  if (!isNaN(num) && Math.floor(num) == num && num >= 0) return num
  let err = new Error("Not a non-negative integer: " + str)
  err.status = 400
  throw err
}

// An object to assist in waiting for a collaborative editing
// instance to publish a new version before sending the version
// event data to the client.
class Waiting {
  constructor(resp, inst, ip, finish) {
    this.resp = resp
    this.inst = inst
    this.ip = ip
    this.finish = finish
    this.done = false
    resp.setTimeout(1000 * 60 * 5, () => {
      this.abort()
      this.send(Output.json({}))
    })
  }

  abort() {
    let found = this.inst.waiting.indexOf(this)
    if (found > -1) this.inst.waiting.splice(found, 1)
  }

  send(output) {
    if (this.done) return
    output.resp(this.resp)
    this.done = true
  }
}

function outputEvents(inst, data) {
  return Output.json({version: inst.version,
                      commentVersion: inst.comments.version,
                      steps: data.steps.map(s => s.toJSON()),
                      clientIDs: data.steps.map(step => step.clientID),
                      comment: data.comment})
}

// An endpoint for a collaborative document instance which
// returns all events between a given version and the server's
// current version of the document.
handle("GET", ["docs", null, "events"], (id, req, resp) => {
  let version = nonNegInteger(req.query.version)
  let commentVersion = nonNegInteger(req.query.commentVersion)

  let inst = getInstance(id, reqIP(req))
  let data = inst.getEvents(version, commentVersion)
  if (data === false)
    return new Output(410, "History no longer available")
  // If the server version is greater than the given version,
  // return the data immediately.
  if (data.steps.length || data.comment.length)
    return outputEvents(inst, data)
  // If the server version matches the given version,
  // wait until a new version is published to return the event data.
  let wait = new Waiting(resp, inst, reqIP(req), () => {
    wait.send(outputEvents(inst, inst.getEvents(version, commentVersion)))
  })
  inst.waiting.push(wait)
  resp.on("close", () => wait.abort())
})

function reqIP(request) {
  return request.headers["x-forwarded-for"] || request.socket.remoteAddress
}

// The event submission endpoint, which a client sends an event to.
handle("POST", ["docs", null, "events"], (data, id, req) => {
  let version = nonNegInteger(data.version)
  let steps = data.steps.map(s => Step.fromJSON(schema, s))
  let result = getInstance(id, reqIP(req)).addEvents(version, steps, data.comment, data.clientID)
  if (!result)
    return new Output(409, "Version not current")
  else
    return Output.json(result)
})
<commit_msg>[collab demo] Send user count in events response<commit_after>const {Step} = require("prosemirror-transform")

const {Router} = require("./route")
const {schema} = require("../schema")
const {getInstance, instanceInfo} = require("./instance")

const router = new Router

exports.handleCollabRequest = function(req, resp) {
  return router.resolve(req, resp)
}

// Object that represents an HTTP response.
class Output {
  constructor(code, body, type) {
    this.code = code
    this.body = body
    this.type = type || "text/plain"
  }

  static json(data) {
    return new Output(200, JSON.stringify(data), "application/json")
  }

  // Write the response.
  resp(resp) {
    resp.writeHead(this.code, {"Content-Type": this.type})
    resp.end(this.body)
  }
}

// : (stream.Readable, Function)
// Invoke a callback with a stream's data.
function readStreamAsJSON(stream, callback) {
  let data = ""
  stream.on("data", chunk => data += chunk)
  stream.on("end", () => {
    let result, error
    try { result = JSON.parse(data) }
    catch (e) { error = e }
    callback(error, result)
  })
  stream.on("error", e => callback(e))
}

// : (string, Array, Function)
// Register a server route.
function handle(method, url, f) {
  router.add(method, url, (req, resp, ...args) => {
    function finish() {
      let output
      try {
        output = f(...args, req, resp)
      } catch (err) {
        console.log(err.stack)
        output = new Output(err.status || 500, err.toString())
      }
      if (output) output.resp(resp)
    }

    if (method == "PUT" || method == "POST")
      readStreamAsJSON(req, (err, val) => {
        if (err) new Output(500, err.toString()).resp(resp)
        else { args.unshift(val); finish() }
      })
    else
      finish()
  })
}

// The root endpoint outputs a list of the collaborative
// editing document instances.
handle("GET", ["docs"], () => {
  return Output.json(instanceInfo())
})

// Output the current state of a document instance.
handle("GET", ["docs", null], (id, req) => {
  let inst = getInstance(id, reqIP(req))
  return Output.json({doc: inst.doc.toJSON(),
                      users: inst.userCount,
                      version: inst.version,
                      comments: inst.comments.comments,
                      commentVersion: inst.comments.version})
})

function nonNegInteger(str) {
  let num = Number(str)
  if (!isNaN(num) && Math.floor(num) == num && num >= 0) return num
  let err = new Error("Not a non-negative integer: " + str)
  err.status = 400
  throw err
}

// An object to assist in waiting for a collaborative editing
// instance to publish a new version before sending the version
// event data to the client.
class Waiting {
  constructor(resp, inst, ip, finish) {
    this.resp = resp
    this.inst = inst
    this.ip = ip
    this.finish = finish
    this.done = false
    resp.setTimeout(1000 * 60 * 5, () => {
      this.abort()
      this.send(Output.json({}))
    })
  }

  abort() {
    let found = this.inst.waiting.indexOf(this)
    if (found > -1) this.inst.waiting.splice(found, 1)
  }

  send(output) {
    if (this.done) return
    output.resp(this.resp)
    this.done = true
  }
}

function outputEvents(inst, data) {
  return Output.json({version: inst.version,
                      commentVersion: inst.comments.version,
                      steps: data.steps.map(s => s.toJSON()),
                      clientIDs: data.steps.map(step => step.clientID),
                      comment: data.comment,
                      users: data.users})
}

// An endpoint for a collaborative document instance which
// returns all events between a given version and the server's
// current version of the document.
handle("GET", ["docs", null, "events"], (id, req, resp) => {
  let version = nonNegInteger(req.query.version)
  let commentVersion = nonNegInteger(req.query.commentVersion)

  let inst = getInstance(id, reqIP(req))
  let data = inst.getEvents(version, commentVersion)
  if (data === false)
    return new Output(410, "History no longer available")
  // If the server version is greater than the given version,
  // return the data immediately.
  if (data.steps.length || data.comment.length)
    return outputEvents(inst, data)
  // If the server version matches the given version,
  // wait until a new version is published to return the event data.
  let wait = new Waiting(resp, inst, reqIP(req), () => {
    wait.send(outputEvents(inst, inst.getEvents(version, commentVersion)))
  })
  inst.waiting.push(wait)
  resp.on("close", () => wait.abort())
})

function reqIP(request) {
  return request.headers["x-forwarded-for"] || request.socket.remoteAddress
}

// The event submission endpoint, which a client sends an event to.
handle("POST", ["docs", null, "events"], (data, id, req) => {
  let version = nonNegInteger(data.version)
  let steps = data.steps.map(s => Step.fromJSON(schema, s))
  let result = getInstance(id, reqIP(req)).addEvents(version, steps, data.comment, data.clientID)
  if (!result)
    return new Output(409, "Version not current")
  else
    return Output.json(result)
})
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */

var gutil = require('gulp-util');
var through = require('through2');
var _ = require('lodash');
var Layout = require('../view/layout');

module.exports = function rendererPlugin(assemble) {

  var layouts = new Layout(assemble);

  return function renderer(options, locals) {
    return through.obj(function (file, encoding, callback) {
      assemble.set('encoding', encoding || 'utf8');

      if (file.isNull()) {
        this.push(file);
        return callback();
      }

      if (file.isStream()) {
        this.emit('error', new gutil.PluginError('assemble-renderer', 'Streaming is not supported with engines.'));
        return callback();
      }

      var data = _.extend({}, assemble.get(), locals, file.data, file.locals);
      var layout = layouts.get(options.ext || file.ext || assemble.get('ext'));
      file.layout = layout && layout.render(file);
      var stream = this;

      function render(err, file, ext) {
        if (err) {
          callback(err);
        } else {
          file.ext = options.ext || ext || assemble.get('ext');
          file.path = gutil.replaceExtension(file.path, file.ext);
          stream.push(file);
          callback();
        }
      }

      var opts = _.extend({}, options, {
        // ext: assemble.get('ext'),
        helpers: assemble.helpers(),
        partials: file.partials(assemble.partials)
      }, data);

      try {
        file.render(opts, render);
      } catch (err) {
        this.emit('error', new gutil.PluginError('assemble-renderer', err));
        return callback();
      }
    });
  };
};<commit_msg>fixing layout.flatten call<commit_after>'use strict';

/**
 * Module dependencies.
 */

var gutil = require('gulp-util');
var through = require('through2');
var _ = require('lodash');
var Layout = require('../view/layout');

module.exports = function rendererPlugin(assemble) {

  var layouts = new Layout(assemble);

  return function renderer(options, locals) {
    return through.obj(function (file, encoding, callback) {
      assemble.set('encoding', encoding || 'utf8');

      if (file.isNull()) {
        this.push(file);
        return callback();
      }

      if (file.isStream()) {
        this.emit('error', new gutil.PluginError('assemble-renderer', 'Streaming is not supported with engines.'));
        return callback();
      }

      var data = _.extend({}, assemble.get(), locals, file.data, file.locals);
      var layout = layouts.get(options.ext || file.ext || assemble.get('ext'));
      file.layout = layout && layout.flatten(file);
      var stream = this;

      function render(err, file, ext) {
        if (err) {
          callback(err);
        } else {
          file.ext = options.ext || ext || assemble.get('ext');
          file.path = gutil.replaceExtension(file.path, file.ext);
          stream.push(file);
          callback();
        }
      }

      var opts = _.extend({}, options, {
        // ext: assemble.get('ext'),
        helpers: assemble.helpers(),
        partials: file.partials(assemble.partials)
      }, data);

      try {
        file.render(opts, render);
      } catch (err) {
        this.emit('error', new gutil.PluginError('assemble-renderer', err));
        return callback();
      }
    });
  };
};<|endoftext|>


<commit_before>(function() {
    function config($stateProvider, $locationProvider) {
      $locationProvider
        .html5Mode({
            enabled: true,
            requireBase: false
        });
        $stateProvider
         .state('landing', {
             url: '/',
             templateUrl: '/templates/landing.html'
         })
         .state('album', {
             url: '/album',
             templateUrl: '/templates/album.html'
         });
    }
    angular
        .module('blocJams', ['ui.router'])
        .config(config);
})();
<commit_msg>new state<commit_after>(function() {
    function config($stateProvider, $locationProvider) {
      $locationProvider
        .html5Mode({
            enabled: true,
            requireBase: false
        });
        $stateProvider
         .state('landing', {
             url: '/',
             templateUrl: '/templates/landing.html'
         })
         .state('album', {
             url: '/album',
             templateUrl: '/templates/album.html'
         })
         .state('collection', {
             url: '/collection',
             templateUrl: '/templates/collection.html'
         });
    }
    angular
        .module('blocJams', ['ui.router'])
        .config(config);
})();
<|endoftext|>


<commit_before>const expect = require('chai').expect;

let Q;
let queue;

try {
  Q = require('../../structures/queue');
  queue = new Q();
} catch (e) {
  throw new Error('Queue could not be tested due to faulty import, likely ' +
  'from an incorrect file path or exporting a non-constructor from the file.');
}

describe('Queue', () => {
  beforeEach(() => {
    queue = new Q();
  });

  it('should be extensible', () => {
    expect(queue).to.be.extensible;
  });

  it('should have properties granted from constructor call', () => {
    expect(queue).to.have.all.keys('front', 'rear', 'size', 'capacity');
  });

  describe('#isEmpty()', () => {
    it('should return true if queue is empty', () => {
      expect(queue.isEmpty()).to.equal(true);
    });

    it('should return false if queue contains values', () => {
      queue.enqueue(0)

      expect(queue.isEmpty()).to.equal(false);
    });
  });

  describe('#dequeue()', () => {
    it('should decrease size of queue by 1', () => {
      queue.enqueue(0);
      queue.enqueue(1);

      queue.dequeue();

      expect(queue.size).to.equal(1);
    });

    it('should remove earliest item enqueued to queue (FIFO)', () => {
      queue.enqueue(0);
      queue.enqueue(1);

      queue.dequeue();

      expect(queue.front.value).to.equal(1);
    });

    it('should return removed value', () => {
      queue.enqueue(0);

      expect(queue.dequeue()).to.equal(0);
    });
  });

  describe('#enqueue()', () => {
    it('should increase size of queue by 1', () => {
      queue.enqueue(0);

      expect(queue.size).to.equal(1);
    });

    it('should append input to end of queue', () => {
      queue.enqueue(0);
      queue.enqueue(1);

      expect(queue.rear.value).to.equal(1);
    });

    it('should not insert item if queue is at capacity', () => {
      const cappedQueue = new Q(0);

      queue.enqueue('never enqueues');

      expect(cappedQueue.size).to.equal(0);
    });
  });

  describe('#getSize()', () => {
    it('should return 0 if queue is empty', () => {
      expect(queue.getSize()).to.equal(0);
    });

    it('should return 1 if queue contains one item', () => {
      queue.enqueue(0);

      expect(queue.getSize()).to.equal(1);
    });
  });

  describe('#isFull()', () => {
    it('should return false if queue has not reached capacity', () => {
      const cappedQueue = new Q(1);

      expect(cappedQueue.isFull()).to.equal(false);
    });

    it('should return true if queue has reached capacity', () => {
      const cappedQueue = new Q(1);

      cappedQueue.enqueue(0);

      expect(cappedQueue.isFull()).to.equal(true);
    });
  });

  describe('#peek()', () => {
    it('should return value at top of queue', () => {
      queue.enqueue(0);

      expect(queue.peek()).to.equal(0);
    });

    it('should return undefined for empty queue', () => {
      expect(queue.peek()).to.equal(undefined);
    });
  });
});<commit_msg>Add tests for dequeuing final node<commit_after>const expect = require('chai').expect;

let Q;
let queue;

try {
  Q = require('../../structures/queue');
  queue = new Q();
} catch (e) {
  throw new Error('Queue could not be tested due to faulty import, likely ' +
  'from an incorrect file path or exporting a non-constructor from the file.');
}

describe('Queue', () => {
  beforeEach(() => {
    queue = new Q();
  });

  it('should be extensible', () => {
    expect(queue).to.be.extensible;
  });

  it('should have properties granted from constructor call', () => {
    expect(queue).to.have.all.keys('front', 'rear', 'size', 'capacity');
  });

  describe('#isEmpty()', () => {
    it('should return true if queue is empty', () => {
      expect(queue.isEmpty()).to.equal(true);
    });

    it('should return false if queue contains values', () => {
      queue.enqueue(0)

      expect(queue.isEmpty()).to.equal(false);
    });
  });

  describe('#dequeue()', () => {
    it('should decrease size of queue by 1', () => {
      queue.enqueue(0);
      queue.enqueue(1);

      queue.dequeue();

      expect(queue.size).to.equal(1);
    });

    it('should remove earliest item enqueued to queue (FIFO)', () => {
      queue.enqueue(0);
      queue.enqueue(1);

      queue.dequeue();

      expect(queue.front.value).to.equal(1);
    });

    it('should set front to null when dequeuing the last node', () => {
      queue.enqueue(1);

      queue.dequeue();

      expect(queue.front).to.be.null;
    });

    it('should set rear to null when dequeuing the last node', () => {
      queue.enqueue(1);

      queue.dequeue();

      expect(queue.rear).to.be.null;
    });

    it('should return removed value', () => {
      queue.enqueue(0);

      expect(queue.dequeue()).to.equal(0);
    });
  });

  describe('#enqueue()', () => {
    it('should increase size of queue by 1', () => {
      queue.enqueue(0);

      expect(queue.size).to.equal(1);
    });

    it('should append input to end of queue', () => {
      queue.enqueue(0);
      queue.enqueue(1);

      expect(queue.rear.value).to.equal(1);
    });

    it('should not insert item if queue is at capacity', () => {
      const cappedQueue = new Q(0);

      queue.enqueue('never enqueues');

      expect(cappedQueue.size).to.equal(0);
    });
  });

  describe('#getSize()', () => {
    it('should return 0 if queue is empty', () => {
      expect(queue.getSize()).to.equal(0);
    });

    it('should return 1 if queue contains one item', () => {
      queue.enqueue(0);

      expect(queue.getSize()).to.equal(1);
    });
  });

  describe('#isFull()', () => {
    it('should return false if queue has not reached capacity', () => {
      const cappedQueue = new Q(1);

      expect(cappedQueue.isFull()).to.equal(false);
    });

    it('should return true if queue has reached capacity', () => {
      const cappedQueue = new Q(1);

      cappedQueue.enqueue(0);

      expect(cappedQueue.isFull()).to.equal(true);
    });
  });

  describe('#peek()', () => {
    it('should return value at top of queue', () => {
      queue.enqueue(0);

      expect(queue.peek()).to.equal(0);
    });

    it('should return undefined for empty queue', () => {
      expect(queue.peek()).to.equal(undefined);
    });
  });
});<|endoftext|>


<commit_before>const Busboy = require('busboy');
const fileFactory = require('./fileFactory');
const memHandler = require('./memHandler');
const tempFileHandler = require('./tempFileHandler');
const processNested = require('./processNested');
const {
  isFunc,
  debugLog,
  buildOptions,
  buildFields,
  parseFileName,
  uriDecodeFileName
} = require('./utilities');

/**
 * Processes multipart request
 * Builds a req.body object for fields
 * Builds a req.files object for files
 * @param  {Object}   options expressFileupload and Busboy options
 * @param  {Object}   req     Express request object
 * @param  {Object}   res     Express response object
 * @param  {Function} next    Express next method
 * @return {void}
 */
module.exports = (options, req, res, next) => {
  req.files = null;

  // Close connection with specified reason and http code, default: 400 Bad Request.
  const closeConnection = (code, reason) => {
    res.writeHead(code || 400, { Connection: 'close' });
    res.end(reason || 'Bad Request');
  };

  // Build busboy options and init busboy instance.
  let busboyOptions = buildOptions(options, {headers: req.headers});
  let busboy = new Busboy(busboyOptions);

  // Build multipart req.body fields
  busboy.on('field', (fieldname, val) => req.body = buildFields(req.body, fieldname, val));

  // Build req.files fields
  busboy.on('file', (fieldname, file, name, encoding, mime) => {
    // Decode file name if uriDecodeFileNames option set true.
    const filename = uriDecodeFileName(options, name);

    const {dataHandler, getFilePath, getFileSize, getHash, complete, cleanup} = options.useTempFiles
      ? tempFileHandler(options, fieldname, filename)
      : memHandler(options, fieldname, filename);

    file.on('limit', () => {
      debugLog(options, `File size limit reached for ${fieldname} -> ${name}, bytes: ${getFileSize()}`);
      // Run user defined limit handler if it has been set.
      if (isFunc(options.limitHandler)){
        return options.limitHandler(req, res, next);
      }
      // Close connection with 413 code if abortOnLimit set(default: false).
      if (options.abortOnLimit) {
        debugLog(options, `Aborting upload because of size limit ${fieldname} -> ${name}, bytes: ${getFileSize()}`);
        closeConnection(413, options.responseOnLimit);
        cleanup();
      }
    });

    file.on('data', dataHandler);

    file.on('end', () => {
      // Add file instance to the req.files
      req.files = buildFields(req.files, fieldname, fileFactory(
        {
          buffer: complete(),
          name: parseFileName(options, filename),
          tempFilePath: getFilePath(),
          size: getFileSize(),
          hash: getHash(),
          encoding,
          truncated: file.truncated,
          mimetype: mime
        },
        options
      ));
    });

    file.on('error', cleanup, next);

    // Debug logging for a new file upload.
    debugLog(options, `New file opload ${fieldname} -> ${name}, bytes: ${getFileSize()}`);
  });

  busboy.on('finish', () => {
    if (options.parseNested) {
      req.body = processNested(req.body);
      req.files = processNested(req.files);
    }
    next();
  });

  busboy.on('error', next);

  req.pipe(busboy);
};
<commit_msg>Update processMultipart.js<commit_after>const Busboy = require('busboy');
const fileFactory = require('./fileFactory');
const memHandler = require('./memHandler');
const tempFileHandler = require('./tempFileHandler');
const processNested = require('./processNested');
const {
  isFunc,
  debugLog,
  buildOptions,
  buildFields,
  parseFileName,
  uriDecodeFileName
} = require('./utilities');

/**
 * Processes multipart request
 * Builds a req.body object for fields
 * Builds a req.files object for files
 * @param  {Object}   options expressFileupload and Busboy options
 * @param  {Object}   req     Express request object
 * @param  {Object}   res     Express response object
 * @param  {Function} next    Express next method
 * @return {void}
 */
module.exports = (options, req, res, next) => {
  req.files = null;

  // Close connection with specified reason and http code, default: 400 Bad Request.
  const closeConnection = (code, reason) => {
    res.writeHead(code || 400, { Connection: 'close' });
    res.end(reason || 'Bad Request');
  };

  // Build busboy options and init busboy instance.
  let busboyOptions = buildOptions(options, {headers: req.headers});
  let busboy = new Busboy(busboyOptions);

  // Build multipart req.body fields
  busboy.on('field', (fieldname, val) => req.body = buildFields(req.body, fieldname, val));

  // Build req.files fields
  busboy.on('file', (fieldname, file, name, encoding, mime) => {
    // Decode file name if uriDecodeFileNames option set true.
    const filename = uriDecodeFileName(options, name);

    const {dataHandler, getFilePath, getFileSize, getHash, complete, cleanup} = options.useTempFiles
      ? tempFileHandler(options, fieldname, filename)
      : memHandler(options, fieldname, filename);

    file.on('limit', () => {
      debugLog(options, `File size limit reached for ${fieldname} -> ${filename}, bytes: ${getFileSize()}`);
      // Run user defined limit handler if it has been set.
      if (isFunc(options.limitHandler)){
        return options.limitHandler(req, res, next);
      }
      // Close connection with 413 code if abortOnLimit set(default: false).
      if (options.abortOnLimit) {
        debugLog(options, `Aborting upload because of size limit ${fieldname} -> ${filename}, bytes: ${getFileSize()}`);
        closeConnection(413, options.responseOnLimit);
        cleanup();
      }
    });

    file.on('data', dataHandler);

    file.on('end', () => {
      // Add file instance to the req.files
      req.files = buildFields(req.files, fieldname, fileFactory(
        {
          buffer: complete(),
          name: parseFileName(options, filename),
          tempFilePath: getFilePath(),
          size: getFileSize(),
          hash: getHash(),
          encoding,
          truncated: file.truncated,
          mimetype: mime
        },
        options
      ));
    });

    file.on('error', cleanup, next);

    // Debug logging for a new file upload.
    debugLog(options, `New file opload ${fieldname} -> ${filename}, bytes: ${getFileSize()}`);
  });

  busboy.on('finish', () => {
    if (options.parseNested) {
      req.body = processNested(req.body);
      req.files = processNested(req.files);
    }
    next();
  });

  busboy.on('error', next);

  req.pipe(busboy);
};
<|endoftext|>


<commit_before>(function(){
	var app = angular.module('partybox',[totimeFilter]);

	var mopidy = new Mopidy({
		webSocketUrl: "ws://vela:6680/mopidy/ws/"
	});

	app.controller('PlayerController',['$http', '$q',function($http,$q){
		var player = this;
		player.currentTlTrack = {};

		/**Gets the Cover for a given album, artist pair**/
		var getCover = function(tl_track){
			var lookup_uri = tl_track.track.album.uri.split(":").pop();
			var queryURL = 'https://api.spotify.com/v1/albums/'+lookup_uri;
			console.log(queryURL);
			$http.get(queryURL).success(function(data){
				console.log(data);
				player.currentTlTrack.albumCover = data.images[0]["url"];
			});
		}

		var trackSet = function(tl_track){

			player.currentTlTrack.name = tl_track.track.name;
			player.currentTlTrack.artist = tl_track.track.artists[0].name;
			player.currentTlTrack.album = tl_track.track.album.name;
			return tl_track;
		}

		var getCurrentTrack = function(){
			$q.when(mopidy.playback.getCurrentTlTrack())
			.then(trackSet, console.error.bind(console))
			.then(getCover, console.error.bind(console));
		}

		mopidy.on("state:online", getCurrentTrack);
		mopidy.on("event:trackPlaybackStarted",getCurrentTrack);
	}]);

	app.controller('TracklistController',function($q){

		var tracklist = this;
		tracklist.tracks = [];

		var getTracks = function(){
			console.log('getting tracks');
			var processTracks = function(tracks){
				console.log(tracks);
				tracklist.tracks = tracks.map(function(e){return e.track}); //extracts only the track object in the tracklist
			}
			$q.when(mopidy.tracklist.getTlTracks()).then(processTracks, console.error.bind(console));
		}

		mopidy.on("state:online",getTracks);
		mopidy.on("event:trackPlaybackStarted",getTracks);
		mopidy.on("event:playbackStateChanged",getTracks);
	});

	app.controller('SearchController',['$q',function($q){
		var searchCtrl = this;
		searchCtrl.results = {};
		searchCtrl.results.tracks = [];
		searchCtrl.query = '';

		this.search = function(query){
			console.log(searchCtrl.query);
			var processTracks = function(results){
				console.log(results);
				//Mopidy does not consistently place the spotify results in the correct order

				searchCtrl.results.tracks = results.map(function(searchResult){
					return searchResult.tracks
				});
				searchCtrl.results.tracks = _.flatten(_.compact(searchCtrl.results.tracks));
				return results;
			}
			$q.when(mopidy.library.search({"any": searchCtrl.query})).then(processTracks,console.error.bind(console));
		}

	}]);

})();
<commit_msg>branch fix<commit_after>(function(){
	var app = angular.module('partybox',[]);

	var mopidy = new Mopidy({
		webSocketUrl: "ws://vela:6680/mopidy/ws/"
	});

	app.controller('PlayerController',['$http', '$q',function($http,$q){
		var player = this;
		player.currentTlTrack = {};

		/**Gets the Cover for a given album, artist pair**/
		var getCover = function(tl_track){
			var lookup_uri = tl_track.track.album.uri.split(":").pop();
			var queryURL = 'https://api.spotify.com/v1/albums/'+lookup_uri;
			console.log(queryURL);
			$http.get(queryURL).success(function(data){
				console.log(data);
				player.currentTlTrack.albumCover = data.images[0]["url"];
			});
		}

		var trackSet = function(tl_track){

			player.currentTlTrack.name = tl_track.track.name;
			player.currentTlTrack.artist = tl_track.track.artists[0].name;
			player.currentTlTrack.album = tl_track.track.album.name;
			return tl_track;
		}

		var getCurrentTrack = function(){
			$q.when(mopidy.playback.getCurrentTlTrack())
			.then(trackSet, console.error.bind(console))
			.then(getCover, console.error.bind(console));
		}

		mopidy.on("state:online", getCurrentTrack);
		mopidy.on("event:trackPlaybackStarted",getCurrentTrack);
	}]);

	app.controller('TracklistController',function($q){

		var tracklist = this;
		tracklist.tracks = [];

		var getTracks = function(){
			console.log('getting tracks');
			var processTracks = function(tracks){
				console.log(tracks);
				tracklist.tracks = tracks.map(function(e){return e.track}); //extracts only the track object in the tracklist
			}
			$q.when(mopidy.tracklist.getTlTracks()).then(processTracks, console.error.bind(console));
		}

		mopidy.on("state:online",getTracks);
		mopidy.on("event:trackPlaybackStarted",getTracks);
		mopidy.on("event:playbackStateChanged",getTracks);
	});

	app.controller('SearchController',['$q',function($q){
		var searchCtrl = this;
		searchCtrl.results = {};
		searchCtrl.results.tracks = [];
		searchCtrl.query = '';

		this.search = function(query){
			console.log(searchCtrl.query);
			var processTracks = function(results){
				console.log(results);
				//Mopidy does not consistently place the spotify results in the correct order

				searchCtrl.results.tracks = results.map(function(searchResult){
					return searchResult.tracks
				});
				searchCtrl.results.tracks = _.flatten(_.compact(searchCtrl.results.tracks));
				return results;
			}
			$q.when(mopidy.library.search({"any": searchCtrl.query})).then(processTracks,console.error.bind(console));
		}

	}]);

})();
<|endoftext|>


<commit_before>'use strict';

var connect = require('connect');
var http = require('http');
var fs = require('fs');
var path = require('path');
var commands = require('../commands');
var promisify = require('../promisify');
var wendy = require('../wendy');
var gaze = promisify(require('gaze'));
var lstat = promisify(fs.lstat);

var makeCommands = [ commands.find('make') ];

module.exports = function(config, log, inputFiles) {
	var watchPatterns = config.project.files;
	var distDir = config.project.distDir;
	var port = config.port;

	return gaze(watchPatterns).then(function(watcher) {
		var makePromise = wendy(makeCommands);
		var dirty = false;

		watcher.on('all', function(event, filePath) {
			// Ignore directories, we only care about files
			lstat(filePath).then(function(stat) {
				if (stat.isFile()) {
					filePath = path.relative(process.cwd(), filePath);
					log.info('%s was %s', filePath, event);
					dirty = true;
				}
			});
		});

		connect.errorHandler.title = 'nBob';
		var app = connect()
			.use(connect.logger('dev'))
			.use(function(req, res, next) {
				if (dirty) {
					makePromise = wendy(makeCommands);
					dirty = false;
				}
				makePromise.then(function() {
					next();
				}, function(error) {
					next(error);
				});
			})
			.use(connect.static(distDir))
			.use(connect.directory(distDir, { icons: true }))
			.use(connect.errorHandler());

		http.createServer(app).listen(port);
		log.info('Listening on port: %d', port);

		// We did not modify input files ourselves
		return inputFiles;
	});
};
<commit_msg>Enabled favicon connect module again to reduce favicon spam in log<commit_after>'use strict';

var connect = require('connect');
var http = require('http');
var fs = require('fs');
var path = require('path');
var commands = require('../commands');
var promisify = require('../promisify');
var wendy = require('../wendy');
var gaze = promisify(require('gaze'));
var lstat = promisify(fs.lstat);

var makeCommands = [ commands.find('make') ];

module.exports = function(config, log, inputFiles) {
	var watchPatterns = config.project.files;
	var distDir = config.project.distDir;
	var port = config.port;

	return gaze(watchPatterns).then(function(watcher) {
		var makePromise = wendy(makeCommands);
		var dirty = false;

		watcher.on('all', function(event, filePath) {
			// Ignore directories, we only care about files
			lstat(filePath).then(function(stat) {
				if (stat.isFile()) {
					filePath = path.relative(process.cwd(), filePath);
					log.info('%s was %s', filePath, event);
					dirty = true;
				}
			});
		});

		connect.errorHandler.title = 'nBob';
		var app = connect()
			.use(connect.favicon())
			.use(connect.logger('dev'))
			.use(function(req, res, next) {
				if (dirty) {
					makePromise = wendy(makeCommands);
					dirty = false;
				}
				makePromise.then(function() {
					next();
				}, function(error) {
					next(error);
				});
			})
			.use(connect.static(distDir))
			.use(connect.directory(distDir, { icons: true }))
			.use(connect.errorHandler());

		http.createServer(app).listen(port);
		log.info('Listening on port: %d', port);

		// We did not modify input files ourselves
		return inputFiles;
	});
};
<|endoftext|>