<commit_before>const LRU = cjsRequire('lru-cache')
const { IndexedCramFile, CraiIndex } = cjsRequire('@gmod/cram')
const { CramSizeLimitError } = cjsRequire('@gmod/cram/errors')

const { Buffer } = cjsRequire('buffer')

const cramIndexedFilesCache = LRU(5)

define( [
            'dojo/_base/declare',
            'JBrowse/Errors',
            'JBrowse/Store/SeqFeature',
            'JBrowse/Store/DeferredStatsMixin',
            'JBrowse/Store/DeferredFeaturesMixin',
            'JBrowse/Store/SeqFeature/GlobalStatsEstimationMixin',
            'JBrowse/Model/XHRBlob',
            'JBrowse/Model/SimpleFeature',
        ],
        function(
            declare,
            Errors,
            SeqFeatureStore,
            DeferredStatsMixin,
            DeferredFeaturesMixin,
            GlobalStatsEstimationMixin,
            XHRBlob,
            SimpleFeature,
        ) {

// wrapper class to make old JBrowse *Blob data access classes work with
// the new-style filehandle API expected by the cram code

class BlobWrapper {
    constructor(oldStyleBlob) {
        this.blob = oldStyleBlob
    }

    read(buffer, offset = 0, length, position) {
        return new Promise((resolve,reject) => {
            this.blob.read(
                position,
                length,
                dataArrayBuffer => {
                    const data = Buffer.from(dataArrayBuffer)
                    data.copy(buffer, offset)
                    resolve()
                },
                reject,
            )
        })
    }

    readFile() {
        return new Promise((resolve, reject) => {
            this.blob.fetch( dataArrayBuffer => {
                resolve(Buffer.from(dataArrayBuffer))
            }, reject)
        })
    }

    stat() {
        return new Promise((resolve, reject) => {
            this.blob.stat(resolve, reject)
        })
    }

    toString() {
        return ( this.blob.url  ? this.blob.url :
                 this.blob.blob ? this.blob.blob.name : undefined ) || undefined;
    }
}

return declare( [ SeqFeatureStore, DeferredStatsMixin, DeferredFeaturesMixin, GlobalStatsEstimationMixin ],

/**
 * @lends JBrowse.Store.SeqFeature.CRAM
 */
{
    /**
     * Data backend for reading feature data directly from a
     * web-accessible CRAM file.
     *
     * @constructs
     */
    constructor: function( args ) {

        let dataBlob
        if (args.cram)
            dataBlob = new BlobWrapper(args.cram)
        else if (args.urlTemplate)
            dataBlob = new BlobWrapper(new XHRBlob(this.resolveUrl(args.urlTemplate || 'data.cram')))
        else throw new Error('must provide either `cram` or `urlTemplate`')

        let indexBlob
        if (args.crai)
            indexBlob = new BlobWrapper(args.crai)
        else if (args.craiUrlTemplate)
            indexBlob = new BlobWrapper(new XHRBlob(this.resolveUrl(args.craiUrlTemplate)))
        else if (args.urlTemplate)
            indexBlob = new BlobWrapper(new XHRBlob(this.resolveUrl(args.urlTemplate+'.crai')))
        else throw new Error('no index provided, must provide a CRAM index')

        this.source = dataBlob.toString()

        // LRU-cache the CRAM object so we don't have to re-download the
        // index when we switch chromosomes
        const cacheKey = `data: ${dataBlob}, index: ${indexBlob}`
        this.cram = cramIndexedFilesCache.get(cacheKey)
        if (!this.cram) {
            this.cram = new IndexedCramFile({
                cramFilehandle: dataBlob,
                index: new CraiIndex({filehandle: indexBlob}),
                seqFetch: this._seqFetch.bind(this),
                checkSequenceMD5: false,
            })

            cramIndexedFilesCache.set(cacheKey, this.cram)
        }

        // pre-download the index before running the statistics estimation so that the stats
        // estimation doesn't time out
        this.cram.hasDataForReferenceSequence(0)
            .then(() => this.cram.cram.getSamHeader())
            .then(samHeader => {
                this._setSamHeader(samHeader)
            })
            .then(() => {
                this._deferred.features.resolve({success:true});
            })
            .then(() => this._estimateGlobalStats())
            .then(stats => {
                this.globalStats = stats;
                this._deferred.stats.resolve({success:true});
            })
            .catch(err => {
                this._deferred.features.reject(err)
                this._deferred.stats.reject(err)
            })

        this.storeTimeout = args.storeTimeout || 3000;
    },

    // process the parsed SAM header from the cram file
    _setSamHeader(samHeader) {
        this._samHeader = {}

        // use the @SQ lines in the header to figure out the
        // mapping between ref seq ID numbers and names
        const refSeqIdToName = []
        const refSeqNameToId = {}
        const sqLines = samHeader.filter(l => l.tag === 'SQ')
        sqLines.forEach((sqLine, seqId) => {
            sqLine.data.forEach(item => {
                if (item.tag === 'SN') {
                    // this is the seq name
                    const seqName = item.value
                    refSeqNameToId[seqName] = seqId
                    refSeqIdToName[seqId] = seqName
                }
            })
        })
        if (refSeqIdToName.length) {
            this._samHeader.refSeqIdToName = refSeqIdToName
            this._samHeader.refSeqNameToId = refSeqNameToId
        }
    },

    _refNameToId(refName) {
        // use info from the SAM header if possible, but fall back to using
        // the ref seq order from when the browser's refseqs were loaded
        if (this._samHeader.refSeqNameToId)
            return this._samHeader.refSeqNameToId[refName]
        else
            return this.browser.getRefSeqNumber(refName)
    },

    _refIdToName(refId) {
        // use info from the SAM header if possible, but fall back to using
        // the ref seq order from when the browser's refseqs were loaded
        if (this._samHeader.refSeqIdToName) {
            return this._samHeader.refSeqIdToName[refId]
        } else {
            let ref = this.browser.getRefSeqById(refId)
            return ref ? ref.name : undefined
        }
    },

    _getRefSeqStore() {
        return new Promise((resolve,reject) => {
            this.browser.getStore('refseqs',resolve,reject)
        })
    },

    // used by the CRAM backend to fetch a region of the underlying reference
    // sequence.  needed for some of its calculations
    async _seqFetch(seqId, start, end) {
        start -= 1 // convert from 1-based closed to interbase

        const refSeqStore = await this._getRefSeqStore()
        if (!refSeqStore) return undefined
        const refName = this._refIdToName(seqId)
        if (!refName) return undefined

        const seqChunks = await new Promise((resolve,reject) => {
            let features = []
            refSeqStore.getFeatures(
                {ref: refName, start: start-1, end},
                f => features.push(f),
                () => resolve(features),
                reject
            )
        })

        const trimmed = []
        seqChunks
        .sort((a,b) => a.get('start') - b.get('start'))
        .forEach( (chunk,i) => {
            let chunkStart = chunk.get('start')
            let chunkEnd = chunk.get('end')
            let trimStart = Math.max(start - chunkStart, 0)
            let trimEnd = Math.min(end - chunkStart, chunkEnd-chunkStart)
            let trimLength = trimEnd - trimStart
            let chunkSeq = chunk.get('seq') || chunk.get('residues')
            trimmed.push(chunkSeq.substr(trimStart,trimLength))
        })

        const sequence = trimmed.join('')
        if (sequence.length !== (end-start))
            throw new Error(`sequence fetch failed: fetching ${
                (start-1).toLocaleString()}-${end.toLocaleString()
                } only returned ${
                    sequence.length.toLocaleString()
                } bases, but should have returned ${
                    (end-start).toLocaleString()
                }`)
        return sequence
    },

    /**
     * Interrogate whether a store has data for a given reference
     * sequence.  Calls the given callback with either true or false.
     *
     * Implemented as a binary interrogation because some stores are
     * smart enough to regularize reference sequence names, while
     * others are not.
     */
    hasRefSeq: function( seqName, callback, errorCallback ) {
        seqName = this.browser.regularizeReferenceName( seqName );
        const refSeqNumber = this._refNameToId(seqName)
        if (refSeqNumber === undefined) callback(false)

        this._deferred.stats
        .then(() => this.cram.hasDataForReferenceSequence(refSeqNumber))
        .then(callback, errorCallback)
    },

    // called by getFeatures from the DeferredFeaturesMixin
    _getFeatures: function( query, featCallback, endCallback, errorCallback ) {
        //this.bam.fetch( query.ref ? query.ref : this.refSeq.name, query.start, query.end, featCallback, endCallback, errorCallback );
        const seqName = query.ref || this.refSeq.name
        const refSeqNumber = this._refNameToId(seqName)
        if (refSeqNumber === undefined) {
            endCallback()
            return
        }

        this.cram.getRecordsForRange(refSeqNumber, query.start + 1, query.end)
            .then(records => {
                for (let i = 0; i < records.length; i+= 1) {
                    featCallback(this._cramRecordToFeature(records[i]))
                }

                endCallback()
            })
            .catch(err => {
                // map the CramSizeLimitError to JBrowse Errors.DataOverflow
                if (err instanceof CramSizeLimitError) {
                    err = new Errors.DataOverflow(err)
                }

                errorCallback(err)
            })
    },

    _cramRecordToFeature(record) {
        const data = {
            name: record.readName,
            start: record.alignmentStart-1,
            end: record.alignmentStart+record.lengthOnRef-1,
            cram_read_features: record.readFeatures,
            type: 'match',
            mapping_quality: record.mappingQuality,
            flags: `0x${record.flags.toString(16)}`,
            cramFlags: `0x${record.cramFlags.toString(16)}`,
            strand: record.isReverseComplemented() ? -1 : 1,
            qual: (record.qualityScores || []).map(q => q+33).join(' '),
            seq: record.readBases,
            seq_id: this._refIdToName(record.sequenceId),

            qc_failed: record.isFailedQc(),
            secondary_alignment: record.isSecondary(),
            supplementary_alignment: record.isSupplementary(),
            multi_segment_template: record.isPaired(),
            multi_segment_all_correctly_aligned: record.isProperlyPaired(),
            multi_segment_next_segment_unmapped: record.isMateUnmapped(),
            multi_segment_first: record.isRead1(),
            multi_segment_last: record.isRead2(),
            multi_segment_next_segment_reversed: record.isMateReverseComplemented(),
            unmapped: record.isSegmentUnmapped(),
            next_seq_id: record.mate ? this._refIdToName(record.mate.sequenceId) : undefined,
            next_segment_position: record.mate
                ? ( this._refIdToName(record.mate.sequenceId)+':'+record.mate.alignmentStart) : undefined,
            tags: record.tags,
        }
        return new SimpleFeature({
            data,
            id: record.uniqueId
        })
    },

    saveStore: function() {
        return {
            urlTemplate: this.config.bam.url,
            baiUrlTemplate: this.config.bai.url
        };
    }

});
});
<commit_msg>make jbrowse cram unique ids start at 1 and pre-stringify them<commit_after>const LRU = cjsRequire('lru-cache')
const { IndexedCramFile, CraiIndex } = cjsRequire('@gmod/cram')
const { CramSizeLimitError } = cjsRequire('@gmod/cram/errors')

const { Buffer } = cjsRequire('buffer')

const cramIndexedFilesCache = LRU(5)

define( [
            'dojo/_base/declare',
            'JBrowse/Errors',
            'JBrowse/Store/SeqFeature',
            'JBrowse/Store/DeferredStatsMixin',
            'JBrowse/Store/DeferredFeaturesMixin',
            'JBrowse/Store/SeqFeature/GlobalStatsEstimationMixin',
            'JBrowse/Model/XHRBlob',
            'JBrowse/Model/SimpleFeature',
        ],
        function(
            declare,
            Errors,
            SeqFeatureStore,
            DeferredStatsMixin,
            DeferredFeaturesMixin,
            GlobalStatsEstimationMixin,
            XHRBlob,
            SimpleFeature,
        ) {

// wrapper class to make old JBrowse *Blob data access classes work with
// the new-style filehandle API expected by the cram code

class BlobWrapper {
    constructor(oldStyleBlob) {
        this.blob = oldStyleBlob
    }

    read(buffer, offset = 0, length, position) {
        return new Promise((resolve,reject) => {
            this.blob.read(
                position,
                length,
                dataArrayBuffer => {
                    const data = Buffer.from(dataArrayBuffer)
                    data.copy(buffer, offset)
                    resolve()
                },
                reject,
            )
        })
    }

    readFile() {
        return new Promise((resolve, reject) => {
            this.blob.fetch( dataArrayBuffer => {
                resolve(Buffer.from(dataArrayBuffer))
            }, reject)
        })
    }

    stat() {
        return new Promise((resolve, reject) => {
            this.blob.stat(resolve, reject)
        })
    }

    toString() {
        return ( this.blob.url  ? this.blob.url :
                 this.blob.blob ? this.blob.blob.name : undefined ) || undefined;
    }
}

return declare( [ SeqFeatureStore, DeferredStatsMixin, DeferredFeaturesMixin, GlobalStatsEstimationMixin ],

/**
 * @lends JBrowse.Store.SeqFeature.CRAM
 */
{
    /**
     * Data backend for reading feature data directly from a
     * web-accessible CRAM file.
     *
     * @constructs
     */
    constructor: function( args ) {

        let dataBlob
        if (args.cram)
            dataBlob = new BlobWrapper(args.cram)
        else if (args.urlTemplate)
            dataBlob = new BlobWrapper(new XHRBlob(this.resolveUrl(args.urlTemplate || 'data.cram')))
        else throw new Error('must provide either `cram` or `urlTemplate`')

        let indexBlob
        if (args.crai)
            indexBlob = new BlobWrapper(args.crai)
        else if (args.craiUrlTemplate)
            indexBlob = new BlobWrapper(new XHRBlob(this.resolveUrl(args.craiUrlTemplate)))
        else if (args.urlTemplate)
            indexBlob = new BlobWrapper(new XHRBlob(this.resolveUrl(args.urlTemplate+'.crai')))
        else throw new Error('no index provided, must provide a CRAM index')

        this.source = dataBlob.toString()

        // LRU-cache the CRAM object so we don't have to re-download the
        // index when we switch chromosomes
        const cacheKey = `data: ${dataBlob}, index: ${indexBlob}`
        this.cram = cramIndexedFilesCache.get(cacheKey)
        if (!this.cram) {
            this.cram = new IndexedCramFile({
                cramFilehandle: dataBlob,
                index: new CraiIndex({filehandle: indexBlob}),
                seqFetch: this._seqFetch.bind(this),
                checkSequenceMD5: false,
            })

            cramIndexedFilesCache.set(cacheKey, this.cram)
        }

        // pre-download the index before running the statistics estimation so that the stats
        // estimation doesn't time out
        this.cram.hasDataForReferenceSequence(0)
            .then(() => this.cram.cram.getSamHeader())
            .then(samHeader => {
                this._setSamHeader(samHeader)
            })
            .then(() => {
                this._deferred.features.resolve({success:true});
            })
            .then(() => this._estimateGlobalStats())
            .then(stats => {
                this.globalStats = stats;
                this._deferred.stats.resolve({success:true});
            })
            .catch(err => {
                this._deferred.features.reject(err)
                this._deferred.stats.reject(err)
            })

        this.storeTimeout = args.storeTimeout || 3000;
    },

    // process the parsed SAM header from the cram file
    _setSamHeader(samHeader) {
        this._samHeader = {}

        // use the @SQ lines in the header to figure out the
        // mapping between ref seq ID numbers and names
        const refSeqIdToName = []
        const refSeqNameToId = {}
        const sqLines = samHeader.filter(l => l.tag === 'SQ')
        sqLines.forEach((sqLine, seqId) => {
            sqLine.data.forEach(item => {
                if (item.tag === 'SN') {
                    // this is the seq name
                    const seqName = item.value
                    refSeqNameToId[seqName] = seqId
                    refSeqIdToName[seqId] = seqName
                }
            })
        })
        if (refSeqIdToName.length) {
            this._samHeader.refSeqIdToName = refSeqIdToName
            this._samHeader.refSeqNameToId = refSeqNameToId
        }
    },

    _refNameToId(refName) {
        // use info from the SAM header if possible, but fall back to using
        // the ref seq order from when the browser's refseqs were loaded
        if (this._samHeader.refSeqNameToId)
            return this._samHeader.refSeqNameToId[refName]
        else
            return this.browser.getRefSeqNumber(refName)
    },

    _refIdToName(refId) {
        // use info from the SAM header if possible, but fall back to using
        // the ref seq order from when the browser's refseqs were loaded
        if (this._samHeader.refSeqIdToName) {
            return this._samHeader.refSeqIdToName[refId]
        } else {
            let ref = this.browser.getRefSeqById(refId)
            return ref ? ref.name : undefined
        }
    },

    _getRefSeqStore() {
        return new Promise((resolve,reject) => {
            this.browser.getStore('refseqs',resolve,reject)
        })
    },

    // used by the CRAM backend to fetch a region of the underlying reference
    // sequence.  needed for some of its calculations
    async _seqFetch(seqId, start, end) {
        start -= 1 // convert from 1-based closed to interbase

        const refSeqStore = await this._getRefSeqStore()
        if (!refSeqStore) return undefined
        const refName = this._refIdToName(seqId)
        if (!refName) return undefined

        const seqChunks = await new Promise((resolve,reject) => {
            let features = []
            refSeqStore.getFeatures(
                {ref: refName, start: start-1, end},
                f => features.push(f),
                () => resolve(features),
                reject
            )
        })

        const trimmed = []
        seqChunks
        .sort((a,b) => a.get('start') - b.get('start'))
        .forEach( (chunk,i) => {
            let chunkStart = chunk.get('start')
            let chunkEnd = chunk.get('end')
            let trimStart = Math.max(start - chunkStart, 0)
            let trimEnd = Math.min(end - chunkStart, chunkEnd-chunkStart)
            let trimLength = trimEnd - trimStart
            let chunkSeq = chunk.get('seq') || chunk.get('residues')
            trimmed.push(chunkSeq.substr(trimStart,trimLength))
        })

        const sequence = trimmed.join('')
        if (sequence.length !== (end-start))
            throw new Error(`sequence fetch failed: fetching ${
                (start-1).toLocaleString()}-${end.toLocaleString()
                } only returned ${
                    sequence.length.toLocaleString()
                } bases, but should have returned ${
                    (end-start).toLocaleString()
                }`)
        return sequence
    },

    /**
     * Interrogate whether a store has data for a given reference
     * sequence.  Calls the given callback with either true or false.
     *
     * Implemented as a binary interrogation because some stores are
     * smart enough to regularize reference sequence names, while
     * others are not.
     */
    hasRefSeq: function( seqName, callback, errorCallback ) {
        seqName = this.browser.regularizeReferenceName( seqName );
        const refSeqNumber = this._refNameToId(seqName)
        if (refSeqNumber === undefined) callback(false)

        this._deferred.stats
        .then(() => this.cram.hasDataForReferenceSequence(refSeqNumber))
        .then(callback, errorCallback)
    },

    // called by getFeatures from the DeferredFeaturesMixin
    _getFeatures: function( query, featCallback, endCallback, errorCallback ) {
        //this.bam.fetch( query.ref ? query.ref : this.refSeq.name, query.start, query.end, featCallback, endCallback, errorCallback );
        const seqName = query.ref || this.refSeq.name
        const refSeqNumber = this._refNameToId(seqName)
        if (refSeqNumber === undefined) {
            endCallback()
            return
        }

        this.cram.getRecordsForRange(refSeqNumber, query.start + 1, query.end)
            .then(records => {
                for (let i = 0; i < records.length; i+= 1) {
                    featCallback(this._cramRecordToFeature(records[i]))
                }

                endCallback()
            })
            .catch(err => {
                // map the CramSizeLimitError to JBrowse Errors.DataOverflow
                if (err instanceof CramSizeLimitError) {
                    err = new Errors.DataOverflow(err)
                }

                errorCallback(err)
            })
    },

    _cramRecordToFeature(record) {
        const data = {
            name: record.readName,
            start: record.alignmentStart-1,
            end: record.alignmentStart+record.lengthOnRef-1,
            cram_read_features: record.readFeatures,
            type: 'match',
            mapping_quality: record.mappingQuality,
            flags: `0x${record.flags.toString(16)}`,
            cramFlags: `0x${record.cramFlags.toString(16)}`,
            strand: record.isReverseComplemented() ? -1 : 1,
            qual: (record.qualityScores || []).map(q => q+33).join(' '),
            seq: record.readBases,
            seq_id: this._refIdToName(record.sequenceId),

            qc_failed: record.isFailedQc(),
            secondary_alignment: record.isSecondary(),
            supplementary_alignment: record.isSupplementary(),
            multi_segment_template: record.isPaired(),
            multi_segment_all_correctly_aligned: record.isProperlyPaired(),
            multi_segment_next_segment_unmapped: record.isMateUnmapped(),
            multi_segment_first: record.isRead1(),
            multi_segment_last: record.isRead2(),
            multi_segment_next_segment_reversed: record.isMateReverseComplemented(),
            unmapped: record.isSegmentUnmapped(),
            next_seq_id: record.mate ? this._refIdToName(record.mate.sequenceId) : undefined,
            next_segment_position: record.mate
                ? ( this._refIdToName(record.mate.sequenceId)+':'+record.mate.alignmentStart) : undefined,
            tags: record.tags,
        }
        return new SimpleFeature({
            data,
            id: (record.uniqueId + 1).toString(),
        })
    },

    saveStore: function() {
        return {
            urlTemplate: this.config.bam.url,
            baiUrlTemplate: this.config.bai.url
        };
    }

});
});
<|endoftext|>


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

return declare( HTMLFeatures,
/**
 * @lends JBrowse.View.Track.Alignments
 */
{

    constructor: function() {
    },

    renderFeature: function(feature, uniqueId, block, scale, containerStart, containerEnd, destBlock ) {
        var featDiv = this.inherited( arguments );
        this._drawMismatches( feature, featDiv, scale );
        return featDiv;
    },

    _drawMismatches: function( feature, featDiv, scale ) {

        // recall: scale is pixels/basepair
        var charSize = this.getCharacterMeasurements();
        if ( scale >= charSize.w ) {
            var mismatches = this._getMismatches( feature );

            array.forEach( mismatches, function( mismatch ) {
                array.forEach( mismatch.bases, function( base, i ) {
                    dojo.create('span', {
                                    className: 'mismatch base base_'+base.toLowerCase(),
                                    style: {
                                        position: 'absolute',
                                        left: scale * (mismatch.start+i) + 'px',
                                        width: scale + 'px',
                                        height: '1.2em',
                                        top: '50%',
                                        marginTop: '-0.6em'
                                    },
                                    innerHTML: base
                                }, featDiv );
               }, this );
            });
        }
    },

    _getMismatches: function( feature ) {
        var seq = feature.get('seq');
        if( ! seq )
            return m;

        // parse the MD tag if it has one
        var mdTag = feature.get('MD');
        if( mdTag ) {
            return this._mdToMismatches( feature, mdTag );
        }

        return [];
    },

    /**
     * parse a SAM MD tag to find mismatching bases of the template versus the reference
     * @returns {Array[Object]} array of mismatches and their positions
     * @private
     */
    _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;
              while( i-- ) {
                  curr.bases += '*';
              }
              nextRecord();
          }
          else if( token.match(/^[a-z]/i) ) { // mismatch
              curr.bases = seq.substr( curr.start, token.length );
              nextRecord();
          }
        });
        return mismatchRecords;
    },

    // stub out subfeature rendering, this track doesn't render subfeatures
    renderSubfeature: function() {},

    /**
     * @returns {Object} containing h and w,
     *      in pixels, of the characters being used for sequences
     */
    getCharacterMeasurements: function() {
        if( !this._measurements )
            this._measurements = this._measureSequenceCharacterSize( this.div );
        return this._measurements;
    },

    /**
     * Conducts a test with DOM elements to measure sequence text width
     * and height.
     */
    _measureSequenceCharacterSize: function( containerElement ) {
        var widthTest = dojo.create('div', {
                                        innerHTML: 'A'
                                            +'C'
                                            +'T'
                                            +'G'
                                            +'N',
                                        style: {
                                            visibility: 'hidden',
                                            position: 'absolute',
                                            left: '0px'
                                        }
                                    }, containerElement );
        var result = {
            w:  widthTest.clientWidth / 5,
            h: widthTest.clientHeight
        };
        containerElement.removeChild(widthTest);
        return result;
    },

    /**
     * Make a default feature detail page for the given feature.
     * @returns {HTMLElement} feature detail page HTML
     */
    defaultFeatureDetail: function( /** JBrowse.Track */ track, /** Object */ f, /** HTMLElement */ div ) {
        var container = this.inherited( arguments );

        var fmt = dojo.hitch( this, '_fmtDetailField' );

        // if( f.get('strand') == -1 ) {
        //     dojo.create('div', { className: 'message', innerHTML: '' })
        // }
        var alignment = '
'+f.get('seq')+'
';
        if( f.get('seq') && f.get('qual') ) {
            container.innerHTML += fmt('Sequence quality scores', this._renderQual( f ) );
        }

        return container;
    },

    _renderQual: function( feature ) {

        var seq  = feature.get('seq'),
            qual = feature.get('qual');
        if( !seq || !qual )
            return '';

        qual = qual.split(/\s+/);
        var fieldWidth = (''+Math.max.apply( Math, qual )).length;

        // pad the sequence with spaces
        var seqPadding = ' ';
        while( seqPadding.length < fieldWidth-1 ) {
            seqPadding += ' ';
        }
        var paddedSeq = array.map( seq, function(s) {
            return s + seqPadding;
        });

        var tableRowHTML = function(fields, class_) {
            class_ = class_ ? ' class="'+class_+'"' : '';
            return '
'+array.map( fields, function(f) { return ''+f+'	'; }).join('')+'
';
        };
        // insert newlines
        var rendered = '';
        var lineFields = Math.round(55/fieldWidth);
        while( paddedSeq.length ) {
            var line = paddedSeq.slice(0,Math.min( paddedSeq.length, lineFields ) );
            paddedSeq = paddedSeq.slice(lineFields);
            rendered += tableRowHTML( line, 'seq' );
            line = qual.slice(0, Math.min( qual.length, lineFields ));
            qual = qual.slice(lineFields);
            rendered += tableRowHTML( line, 'qual' );
        }
        return '
'+rendered+'
';
    }
});
});<commit_msg>draw base mismatches on alignment glyphs as colored lines when zoomed further out<commit_after>define( ['dojo/_base/declare',
         'dojo/_base/array',
         'JBrowse/View/Track/HTMLFeatures'
        ],
        function( declare, array, HTMLFeatures ) {

return declare( HTMLFeatures,
/**
 * @lends JBrowse.View.Track.Alignments
 */
{

    constructor: function() {
    },

    renderFeature: function(feature, uniqueId, block, scale, containerStart, containerEnd, destBlock ) {
        var featDiv = this.inherited( arguments );
        this._drawMismatches( feature, featDiv, scale );
        return featDiv;
    },

    _drawMismatches: function( feature, featDiv, scale ) {
        // recall: scale is pixels/basepair
        if ( scale >= 1 ) {
            var mismatches = this._getMismatches( feature );
            var charSize = this.getCharacterMeasurements();
            var drawChars = scale >= charSize.w;

            array.forEach( mismatches, function( mismatch ) {
                array.forEach( mismatch.bases, function( base, i ) {
                    dojo.create('span', {
                                    className: 'mismatch base base_'+base.toLowerCase(),
                                    style: {
                                        position: 'absolute',
                                        left: scale * (mismatch.start+i) + 'px',
                                        width: scale + 'px',
                                        height: '1.2em',
                                        top: '50%',
                                        marginTop: '-0.6em'
                                    },
                                    innerHTML: drawChars ? base : ''
                                }, featDiv );
               }, this );
            });
        }
    },

    _getMismatches: function( feature ) {
        var seq = feature.get('seq');
        if( ! seq )
            return m;

        // parse the MD tag if it has one
        var mdTag = feature.get('MD');
        if( mdTag ) {
            return this._mdToMismatches( feature, mdTag );
        }

        return [];
    },

    /**
     * parse a SAM MD tag to find mismatching bases of the template versus the reference
     * @returns {Array[Object]} array of mismatches and their positions
     * @private
     */
    _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;
              while( i-- ) {
                  curr.bases += '*';
              }
              nextRecord();
          }
          else if( token.match(/^[a-z]/i) ) { // mismatch
              curr.bases = seq.substr( curr.start, token.length );
              nextRecord();
          }
        });
        return mismatchRecords;
    },

    // stub out subfeature rendering, this track doesn't render subfeatures
    renderSubfeature: function() {},

    /**
     * @returns {Object} containing h and w,
     *      in pixels, of the characters being used for sequences
     */
    getCharacterMeasurements: function() {
        if( !this._measurements )
            this._measurements = this._measureSequenceCharacterSize( this.div );
        return this._measurements;
    },

    /**
     * Conducts a test with DOM elements to measure sequence text width
     * and height.
     */
    _measureSequenceCharacterSize: function( containerElement ) {
        var widthTest = dojo.create('div', {
                                        innerHTML: 'A'
                                            +'C'
                                            +'T'
                                            +'G'
                                            +'N',
                                        style: {
                                            visibility: 'hidden',
                                            position: 'absolute',
                                            left: '0px'
                                        }
                                    }, containerElement );
        var result = {
            w:  widthTest.clientWidth / 5,
            h: widthTest.clientHeight
        };
        containerElement.removeChild(widthTest);
        return result;
    },

    /**
     * Make a default feature detail page for the given feature.
     * @returns {HTMLElement} feature detail page HTML
     */
    defaultFeatureDetail: function( /** JBrowse.Track */ track, /** Object */ f, /** HTMLElement */ div ) {
        var container = this.inherited( arguments );

        var fmt = dojo.hitch( this, '_fmtDetailField' );

        // if( f.get('strand') == -1 ) {
        //     dojo.create('div', { className: 'message', innerHTML: '' })
        // }
        var alignment = '
'+f.get('seq')+'
';
        if( f.get('seq') && f.get('qual') ) {
            container.innerHTML += fmt('Sequence quality scores', this._renderQual( f ) );
        }

        return container;
    },

    _renderQual: function( feature ) {

        var seq  = feature.get('seq'),
            qual = feature.get('qual');
        if( !seq || !qual )
            return '';

        qual = qual.split(/\s+/);
        var fieldWidth = (''+Math.max.apply( Math, qual )).length;

        // pad the sequence with spaces
        var seqPadding = ' ';
        while( seqPadding.length < fieldWidth-1 ) {
            seqPadding += ' ';
        }
        var paddedSeq = array.map( seq, function(s) {
            return s + seqPadding;
        });

        var tableRowHTML = function(fields, class_) {
            class_ = class_ ? ' class="'+class_+'"' : '';
            return '
'+array.map( fields, function(f) { return ''+f+'	'; }).join('')+'
';
        };
        // insert newlines
        var rendered = '';
        var lineFields = Math.round(55/fieldWidth);
        while( paddedSeq.length ) {
            var line = paddedSeq.slice(0,Math.min( paddedSeq.length, lineFields ) );
            paddedSeq = paddedSeq.slice(lineFields);
            rendered += tableRowHTML( line, 'seq' );
            line = qual.slice(0, Math.min( qual.length, lineFields ));
            qual = qual.slice(lineFields);
            rendered += tableRowHTML( line, 'qual' );
        }
        return '
'+rendered+'
';
    }
});
});<|endoftext|>


<commit_before><commit_msg>test for random blocks<commit_after><|endoftext|>


<commit_before>// Custom SpacialGaze scripts.

'use strict';

exports.BattleScripts = {
    randomSeasonalRegStaffTeam: function (side) {
        let team = [];
        let variant = this.random(2);

        let sets = {
            // Admins.
            '~HoeenHero': {
                species: 'Ludicolo', ability: 'Swift Swim', item: 'Leftovers', gender: 'M',
                moves: [['Hydro Pump', 'Scald'][variant], 'Ice Beam', 'Giga Drain'],
                signatureMove: 'Scripting',
                evs: {spa: 252, spe: 252, hp: 4}, nature: 'Modest',
            },
            '~Mystifi': {
                species: 'Clefairy', ability: 'Analytic', item: 'Eviolite', gender: 'F',
                moves: [['Calm Mind', 'Cosmic Power'][variant], 'Soft-Boiled', 'Stored Power'],
                signatureMove: 'Mystic Mirage',
                evs: {hp: 252, def: 252, spd: 4}, nature: 'Bold',
            },

            // Leaders:
            '&HiroZ': {
                species: 'Genesect', ability: 'Download', item: 'Choice Scarf',
                moves: ['U-turn', 'Ice Beam', 'Explosion'],
                signatureMove: 'Crystallized Ukaku',
                evs: {atk: 252, spe: 252, spa: 4}, nature: 'Hasty',
            },
            // Moderators:
            '@Almighty Bronzong': {
                species: 'Bronzong', ability: 'Levitate', item: 'Leftovers', gender: (variant === 1) ? 'M' : 'F',
                moves: ['Gyro Ball', 'Confuse Ray', 'Toxic', 'Earthquake'],
                signatureMove: 'Blast Furnace',
                evs: {hp: 252, def: 168, spd: 88}, nature: 'Sassy',
            },
            '@C733937 123': {
                species: 'Tyranitar', ability: 'Bulletproof', item:'Safety Goggles', gender: 'M',
                moves: ['Assist', 'Beat Up', 'Sucker Punch', 'Heavy Slam'],
                signatureMove: 'Lightshot Giga-Lance',
                evs: {hp: 252, atk: 252}, nature: 'Adamant',
            },
            '@BDH93': {
                species: 'Dunsparce', ability: 'Serene Grace', item: 'Kings Rock', gender: 'M',
                moves: ['Roost', 'Coil', 'Rock Slide', ['Glare', 'Body Slam'][variant]],
                signatureMove: 'Getting Trolled',
                evs: {hp: 252, atk: 252, def: 4}, nature: 'Naughty',
            },
            '@Mimiroppu': {
                species: 'Lopunny', ability: 'Limber', item: 'Lopunnite', gender: 'F',
                moves: ['Fake out', 'Return', 'High Jump Kick'],
                signatureMove: 'Charm Up',
                evs: {atk: 252, spe: 252, def: 4}, nature: 'Jolly',
            },
            '@Kraken Mare': {
                species: 'Gardevoir', ability: 'Moody', shiny: true, item: 'Gardevoirite', gender: 'F',
                moves: ['Moonblast', 'Calm Mind', 'Psychic'],
                signatureMove: 'Mega Rage',
                evs: {hp: 248, spa: 252, def: 8}, nature: 'Modest',
            },
            '@Vacuo': {
                species: 'Magnezone', ability: 'Levitate', item: 'Choice Specs',
                moves: [['Volt Switch', 'Thunderbolt'][this.random(2)], 'Hidden Power Ice', 'Aura Sphere'],
                signatureMove: 'Mechanical Dysfunction',
                evs: {spa: 252, spe: 252, hp: 4}, nature: 'Modest',
            },

            // Drivers:
            '%ducktown': {
                species: 'Golduck', ability: 'Cloud Nine', item: 'Leftovers', gender: 'M',
                moves: [ 'Scald', 'Ice Beam', 'Psychic'],
                signatureMove: 'Duck Power',
                evs: {spa: 252, spe: 252, hp: 4}, nature: 'Modest',
            },
            '%Serperiorater': {
                species: 'Serperior', ability: 'Sturdy', item: 'Leftovers', gender: 'M',
                moves: ['Psychic', 'Aura Sphere', 'Dark Pulse'],
                signatureMove: 'Saber Strike',
                evs: {spa: 252, spe: 252, spd: 4}, nature: 'Timid',
            },
            '%Vulcaron': {
                species: 'Murkrow', ability: 'Prankster', item: 'Eviolite', gender: 'M',
                moves: ['Thunder Wave', 'Mean Look', 'Confuse Ray'],
                signatureMove: 'Troll',
                evs: {hp: 252, def: 252, spd: 4}, nature: 'Impish',
            },
            // Former Bots
            '*SpaceGazer': {
                species: 'Registeel', ability: 'No Guard', item: 'Weakness Policy',
                moves: ['Zap Cannon', 'Iron Head', 'Stone Edge'],
                signatureMove: 'Spacial Blast',
                evs: {atk: 252, spd: 252, hp: 4}, nature: 'Adamant',
            },
            '*Spacial Bot': {
                species: 'Regirock', ability: 'Wonder Guard', item: 'Leftovers',
                moves: [['Stone Edge', 'Earthquake'][variant], 'Explosion', 'Iron Head'],
                signatureMove: 'Ancient Ritual',
                evs: {atk: 252, spd: 252, hp: 4}, nature: 'Adamant',
            },
            '*SG Bot': {
                species: 'Regice', ability: 'Flash Fire', item: 'Leftovers',
                moves: ['Ice Beam', 'Ancient Power','Thunderbolt'],
                signatureMove: 'Frostbite',
                evs: {spa: 252, spd: 252, hp: 4}, nature: 'Adamant',
            },
            // Voices:
            '+Admewn': {
                species: 'Mew', ability: 'Protean', item: 'Expert Belt',
                moves: [ 'Earth Power', 'Oblivion Wing', 'Shadow Ball'],
                signatureMove: 'Mewtation',
                evs: {spa: 252, spe: 252, hp: 4}, nature: 'Timid',
            },

            '+Auction': {
                species: 'Aegislash', ability: 'Water Absorb', item: 'Leftovers', gender: 'M',
                moves: ['Swords Dance', 'Sacred Sword', 'Shadow Sneak', 'Kings Shield'],
                signatureMove: 'Zeo-Bash',
                evs: {atk: 252, spd: 8, hp: 248}, nature: 'Adamant',
            },
            '+Hydrostatics': {
                species: 'Charizard', ability: 'Solar Power', item: 'Charizardite X', gender: 'M',
                moves: [ 'Outrage', 'Flare Blitz', 'Thunder Punch'],
                signatureMove: 'Nature\'s Fury',
                evs: {spa: 252, spe: 252, hp: 4}, nature: 'Jolly',
            },
            '+Saber Ran': {
                species: 'Flygon', ability: 'Levitate', item: 'Choice Band',
                moves: [ 'Outrage', 'U-turn', 'Earthquake'],
                signatureMove: 'Out Ripper',
                evs: {atk: 252, spe: 252, hp: 4}, nature: 'Adamant',
            },
            '+The Run': {
                species: 'Volcanion', ability: 'Protean', item: 'Life Orb',
                moves: ['Fire Blast', 'Steam Eruption', 'Recover'],
                signatureMove: 'Vapor Boost',
                evs: {spa: 252, spe: 252, hp: 4}, nature: 'Timid',
            },
            '+UmichBrendan': {
                species: 'Slaking', ability: 'Guts', item: 'Flame Orb', gender: 'M',
                moves: [ 'Fire Punch', 'Thunder Punch', 'Facade'],
                signatureMove: 'Vacation Time',
                evs: {atk: 252, spe: 4, hp: 252}, nature: 'Modest',
            },
            '+Xavier1942': {
                species: 'Porygon2', ability: 'Prankster', item: 'Eviolite',
                moves: ['Tri Attack', 'Recover', 'Ice Beam'],
                signatureMove: 'Xavier Hax',
                evs: {hp: 252, def: 136, spa: 24, spd: 96}, nature: 'Bold',
            },
            '+Hurricane\'d': {
                species: 'Tomohawk', ability: 'Gale Wings', item: 'Rocky Helmet', gender: 'M',
                moves: [ 'Aura Sphere', 'Taunt', 'Hurricane'],
                signatureMove: 'Rainbust Orb',
                evs: {spa: 252, spe: 252, hp: 4}, nature: 'Bold',
            },
            '+Opple': {
                species: 'Dragonite', ability: 'Multiscale', item: 'Weakness Policy', gender: 'M',
                moves: [ 'Fire Punch', 'Dragon Claw', 'Waterfall'],
                signatureMove: 'Ancient Orb',
                evs: {atk: 252, spe: 252, hp: 4}, nature: 'Adamant',
            },
            '%Desokoro': {
                species: 'Gyarados', ability: 'Guts', item: 'Leftovers', gender: 'M',
                moves: [ 'Substitute', 'Dragon Dance', 'Bounce'],
                signatureMove: 'Tsunami Crash',
                evs: {atk: 252, spe: 252, hp: 4}, nature: 'Adamant',
            },
            '+CelestialTater': {
                species: 'Armaldo', ability: 'Unburden', item: 'White Herb', gender: 'M',
                moves: ['Drain Punch', 'Stone Edge', 'Megahorn'],
                signatureMove: 'Shell Break',
                evs: {atk: 128, spe: 128, hp: 252}, nature: 'Adamant',
            },
        };
        // convert moves to ids.
        for (var k in sets) {
            sets[k].moves = sets[k].moves.map(toId);
            sets[k].baseSignatureMove = toId(sets[k].baseSignatureMove);
        }

        // Generate the team randomly.
        let pool = Object.keys(sets);
        for (let i = 0; i < 6; i++) {
            let name = this.sampleNoReplace(pool);
            let set = sets[name];
            set.level = 100;
            set.name = name;
            if (!set.ivs) {
                set.ivs = {hp:31, atk:31, def:31, spa:31, spd:31, spe:31};
            } else {
                for (let iv in {hp:31, atk:31, def:31, spa:31, spd:31, spe:31}) {
                    set.ivs[iv] = iv in set.ivs ? set.ivs[iv] : 31;
                }
            }
            // Assuming the hardcoded set evs are all legal.
            if (!set.evs) set.evs = {hp:84, atk:84, def:84, spa:84, spd:84, spe:84};
            set.moves = [this.sampleNoReplace(set.moves), this.sampleNoReplace(set.moves), this.sampleNoReplace(set.moves)].concat(set.signatureMove);
            team.push(set);
        }
        return team;
    },
};
<commit_msg>Saber Ran/ Ranfen Update as requested (by Ran) (#14)<commit_after>// Custom SpacialGaze scripts.

'use strict';

exports.BattleScripts = {
    randomSeasonalRegStaffTeam: function (side) {
        let team = [];
        let variant = this.random(2);

        let sets = {
            // Admins.
            '~HoeenHero': {
                species: 'Ludicolo', ability: 'Swift Swim', item: 'Leftovers', gender: 'M',
                moves: [['Hydro Pump', 'Scald'][variant], 'Ice Beam', 'Giga Drain'],
                signatureMove: 'Scripting',
                evs: {spa: 252, spe: 252, hp: 4}, nature: 'Modest',
            },
            '~Mystifi': {
                species: 'Clefairy', ability: 'Analytic', item: 'Eviolite', gender: 'F',
                moves: [['Calm Mind', 'Cosmic Power'][variant], 'Soft-Boiled', 'Stored Power'],
                signatureMove: 'Mystic Mirage',
                evs: {hp: 252, def: 252, spd: 4}, nature: 'Bold',
            },

            // Leaders:
            '&HiroZ': {
                species: 'Genesect', ability: 'Download', item: 'Choice Scarf',
                moves: ['U-turn', 'Ice Beam', 'Explosion'],
                signatureMove: 'Crystallized Ukaku',
                evs: {atk: 252, spe: 252, spa: 4}, nature: 'Hasty',
            },
            '&Opple': {
                species: 'Dragonite', ability: 'Multiscale', item: 'Weakness Policy', gender: 'M',
                moves: [ 'Fire Punch', 'Dragon Claw', 'Waterfall'],
                signatureMove: 'Ancient Orb',
                evs: {atk: 252, spe: 252, hp: 4}, nature: 'Adamant',
            },
            '&Kraken Mare': {
                species: 'Gardevoir', ability: 'Moody', shiny: true, item: 'Gardevoirite', gender: 'F',
                moves: ['Moonblast', 'Calm Mind', 'Psychic'],
                signatureMove: 'Mega Rage',
                evs: {hp: 248, spa: 252, def: 8}, nature: 'Modest',
            },
            // Moderators:
            '@Almighty Bronzong': {
                species: 'Bronzong', ability: 'Levitate', item: 'Leftovers', gender: (variant === 1) ? 'M' : 'F',
                moves: ['Gyro Ball', 'Confuse Ray', 'Toxic', 'Earthquake'],
                signatureMove: 'Blast Furnace',
                evs: {hp: 252, def: 168, spd: 88}, nature: 'Sassy',
            },
            '@C733937 123': {
                species: 'Tyranitar', ability: 'Bulletproof', item:'Safety Goggles', gender: 'M',
                moves: ['Assist', 'Beat Up', 'Sucker Punch', 'Heavy Slam'],
                signatureMove: 'Lightshot Giga-Lance',
                evs: {hp: 252, atk: 252}, nature: 'Adamant',
            },
            '@BDH93': {
                species: 'Dunsparce', ability: 'Serene Grace', item: 'Kings Rock', gender: 'M',
                moves: ['Roost', 'Coil', 'Rock Slide', ['Glare', 'Body Slam'][variant]],
                signatureMove: 'Getting Trolled',
                evs: {hp: 252, atk: 252, def: 4}, nature: 'Naughty',
            },
            '@Mimiroppu': {
                species: 'Lopunny', ability: 'Limber', item: 'Lopunnite', gender: 'F',
                moves: ['Fake out', 'Return', 'High Jump Kick'],
                signatureMove: 'Charm Up',
                evs: {atk: 252, spe: 252, def: 4}, nature: 'Jolly',
            },
            '@Vacuo': {
                species: 'Magnezone', ability: 'Levitate', item: 'Choice Specs',
                moves: [['Volt Switch', 'Thunderbolt'][this.random(2)], 'Hidden Power Ice', 'Aura Sphere'],
                signatureMove: 'Mechanical Dysfunction',
                evs: {spa: 252, spe: 252, hp: 4}, nature: 'Modest',
            },

            // Drivers:
            '%ducktown': {
                species: 'Golduck', ability: 'Cloud Nine', item: 'Leftovers', gender: 'M',
                moves: [ 'Scald', 'Ice Beam', 'Psychic'],
                signatureMove: 'Duck Power',
                evs: {spa: 252, spe: 252, hp: 4}, nature: 'Modest',
            },
            '%Serperiorater': {
                species: 'Serperior', ability: 'Sturdy', item: 'Leftovers', gender: 'M',
                moves: ['Psychic', 'Aura Sphere', 'Dark Pulse'],
                signatureMove: 'Saber Strike',
                evs: {spa: 252, spe: 252, spd: 4}, nature: 'Timid',
            },
            '%Vulcaron': {
                species: 'Murkrow', ability: 'Prankster', item: 'Eviolite', gender: 'M',
                moves: ['Thunder Wave', 'Mean Look', 'Confuse Ray'],
                signatureMove: 'Troll',
                evs: {hp: 252, def: 252, spd: 4}, nature: 'Impish',
            },
            // Former Bots
            '*SpaceGazer': {
                species: 'Registeel', ability: 'No Guard', item: 'Weakness Policy',
                moves: ['Zap Cannon', 'Iron Head', 'Stone Edge'],
                signatureMove: 'Spacial Blast',
                evs: {atk: 252, spd: 252, hp: 4}, nature: 'Adamant',
            },
            '*Spacial Bot': {
                species: 'Regirock', ability: 'Wonder Guard', item: 'Leftovers',
                moves: [['Stone Edge', 'Earthquake'][variant], 'Explosion', 'Iron Head'],
                signatureMove: 'Ancient Ritual',
                evs: {atk: 252, spd: 252, hp: 4}, nature: 'Adamant',
            },
            '*SG Bot': {
                species: 'Regice', ability: 'Flash Fire', item: 'Leftovers',
                moves: ['Ice Beam', 'Ancient Power','Thunderbolt'],
                signatureMove: 'Frostbite',
                evs: {spa: 252, spd: 252, hp: 4}, nature: 'Adamant',
            },
            // Voices:
            '+Admewn': {
                species: 'Mew', ability: 'Protean', item: 'Expert Belt',
                moves: [ 'Earth Power', 'Oblivion Wing', 'Shadow Ball'],
                signatureMove: 'Mewtation',
                evs: {spa: 252, spe: 252, hp: 4}, nature: 'Timid',
            },

            '+Auction': {
                species: 'Aegislash', ability: 'Water Absorb', item: 'Leftovers', gender: 'M',
                moves: ['Swords Dance', 'Sacred Sword', 'Shadow Sneak', 'Kings Shield'],
                signatureMove: 'Zeo-Bash',
                evs: {atk: 252, spd: 8, hp: 248}, nature: 'Adamant',
            },
            '+Hydrostatics': {
                species: 'Charizard', ability: 'Solar Power', item: 'Charizardite X', gender: 'M',
                moves: [ 'Outrage', 'Flare Blitz', 'Thunder Punch'],
                signatureMove: 'Nature\'s Fury',
                evs: {spa: 252, spe: 252, hp: 4}, nature: 'Jolly',
            },
            '+Ranfen': {
                species: 'Flygon', ability: 'Levitate', item: 'Choice Band',
                moves: [ 'Outrage', 'Dragon Dance', 'Earthquake'],
                signatureMove: 'Out Ripper',
                evs: {atk: 252, spe: 252, hp: 4}, nature: 'Adamant',
            },
            '+The Run': {
                species: 'Volcanion', ability: 'Protean', item: 'Life Orb',
                moves: ['Fire Blast', 'Steam Eruption', 'Recover'],
                signatureMove: 'Vapor Boost',
                evs: {spa: 252, spe: 252, hp: 4}, nature: 'Timid',
            },
            '+UmichBrendan': {
                species: 'Slaking', ability: 'Guts', item: 'Flame Orb', gender: 'M',
                moves: [ 'Fire Punch', 'Thunder Punch', 'Facade'],
                signatureMove: 'Vacation Time',
                evs: {atk: 252, spe: 4, hp: 252}, nature: 'Modest',
            },
            '+Xavier1942': {
                species: 'Porygon2', ability: 'Prankster', item: 'Eviolite',
                moves: ['Tri Attack', 'Recover', 'Ice Beam'],
                signatureMove: 'Xavier Hax',
                evs: {hp: 252, def: 136, spa: 24, spd: 96}, nature: 'Bold',
            },
            '+Hurricane\'d': {
                species: 'Tomohawk', ability: 'Gale Wings', item: 'Rocky Helmet', gender: 'M',
                moves: [ 'Aura Sphere', 'Taunt', 'Hurricane'],
                signatureMove: 'Rainbust Orb',
                evs: {spa: 252, spe: 252, hp: 4}, nature: 'Bold',
            },
            '%Desokoro': {
                species: 'Gyarados', ability: 'Guts', item: 'Leftovers', gender: 'M',
                moves: [ 'Substitute', 'Dragon Dance', 'Bounce'],
                signatureMove: 'Tsunami Crash',
                evs: {atk: 252, spe: 252, hp: 4}, nature: 'Adamant',
            },
            '+CelestialTater': {
                species: 'Armaldo', ability: 'Unburden', item: 'White Herb', gender: 'M',
                moves: ['Drain Punch', 'Stone Edge', 'Megahorn'],
                signatureMove: 'Shell Break',
                evs: {atk: 128, spe: 128, hp: 252}, nature: 'Adamant',
            },
        };
        // convert moves to ids.
        for (var k in sets) {
            sets[k].moves = sets[k].moves.map(toId);
            sets[k].baseSignatureMove = toId(sets[k].baseSignatureMove);
        }

        // Generate the team randomly.
        let pool = Object.keys(sets);
        for (let i = 0; i < 6; i++) {
            let name = this.sampleNoReplace(pool);
            let set = sets[name];
            set.level = 100;
            set.name = name;
            if (!set.ivs) {
                set.ivs = {hp:31, atk:31, def:31, spa:31, spd:31, spe:31};
            } else {
                for (let iv in {hp:31, atk:31, def:31, spa:31, spd:31, spe:31}) {
                    set.ivs[iv] = iv in set.ivs ? set.ivs[iv] : 31;
                }
            }
            // Assuming the hardcoded set evs are all legal.
            if (!set.evs) set.evs = {hp:84, atk:84, def:84, spa:84, spd:84, spe:84};
            set.moves = [this.sampleNoReplace(set.moves), this.sampleNoReplace(set.moves), this.sampleNoReplace(set.moves)].concat(set.signatureMove);
            team.push(set);
        }
        return team;
    },
};
<|endoftext|>


<commit_before>"use strict";
var db = require('../neo4j/neo-connection.js');

/* /create/argument POST data expects:
 *      parent_claim: ID
 *      type: "SUPPORTS" / "OPPOSES"
 *      premises: [ID, ID, ID] array minimum of 2?
 *
 * returns:
 *  - 6107336639
 *  - The parent claim filled out with all it's arguments
 */

var returnObj = {
    "meta": "No meta yet",
    "data": {
        "id": "33",
        "text": "text text",
        "probability": "null",
        "arguments": []
    }
}

function testPostData(postData){
    if (!postData.hasOwnProperty('parent_claim_id')) {
        console.log("1", postData.parent_claim_id);
        return false;
    }
    if (!postData.hasOwnProperty('type') || (postData.type != 'SUPPORTS' && postData.type != 'OPPOSES') ) {
        console.log("2", postData.type);
        return false;
    }
    if (!postData.hasOwnProperty('premise_ids') || postData.premise_ids.length < 2) {
        //premise_ids should be an array of claim IDs
        console.log("3", postData.premises);
        return false;
    }
    return true;
}

module.exports = function(req, res){

    console.log("TODO: escape post data", typeof req.body);

    if (!testPostData(req.body)) {
        return res.json({
            errors: 'malformed post data',
        });
    }

    var premisMatch = req.body.premise_ids;
    premisMatch.toString();

    try {
        //create an argument node with a ${req.body.type} link to the ${req.body.parent_claim_id} claim node and multiple USED_IN links from the req.body.premise_ids claims
        db.cypher({
            query: `MATCH (claim:Claim), (premis:Claim)
                    WHERE ID(claim) = ${req.body.parent_claim_id} AND ID(premis) IN [${premisMatch}]
                    WITH claim, COLLECT(premis) AS premises
                    CREATE (newArgument:ArgGroup)-[:${req.body.type}]->(claim)
                    WITH newArgument, premises, claim
                    FOREACH (premise IN premises | CREATE (premise)-[:USED_IN]->(newArgument))
                    WITH claim
                    OPTIONAL MATCH (argument:ArgGroup)-[argLink]->(claim)
                    OPTIONAL MATCH (premis:Claim)-[premisLink]->(argument)
                    WITH claim, argument, argLink,
                        CASE WHEN ID(premis) IS NULL THEN null ELSE {id: ID(premis), text: premis.text, labels: LABELS(premis), state: premis.state} END AS premises
                    WITH claim,
                        CASE WHEN ID(argument) IS NULL THEN null ELSE {id: ID(argument), type:TYPE(argLink), state: argument.state, premises: COLLECT(premises)} END AS arguments
                    WITH {id: id(claim), text: claim.text, labels: LABELS(claim), state: claim.state, arguments: COLLECT(arguments)} AS claim
                    RETURN claim
                    LIMIT 100`
        }, function (err, results) {
            if (err) throw err;

            if (!results) {
                console.log('No claims found.');
                res.json({ error: 'No claims found' });
            } else {
                if (results.length == 0){

                    res.json({
                        meta: 'Claim was not returned, probably means it wasn\'t created ',
                        data: {}
                    });
                    return;
                }

                res.json({
                    meta: 'No meta yet',
                    data: results[0]
                });
            }
        });

    }
    catch(err){
        console.log('error happened - meep moop');
        res.json({
            errors: JSON.stringify(err),
        });
    }
}<commit_msg>calls the two new procedures instead of the one cypher script<commit_after>"use strict";
var db = require('../neo4j/neo-connection.js');

/* /create/argument POST data expects:
 *      parent_claim: ID
 *      type: "SUPPORTS" / "OPPOSES"
 *      premises: [ID, ID, ID] array minimum of 2?
 *
 * returns:
 *  - 6107336639
 *  - The parent claim filled out with all it's arguments
 */

var returnObj = {
    "meta": "No meta yet",
    "data": {
        "id": "33",
        "text": "text text",
        "probability": "null",
        "arguments": []
    }
}

function testPostData(postData) {
    if (!postData.hasOwnProperty('parent_claim_id')) {
        console.log("1", postData.parent_claim_id);
        return false;
    }
    if (!postData.hasOwnProperty('type') || (postData.type != 'SUPPORTS' && postData.type != 'OPPOSES')) {
        console.log("2", postData.type);
        return false;
    }
    if (!postData.hasOwnProperty('premise_ids') || postData.premise_ids.length < 2) {
        //premise_ids should be an array of claim IDs
        console.log("3", postData.premises);
        return false;
    }
    return true;
}

module.exports = function (req, res) {

    console.log("TODO: escape post data", typeof req.body);

    if (!testPostData(req.body)) {
        return res.json({
            errors: 'malformed post data',
        });
    }

    var premisMatch = req.body.premise_ids;
    premisMatch.toString();

    try {
        //create an argument node with a ${req.body.type} link to the ${req.body.parent_claim_id} claim node and multiple USED_IN links from the req.body.premise_ids claims
        //call WL.CreateArgumentGroup([1243, 1254])
        //call WL.AttachArgumentGroup(1243, 1254, "SUPPORTS")

        var newArgGroupID = 0;

        console.log("step by step:1");

        db.cypher({
            query: `call WL.CreateArgumentGroup([${premisMatch}])`
        }, function (err, results) {
            console.log("step by step:2");
            if (err) throw err;

            if (!results) {
                console.log('No claims found.');
                res.json({
                    error: 'No claims found'
                });
            } else {
                if (results.length == 0) {

                    res.json({
                        meta: 'Claim was not returned, probably means it wasn\'t created ',
                        data: {}
                    });
                    return;
                }

                newArgGroupID = results[0].value;

                db.cypher({
                    query: `call WL.AttachArgumentGroup(${newArgGroupID}, 1302, "SUPPORTS")`
                }, function (err, results) {
                    if (err) throw err;

                    if (!results) {
                        console.log('No claims found.');
                        res.json({
                            error: 'No claims found'
                        });
                    } else {
                        if (results.length == 0) {

                            res.json({
                                meta: 'Claim was not returned, probably means it wasn\'t created ',
                                data: {}
                            });
                            return;
                        }
                        console.log(results);

                        res.json({
                            meta: 'No meta yet',
                            data: results[0]
                        });
                    }
                });

                // res.json({
                //     meta: 'No meta yet',
                //     data: results[0]
                // });
            }
        });

        console.log("step by step:3");

    } catch (err) {
        console.log('error happened - meep moop');
        res.json({
            errors: JSON.stringify(err),
        });
    }
}<|endoftext|>


<commit_before>var MessageStream = require("message-stream")
var net = require("net")
var argv = require("optimist").argv
var EventEmitter = require("events").EventEmitter

// port needed for connection
var port = argv.port || 2503
var myIp = require("my-local-ip")()
// id needed for per client identity
var host = argv.host || myIp
var id = myIp + ":" + port

// name purely for pretty-ness
var name = argv.name || "Anonymous"

function Chat(id, name) {
    // Each node needs a messages thing
    var chat = new EventEmitter()

    var history = chat.history = []

    // We should be able to send messages locally
    chat.send = function (text) {
        chat.emit("message", {
            text: text,
            name: name,
            id: id,
            time: Date.now()
        })
    }

    // Create a stream for sending and receiving messages
    // When we receieve a message from the stream we should
    // call .receive
    // When we have a message emmitted we should queue it
    // unless we emitted it ourselves to avoid an infinite loop
    // This means we should always pass along the stream to
    // receive
    chat.createStream = function () {
        var stream = MessageStream(function (message) {
            if(message.since != null) {
              console.log(message.id + ' requests messages since:', message.since)
              history.forEach(function (e) {
                if(e.time > message.since)
                  stream.queue(e)
              })
            }
            else
              chat.receive(message, stream)
        })

        chat.on("message", function (message, source) {
            if (source !== stream) {
                stream.queue(message)
            }
        })

        stream.queue({since: chat.latest(), id: id})

        return stream
    }

    // we should be able to receive messages from a network
    chat.receive = function (message, source) {
        chat.emit("message", message, source)
    }

    // print each message
    chat.on("message", function (message) {
        chat.history.push(message)
        console.log(message.name + " > " + message.text)
    })

    //get the lastest message we know.
    chat.latest = function () {
      return history.reduce(function (max, e) {
        return max.time > e.time ? max : e
      }, {time: 0}).time
    }

    return chat
}

var chat = Chat(id, name)
process.stdin.on("data", function (text) {
    chat.send(String(text))
})

if (argv.server) {
    var server = net.createServer(function (stream) {
        stream.pipe(chat.createStream()).pipe(stream)
    })

    server.listen(port)
    console.log("Started server on port", port)
} else {
    (function connect () {
        console.log('Attempt connection to:', host+':'+port)
        var client = net.connect(port, host, function () {
            client.pipe(chat.createStream()).pipe(client)
            console.log("Connected to server on port", port)
        })

        client.once('error', reconnect)
        client.once('end', reconnect)

        function reconnect () {
          setTimeout(function () {
            connect()
          }, 1000)
        }
    })()
}
<commit_msg>style consistency<commit_after>var MessageStream = require('message-stream')
var net = require('net')
var argv = require('optimist').argv
var EventEmitter = require('events').EventEmitter

// port needed for connection
var port = argv.port || 2503
var myIp = require('my-local-ip')()
// id needed for per client identity
var host = argv.host || myIp
var id = myIp + ':' + port

// name purely for pretty-ness
var name = argv.name || 'Anonymous'

function Chat(id, name) {
    // Each node needs a messages thing
    var chat = new EventEmitter()

    var history = chat.history = []

    // We should be able to send messages locally
    chat.send = function (text) {
        chat.emit('message', {
            text: text,
            name: name,
            id: id,
            time: Date.now()
        })
    }

    // Create a stream for sending and receiving messages
    // When we receieve a message from the stream we should
    // call .receive
    // When we have a message emmitted we should queue it
    // unless we emitted it ourselves to avoid an infinite loop
    // This means we should always pass along the stream to
    // receive
    chat.createStream = function () {
        var stream = MessageStream(function (message) {
            if(message.since !== null) {
                console.log(message.id + ' requests messages since:', message.since)
                history.forEach(function (e) {
                    if(e.time > message.since) {
                        stream.queue(e)
                    }
                })
            } else {
                chat.receive(message, stream)
            }
        })

        chat.on('message', function (message, source) {
            if (source !== stream) {
                stream.queue(message)
            }
        })

        stream.queue({since: chat.latest(), id: id})

        return stream
    }

    // we should be able to receive messages from a network
    chat.receive = function (message, source) {
        chat.emit('message', message, source)
    }

    // print each message
    chat.on('message', function (message) {
        chat.history.push(message)
        console.log(message.name + ' > ' + message.text)
    })

    //get the lastest message we know.
    chat.latest = function () {
        return history.reduce(function (max, e) {
            return max.time > e.time ? max : e
        }, {time: 0}).time
    }

    return chat
}

var chat = Chat(id, name)
process.stdin.on('data', function (text) {
    chat.send(String(text))
})

if (argv.server) {
    var server = net.createServer(function (stream) {
        stream.pipe(chat.createStream()).pipe(stream)
    })

    server.listen(port)
    console.log('Started server on port', port)
} else {
    (function connect () {
        console.log('Attempt connection to:', host+':'+port)
        var client = net.connect(port, host, function () {
            client.pipe(chat.createStream()).pipe(client)
            console.log('Connected to server on port', port)
        })

        client.once('error', reconnect)
        client.once('end', reconnect)

        function reconnect () {
            setTimeout(function () {
                connect()
            }, 1000)
        }
    })()
}
<|endoftext|>


<commit_before>exports.command = 'about';
const Discord = require('discord.js');

exports.about = {
	run: function(bot,suffix,msg) {
		const embed = new Discord.RichEmbed()
			.setTitle('About')
			.setDescription('Feel Free To Check Out My New Framework Right [Here](https://github.com/BaconHawk/BaconHawkJS/)')
			.setTimestamp()
			.setFooter('BaconHawkJS')
			.setColor(0xee0000)
		msg.channel.sendEmbed(embed);
	}
}<commit_msg>Added const baconhawk = "BaconHawkJS"<commit_after>exports.command = 'about';
const Discord = require('discord.js');
const baconhawk = "BaconHawkJS"
exports.about = {
	run: function(bot,suffix,msg) {
		const embed = new Discord.RichEmbed()
			.setTitle('About')
			.setDescription('Feel Free To Check Out My New Framework Right [Here](https://github.com/BaconHawk/BaconHawkJS/)')
			.setTimestamp()
			.setFooter(baconhawk)
			.setColor(0xee0000)
		msg.channel.sendEmbed(embed);
	}
}
<|endoftext|>


<commit_before>module.exports = {
  description: 'Add bower dependencies for bootstrap and bootswatch to the project',

  normalizeEntityName: function() {
    // allows us to run ember -g ember-cli-bootswatch and not blow up
    // because ember cli normally expects the format
    // ember generate <entitiyName> <blueprint>
  },

  afterInstall: function(options) {
    var addon = this;

    // Ability to add multiple bower packages introduced in ember-cli 0.1.2
    if (this.addBowerPackagesToProject) {
      return this.addBowerPackagesToProject([
        {name: 'bootstrap', target: '^3.3.4'},
        {name: 'bootswatch', target: '^3.3.4'}
      ]);
    } else { // Else need to add them individually
      return this.addBowerPackageToProject('bootstrap', '^3.3.4').then(function(){
        return addon.addBowerPackageToProject('bootswatch', '^3.3.4');
      });
    }

  } // :afterInstall

};
<commit_msg>Bump bower deps to 3.3.5<commit_after>module.exports = {
  description: 'Add bower dependencies for bootstrap and bootswatch to the project',

  normalizeEntityName: function() {
    // allows us to run ember -g ember-cli-bootswatch and not blow up
    // because ember cli normally expects the format
    // ember generate <entitiyName> <blueprint>
  },

  afterInstall: function(options) {
    var addon = this;

    // Ability to add multiple bower packages introduced in ember-cli 0.1.2
    if (addon.addBowerPackagesToProject) {
      return addon.addBowerPackagesToProject([
        {name: 'bootstrap', target: '^3.3.5'},
        {name: 'bootswatch', target: '^3.3.5'}
      ]);
    } else { // Else need to add them individually
      return addon.addBowerPackageToProject('bootstrap', '^3.3.5').then(function(){
        return addon.addBowerPackageToProject('bootswatch', '^3.3.5');
      });
    }

  } // :afterInstall

};
<|endoftext|>


<commit_before>"use strict";

var request = require('request');
var mustache = require('mustache');

module.exports = function (RED) {

  function HTTPRequest(n) {
    RED.nodes.createNode(this, n);
    var node = this;
    var nodeUrl = n.url;
    var nodeFollowRedirects = n["follow-redirects"];
    var isTemplatedUrl = (nodeUrl || "").indexOf("{{") != -1;
    var nodeMethod = n.method || "GET";
    if (n.tls) {
      var tlsNode = RED.nodes.getNode(n.tls);
    }
    this.ret = n.ret || "txt";
    if (RED.settings.httpRequestTimeout) {
      this.reqTimeout = parseInt(RED.settings.httpRequestTimeout) || 120000;
    } else {
      this.reqTimeout = 120000;
    }

    this.on("input", function (msg) {
      var preRequestTimestamp = process.hrtime();
      node.status({
        fill: "blue",
        shape: "dot",
        text: "httpin.status.requesting"
      });

      var url = nodeUrl || msg.url;
      if (msg.url && nodeUrl && (nodeUrl !== msg.url)) { // revert change below when warning is finally removed
        node.warn(RED._("common.errors.nooverride"));
      }
      if (isTemplatedUrl) {
        url = mustache.render(nodeUrl, msg);
      }
      if (!url) {
        node.error(RED._("httpin.errors.no-url"), msg);
        node.status({
          fill: "red",
          shape: "ring",
          text: (RED._("httpin.errors.no-url"))
        });
        return;
      }
      // url must start http:// or https:// so assume http:// if not set
      if (!((url.indexOf("http://") === 0) || (url.indexOf("https://") === 0))) {
        if (tlsNode) {
          url = "https://" + url;
        } else {
          url = "http://" + url;
        }
      }

      var method = nodeMethod.toUpperCase() || "GET";
      if (msg.method && n.method && (n.method !== "use")) { // warn if override option not set
        node.warn(RED._("common.errors.nooverride"));
      }
      if (msg.method && n.method && (n.method === "use")) {
        method = msg.method.toUpperCase(); // use the msg parameter
      }
      var opts = {
        method: method,
        url: url,
        timeout: node.reqTimeout,
        followRedirect: nodeFollowRedirects,
        headers: {}
      };

      if (msg.headers) {
        for (var v in msg.headers) {
          if (msg.headers.hasOwnProperty(v)) {
            var name = v.toLowerCase();
            if (name !== "content-type" && name !== "content-length") {
              // only normalise the known headers used later in this
              // function. Otherwise leave them alone.
              name = v;
            }
            opts.headers[name] = msg.headers[v];
          }
        }
      }

      if (msg.payload && (method == "POST" || method == "PUT" || method == "PATCH")) {
        if (opts.headers['content-type'] == 'application/x-www-form-urlencoded') {
          opts.form = msg.payload;
        } else if (opts.headers['content-type'] == 'multipart/form-data') {
          opts.formData = msg.payload;
        } else {
          if (typeof msg.payload === "string" || Buffer.isBuffer(msg.payload)) {
            opts.body = msg.payload;
          } else if (typeof msg.payload == "number") {
            opts.body = msg.payload + "";
          } else {
            opts.body = JSON.stringify(msg.payload);
            if (opts.headers['content-type'] == null) {
              opts.headers['content-type'] = "application/json";
            }
          }
        }
      }

      if (this.credentials && this.credentials.user) {
        opts.auth = {
          user: this.credentials.user,
          pass: this.credentials.password,
          sendImmediately: false
        }
      }

      if (tlsNode) {
        tlsNode.addTLSOptions(opts);
      }

      request(opts, function (error, response, body) {
        node.status({});
        if (error) {
          if (error.code === 'ETIMEDOUT') {
            node.error(RED._("common.notification.errors.no-response"), msg);
            setTimeout(function () {
              node.status({
                fill: "red",
                shape: "ring",
                text: "common.notification.errors.no-response"
              });
            }, 10);
          } else {
            node.error(error, msg);
            msg.payload = error.toString() + " : " + url;
            msg.statusCode = error.code;
            node.send(msg);
            node.status({
              fill: "red",
              shape: "ring",
              text: error.code
            });
          }
        } else {
          msg.payload = body;
          msg.headers = response.headers;
          msg.statusCode = response.statusCode;
          if (node.metric()) {
            // Calculate request time
            var diff = process.hrtime(preRequestTimestamp);
            var ms = diff[0] * 1e3 + diff[1] * 1e-6;
            var metricRequestDurationMillis = ms.toFixed(3);
            node.metric("duration.millis", msg, metricRequestDurationMillis);
            if (response.connection && response.connection.bytesRead) {
              node.metric("size.bytes", msg, response.connection.bytesRead);
            }
          }
          if (node.ret === "bin") {
            msg.payload = new Buffer(msg.payload, "binary");
          } else if (node.ret === "obj") {
            try {
              msg.payload = JSON.parse(msg.payload);
            } catch (e) {
              node.warn(RED._("httpin.errors.json-error"));
            }
          }
          node.send(msg);
        }
      })
    });
  }

  RED.nodes.registerType("www-request-multipart", HTTPRequest, {
    credentials: {
      user: {
        type: "text"
      },
      password: {
        type: "password"
      }
    }
  });
}
<commit_msg>removed mustache<commit_after>"use strict";

var request = require('request');

module.exports = function (RED) {

  function HTTPRequest(n) {
    RED.nodes.createNode(this, n);
    var node = this;
    var nodeUrl = n.url;
    var nodeFollowRedirects = n["follow-redirects"];
    var isTemplatedUrl = (nodeUrl || "").indexOf("{{") != -1;
    var nodeMethod = n.method || "GET";
    if (n.tls) {
      var tlsNode = RED.nodes.getNode(n.tls);
    }
    this.ret = n.ret || "txt";
    if (RED.settings.httpRequestTimeout) {
      this.reqTimeout = parseInt(RED.settings.httpRequestTimeout) || 120000;
    } else {
      this.reqTimeout = 120000;
    }

    this.on("input", function (msg) {
      var preRequestTimestamp = process.hrtime();
      node.status({
        fill: "blue",
        shape: "dot",
        text: "httpin.status.requesting"
      });

      var url = nodeUrl || msg.url;
      if (msg.url && nodeUrl && (nodeUrl !== msg.url)) { // revert change below when warning is finally removed
        node.warn(RED._("common.errors.nooverride"));
      }

      var re = new RegExp("\\{\\{\\{(" + Object.keys(msg).join("|") + ")\\}\\}\\}", "g");
      url = url.replace(re, function (a, b) {
        return msg[b];
      });

      if (!url) {
        node.error(RED._("httpin.errors.no-url"), msg);
        node.status({
          fill: "red",
          shape: "ring",
          text: (RED._("httpin.errors.no-url"))
        });
        return;
      }
      // url must start http:// or https:// so assume http:// if not set
      if (!((url.indexOf("http://") === 0) || (url.indexOf("https://") === 0))) {
        if (tlsNode) {
          url = "https://" + url;
        } else {
          url = "http://" + url;
        }
      }

      var method = nodeMethod.toUpperCase() || "GET";
      if (msg.method && n.method && (n.method !== "use")) { // warn if override option not set
        node.warn(RED._("common.errors.nooverride"));
      }
      if (msg.method && n.method && (n.method === "use")) {
        method = msg.method.toUpperCase(); // use the msg parameter
      }
      var opts = {
        method: method,
        url: url,
        timeout: node.reqTimeout,
        followRedirect: nodeFollowRedirects,
        headers: {}
      };

      if (msg.headers) {
        for (var v in msg.headers) {
          if (msg.headers.hasOwnProperty(v)) {
            var name = v.toLowerCase();
            if (name !== "content-type" && name !== "content-length") {
              // only normalise the known headers used later in this
              // function. Otherwise leave them alone.
              name = v;
            }
            opts.headers[name] = msg.headers[v];
          }
        }
      }

      if (msg.payload && (method == "POST" || method == "PUT" || method == "PATCH")) {
        if (opts.headers['content-type'] == 'application/x-www-form-urlencoded') {
          opts.form = msg.payload;
        } else if (opts.headers['content-type'] == 'multipart/form-data') {
          opts.formData = msg.payload;
        } else {
          if (typeof msg.payload === "string" || Buffer.isBuffer(msg.payload)) {
            opts.body = msg.payload;
          } else if (typeof msg.payload == "number") {
            opts.body = msg.payload + "";
          } else {
            opts.body = JSON.stringify(msg.payload);
            if (opts.headers['content-type'] == null) {
              opts.headers['content-type'] = "application/json";
            }
          }
        }
      }

      if (this.credentials && this.credentials.user) {
        opts.auth = {
          user: this.credentials.user,
          pass: this.credentials.password,
          sendImmediately: false
        }
      }

      if (tlsNode) {
        tlsNode.addTLSOptions(opts);
      }

      request(opts, function (error, response, body) {
        node.status({});
        if (error) {
          if (error.code === 'ETIMEDOUT') {
            node.error(RED._("common.notification.errors.no-response"), msg);
            setTimeout(function () {
              node.status({
                fill: "red",
                shape: "ring",
                text: "common.notification.errors.no-response"
              });
            }, 10);
          } else {
            node.error(error, msg);
            msg.payload = error.toString() + " : " + url;
            msg.statusCode = error.code;
            node.send(msg);
            node.status({
              fill: "red",
              shape: "ring",
              text: error.code
            });
          }
        } else {
          msg.payload = body;
          msg.headers = response.headers;
          msg.statusCode = response.statusCode;
          if (node.metric()) {
            // Calculate request time
            var diff = process.hrtime(preRequestTimestamp);
            var ms = diff[0] * 1e3 + diff[1] * 1e-6;
            var metricRequestDurationMillis = ms.toFixed(3);
            node.metric("duration.millis", msg, metricRequestDurationMillis);
            if (response.connection && response.connection.bytesRead) {
              node.metric("size.bytes", msg, response.connection.bytesRead);
            }
          }
          if (node.ret === "bin") {
            msg.payload = new Buffer(msg.payload, "binary");
          } else if (node.ret === "obj") {
            try {
              msg.payload = JSON.parse(msg.payload);
            } catch (e) {
              node.warn(RED._("httpin.errors.json-error"));
            }
          }
          node.send(msg);
        }
      })
    });
  }

  RED.nodes.registerType("www-request-multipart", HTTPRequest, {
    credentials: {
      user: {
        type: "text"
      },
      password: {
        type: "password"
      }
    }
  });
}
<|endoftext|>


<commit_before>
import { mount } from 'enzyme';

import SearchBox from '../../../react-src/components/Tree/SearchBox.js';

describe('Tree/SearchBox Component', ()=>{
    let props = {};
    let enzymeWrapper = {};
    beforeEach(()=>{
        props = {
            handleSearchChange: jest.fn(),
            originalSearchString: "Mobius",
            handleClearSearch: jest.fn()
        };

        enzymeWrapper = mount(<SearchBox {...props}/>)
    });

});<commit_msg>Added basic render test.<commit_after>
import { mount } from 'enzyme';

import SearchBox from '../../../react-src/components/Tree/SearchBox.js';

describe('Tree/SearchBox Component', ()=>{
    let props = {};
    let enzymeWrapper = {};
    beforeEach(()=>{
        props = {
            handleSearchChange: jest.fn(),
            originalSearchString: "Mobius",
            handleClearSearch: jest.fn()
        };

        enzymeWrapper = mount(<SearchBox {...props}/>)
    });

    test("should render the search box and clear x", ()=>{
       expect(enzymeWrapper.find('FormControl').exists()).toBe(true);
    });
});<|endoftext|>


<commit_before>(() => {
	"use strict";

	// --------------------------------
	// Model for view directive
	// --------------------------------
	let view = {};
	view.templateUrl = "home/home.view.tpl";

	// --------------------------------
	// Controller and ViewModel
	// --------------------------------
	view.controller = function HomeController($log) {
		$log.debug("HomeView has loaded.");
	};

	// --------------------------------
	// View module
	// --------------------------------
	angular.module("home.view", [
		"mixin.service"
	])
	.directive("home", function homeView(mixin$) {
		// Set defaults for view.link
		view = mixin$("view.mixin.json", [view]);
		return view;
	});
})();
<commit_msg>Edits<commit_after>(() => {
	"use strict";

	// --------------------------------
	// Model for view directive
	// --------------------------------
	let view = {};
	view.templateUrl = "home/home.view.tpl";

	// --------------------------------
	// Controller and ViewModel
	// --------------------------------
	view.controller = function HomeController($log) {
		const vm = this;
		$log.debug("HomeView has loaded.");
	};

	// --------------------------------
	// View module
	// --------------------------------
	angular.module("home.view", [
		"mixin.service"
	])
	.directive("home", function homeView(mixin$) {
		// Set defaults for view.link
		view = mixin$("view.mixin.json", [view]);
		return view;
	});
})();
<|endoftext|>


<commit_before>var NULL = null;

function NOP() {}
function NOT_IMPLEMENTED() { throw new Error("not implemented."); }

var assert = {};
assert.instanceOf = function(object, typename) {
  switch (typename) {
  case "int":
  case "long":
    if (typeof object !== "number") {
      throw new TypeError("require:"+typename+", but:"+object);
    }
    if (int(object) !== object) {
      throw new TypeError("require:int, but:float, " + object);
    }
    break;
  case "int*":
    if (object && ! object instanceof Int16Array) {
      throw new TypeError("require:int*, but:" + object);
    }
    break;
  case "long*":
    if (object && ! object instanceof Int32Array) {
      throw new TypeError("require:int*, but:" + object);
    }
    break;
  case "float":
    if (typeof object !== "number") {
      throw new TypeError("require:"+typename+", but:"+object);
    }
    break;
  case "float*":
    if (object && ! object instanceof Float32Array) {
      throw new TypeError("require:int*, but:" + object);
    }
    break;
  case "void":
    if (typeof object !== "object") {
      throw new TypeError("require:object, but:"+object);
    }
    break;
  default:
    if (object.__name !== typename) {
      throw new TypeError("require:"+typename+", but:"+object.__name);
    }
  }
  return 0;
};

function int(x) {
  return x|0;
}

function pointer(src, offset, length) {
  offset = (src.byteOffset + offset) * src.constructor.BYTES_PER_ELEMENT;
  if (length) {
    return new src.constructor(src.buffer, offset, length);
  } else {
    return new src.constructor(src.buffer, offset);
  }
}

function set_kv(dst, src) {
  var val;
  for (var k in src) {
    if (dst.hasOwnProperty(k)) {
      if (src[k] && src[k].$) {
        for (var i = 0; i < src[k].$.length; i++) {
          dst[k][i] = src[k].$[i];
        }
      } else {
        dst[k] = src[k];
      }
    } else {
      throw new Error("Object [" + dst.constructor.name + "] has no property '" + k + "'");
    }
  }
}

var uint8   = 0;
var int16   = 1;
var int32   = 2;
var uint32  = 3;
var float32 = 4;

function calloc(n, size) {
  var a, i, m;
  if (Array.isArray(n)) {
    if (n.length === 2) {
      a = new Array(n[0]);
      for (i = 0; i < n[0]; i++) {
        a[i] = calloc(n[1], size);
      }
      return a;
    }
  } else {
    if (typeof size === "number") {
      switch (size) {
      case uint8  : return new Uint8Array(n);
      case int16  : return new Int16Array(n);
      case int32  : return new Int32Array(n);
      case uint32 : return new Uint32Array(n);
      case float32: return new Float32Array(n);
      }
    } else if (typeof size === "function") {
      a = new Array(n); for (i = 0; i < n; i++) { a[i] = size(); } return a;
    } else {
      a = new Array(n); for (i = 0; i < n; i++) { a[i] = null  ; } return a;
    }
  }
  throw new Error("calloc failed.");
}

function realloc(src, newSize) {
  var ret = new src.constructor(newSize);
  ret.set(src);
  return ret;
}

function copy(dst, src, offset) {
  dst.set(src, offset||0);
}

function valset(dst, val, size) {
  for(var i=0;i<size;i++)dst[i]=val;
}
<commit_msg>fixed: array pointer<commit_after>var NULL = null;

function NOP() {}
function NOT_IMPLEMENTED() { throw new Error("not implemented."); }

var assert = {};
assert.isNotNaN = function(num) {
  if (isNaN(num)) {
    throw new Error("NaN!?");
  }
  return 0;
};
assert.instanceOf = function(object, typename) {
  switch (typename) {
  case "int":
  case "long":
    if (typeof object !== "number") {
      throw new TypeError("require:"+typename+", but:"+object);
    }
    if (int(object) !== object) {
      throw new TypeError("require:int, but:float, " + object);
    }
    break;
  case "int*":
    if (object && ! object instanceof Int16Array) {
      throw new TypeError("require:int*, but:" + object);
    }
    break;
  case "long*":
    if (object && ! object instanceof Int32Array) {
      throw new TypeError("require:int*, but:" + object);
    }
    break;
  case "float":
    if (typeof object !== "number") {
      throw new TypeError("require:"+typename+", but:"+object);
    }
    break;
  case "float*":
    if (object && ! object instanceof Float32Array) {
      throw new TypeError("require:int*, but:" + object);
    }
    break;
  case "void":
    if (typeof object !== "object") {
      throw new TypeError("require:object, but:"+object);
    }
    break;
  default:
    if (object.__name !== typename) {
      throw new TypeError("require:"+typename+", but:"+object.__name);
    }
  }
  return 0;
};

function int(x) {
  return x|0;
}

function pointer(src, offset, length) {
  if (Array.isArray(src)) {
    if (offset >= 0) {
      return src.slice(offset, offset+length);
    }
    throw new Error("Ops.. Array["+offset+"]..");
  } else {
    offset = (src.byteOffset + offset) * src.constructor.BYTES_PER_ELEMENT;
    assert.isNotNaN(offset);

    if (typeof length === "number") {
      return new src.constructor(src.buffer, offset, length);
    } else {
      return new src.constructor(src.buffer, offset);
    }
  }
}

function set_kv(dst, src) {
  var val;
  for (var k in src) {
    if (dst.hasOwnProperty(k)) {
      if (src[k] && src[k].$) {
        for (var i = 0; i < src[k].$.length; i++) {
          dst[k][i] = src[k].$[i];
        }
      } else {
        dst[k] = src[k];
      }
    } else {
      throw new Error("Object [" + dst.constructor.name + "] has no property '" + k + "'");
    }
  }
}

var uint8   = 0;
var int16   = 1;
var int32   = 2;
var uint32  = 3;
var float32 = 4;

function calloc(n, size) {
  var a, i, m;
  if (Array.isArray(n)) {
    if (n.length === 2) {
      a = new Array(n[0]);
      for (i = 0; i < n[0]; i++) {
        a[i] = calloc(n[1], size);
      }
      return a;
    }
  } else {
    if (typeof size === "number") {
      switch (size) {
      case uint8  : return new Uint8Array(n);
      case int16  : return new Int16Array(n);
      case int32  : return new Int32Array(n);
      case uint32 : return new Uint32Array(n);
      case float32: return new Float32Array(n);
      }
    } else if (typeof size === "function") {
      a = new Array(n); for (i = 0; i < n; i++) { a[i] = size(); } return a;
    } else {
      a = new Array(n); for (i = 0; i < n; i++) { a[i] = null  ; } return a;
    }
  }
  throw new Error("calloc failed.");
}

function realloc(src, newSize) {
  var ret = new src.constructor(newSize);
  ret.set(src);
  return ret;
}

function copy(dst, src, offset) {
  dst.set(src, offset||0);
}

function valset(dst, val, size) {
  for(var i=0;i<size;i++)dst[i]=val;
}
<|endoftext|>