<commit_before>'use strict';

// ---------------------------------------------------------------------------

const huobipro = require ('./huobipro.js');

// ---------------------------------------------------------------------------

module.exports = class hadax extends huobipro {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'hadax',
            'name': 'HADAX',
            'countries': 'CN',
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/38059952-4756c49e-32f1-11e8-90b9-45c1eccba9cd.jpg',
                'api': 'https://api.hadax.com',
                'www': 'https://www.hadax.com',
                'doc': 'https://github.com/huobiapi/API_Docs/wiki',
            },
            'api': {
                'public': {
                    'get': [
                        'hadax/common/symbols', // 查询系统支持的所有交易对
                        'hadax/common/currencys', // 查询系统支持的所有币种
                        'common/timestamp', // 查询系统当前时间
                    ],
                },
            },
        });
    }

    async fetchMarkets () {
        let response = await this.publicGetHadaxCommonSymbols ();
        return this.parseMarkets (response['data']);
    }
};
<commit_msg>hadax hostname #2331<commit_after>'use strict';

// ---------------------------------------------------------------------------

const huobipro = require ('./huobipro.js');

// ---------------------------------------------------------------------------

module.exports = class hadax extends huobipro {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'hadax',
            'name': 'HADAX',
            'countries': 'CN',
            'hostname': 'api.hadax.com',
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/38059952-4756c49e-32f1-11e8-90b9-45c1eccba9cd.jpg',
                'api': 'https://api.hadax.com',
                'www': 'https://www.hadax.com',
                'doc': 'https://github.com/huobiapi/API_Docs/wiki',
            },
            'api': {
                'public': {
                    'get': [
                        'hadax/common/symbols', // 查询系统支持的所有交易对
                        'hadax/common/currencys', // 查询系统支持的所有币种
                        'common/timestamp', // 查询系统当前时间
                    ],
                },
            },
        });
    }

    async fetchMarkets () {
        let response = await this.publicGetHadaxCommonSymbols ();
        return this.parseMarkets (response['data']);
    }
};
<|endoftext|>


<commit_before>define([
	"dojo/_base/declare", "dojo/request",
	"dojo/store/Memory", "dojo/store/util/QueryResults",
	"dojo/when", "dojo/_base/lang", "dojo/Stateful", "dojo/_base/Deferred"
], function(declare, request,
			Memory, QueryResults,
			when, lang, Stateful, Deferred){
	return declare([Memory, Stateful], {
		baseQuery: {},
		apiServer: window.App.dataServiceURL,
		idProperty: "family_id",
		state: null,

		onSetState: function(attr, oldVal, state){
			//console.log("ProteinFamiliesMemoryStore setState: ", state.genome_ids);
			var cur = (this.genome_ids || []).join("");
			var next = (state.genome_ids || []).join("");
			if(cur != next){
				this.set("genome_ids", state.genome_ids || []);
				this._loaded = false;
				delete this._loadingDeferred;
			}

		},
		constructor: function(options){
			this._loaded = false;
			this.genome_ids = [];
			if(options.apiServer){
				this.apiServer = options.apiServer;
			}
			this.watch('state', lang.hitch(this, 'onSetState'));
		},

		query: function(query, opts){
			query = query || {};
			if(this._loaded){
				return this.inherited(arguments);
			}
			else{
				var _self = this;
				var results;
				var qr = QueryResults(when(this.loadData(), function(){
					results = _self.query(query, opts);
					qr.total = when(results, function(results){
						return results.total || results.length
					});
					return results;
				}));

				return qr;
			}
		},

		get: function(id, opts){
			if(this._loaded){
				return this.inherited(arguments);
			}else{
				var _self = this;
				return when(this.loadData(), function(){
					return _self.get(id, options)
				})
			}
		},

		loadData: function(){
			if(this._loadingDeferred){
				return this._loadingDeferred;
			}

			var state = this.state || {};

			if(!state.genome_ids || state.genome_ids.length < 1){
				console.log("No Genome IDS, use empty data set for initial store");

				//this is done as a deferred instead of returning an empty array
				//in order to make it happen on the next tick.  Otherwise it
				//in the query() function above, the callback happens before qr exists
				var def = new Deferred();
				setTimeout(lang.hitch(this, function(){
					this.setData([]);
					this._loaded = true;
					def.resolve(true);
				}), 0);
				return def.promise;

			}

			// TODO: change family Id based on params
			var familyType = 'figfam';
			var familyId = familyType + '_id';

			var query = {
				q: "genome_id:(" + this.genome_ids.join(' OR ') + ")",
				fq: "annotation:PATRIC AND feature_type:CDS AND " + familyId + ":[* TO *]",
				rows: 0,
				facet: true,
				'json.facet': '{stat:{type:field,field:' + familyId + ',limit:-1,facet:{aa_length_min:"min(aa_length)",aa_length_max:"max(aa_length)",aa_length_mean:"avg(aa_length)",ss:"sumsq(aa_length)",sum:"sum(aa_length)"}}}'
			};
			var q = Object.keys(query).map(function(p){
				return p + "=" + query[p]
			}).join("&");

			var _self = this;

			this._loadingDeferred = when(request.post(this.apiServer + '/genome_feature/', {
				handleAs: 'json',
				headers: {
					'Accept': "application/solr+json",
					'Content-Type': "application/solrquery+x-www-form-urlencoded",
					'X-Requested-With': null,
					'Authorization': this.token ? this.token : (window.App.authorizationToken || "")
				},
				data: q
			}), function(response){
				console.log("PFS First Response");
				var familyStat = response.facets.stat.buckets;

				var familyIdList = [];
				familyStat.forEach(function(element){
					if(element.val != ""){
						familyIdList.push(element.val);
					}
				});

				// sub query - genome distribution
				query = q + '&json.facet={stat:{type:field,field:genome_id,limit:-1,facet:{families:{type:field,field:' + familyId + ',limit:-1,sort:{index:asc}}}}}';

				console.log("Do Second Request to /genome_feature/");
				return when(request.post(_self.apiServer + '/genome_feature/', {
					handleAs: 'json',
					headers: {
						'Accept': "application/solr+json",
						'Content-Type': "application/solrquery+x-www-form-urlencoded",
						'X-Requested-With': null,
						'Authorization': _self.token ? _self.token : (window.App.authorizationToken || "")
					},
					data: query
				}), function(response){
					console.log("PFS Second Response");

					return when(request.post(_self.apiServer + '/protein_family_ref/', {
						handleAs: 'json',
						headers: {
							'Accept': "application/solr+json",
							'Content-Type': "application/solrquery+x-www-form-urlencoded",
							'X-Requested-With': null,
							'Authorization': _self.token ? _self.token : (window.App.authorizationToken || "")
						},
						data: {
							q: 'family_type:' + familyType + ' AND family_id:(' + familyIdList.join(' OR ') + ')',
							rows: 1000000
						}
					}), function(res){
						console.log("PFS Third Response");
						var genomeFamilyDist = response.facets.stat.buckets;
						var familyGenomeCount = {};
						var familyGenomeIdCountMap = {};
						var familyGenomeIdSet = {};
						var genomePosMap = {};
						_self.genome_ids.forEach(function(genomeId, idx){
							genomePosMap[genomeId] = idx;
						});

						window.performance.mark('mark_start_stat1');
						console.log("Build Genome Family Dist");
						genomeFamilyDist.forEach(function(genome){
							var genomeId = genome.val;
							var genomePos = genomePosMap[genomeId];
							var familyBuckets = genome.families.buckets;

							familyBuckets.forEach(function(bucket){
								var familyId = bucket.val;
								if(familyId != ""){
									var genomeCount = bucket.count.toString(16);
									if(genomeCount.length < 2) genomeCount = '0' + genomeCount;

									if(familyId in familyGenomeIdCountMap){
										familyGenomeIdCountMap[familyId][genomePos] = genomeCount;
									}
									else{
										var genomeIdCount = new Array(_self.genome_ids.length);
										genomeIdCount[genomePos] = genomeCount;
										familyGenomeIdCountMap[familyId] = genomeIdCount;
									}

									if(familyId in familyGenomeIdSet){
										familyGenomeIdSet[familyId].push(genomeId);
									}
									else{
										var genomeIds = new Array(_self.genome_ids.length);
										genomeIds.push(genomeId);
										familyGenomeIdSet[familyId] = genomeIds;
									}
								}
							});
						});

						console.log("Complete Genome Family Dist");
						window.performance.mark('mark_end_stat1');
						window.performance.measure('measure_protein_family_stat1', 'mark_start_stat1', 'mark_end_stat1');

						window.performance.mark('mark_start_stat2');
						console.log("familyGenomeCount");
						Object.keys(familyGenomeIdCountMap).forEach(function(familyId){
							var hashSet = {};
							familyGenomeIdSet[familyId].forEach(function(value){
								hashSet[value] = true;
							});
							familyGenomeCount[familyId] = Object.keys(hashSet).length;
						});

						window.performance.mark('mark_end_stat2');
						window.performance.measure('measure_protein_family_stat2', 'mark_start_stat2', 'mark_end_stat2');

						window.performance.mark('mark_start_stat3');

						var data = {};
						var familyRefHash = {};
						res.response.docs.forEach(function(el){
							if(!(el.family_id in familyRefHash)){
								familyRefHash[el.family_id] = el.family_product;
							}
						});
						window.performance.mark('mark_end_stat3');
						window.performance.measure('measure_protein_family_stat3', 'mark_start_stat3', 'mark_end_stat3');

						console.log("FamilyStat");
						window.performance.mark('mark_start_stat4');
						familyStat.forEach(function(element){
							var familyId = element.val;
							if(familyId != ""){
								var featureCount = element.count;
								var std = 0;
								if(featureCount > 1){
									var sumSq = element.ss || 0;
									var sum = element.sum || 0;
									var realSq = sumSq - (sum * sum) / featureCount;
									std = Math.sqrt(realSq / (featureCount - 1));
								}

								data[familyId] = {
									family_id: familyId,
									feature_count: featureCount,
									genome_count: familyGenomeCount[familyId],
									aa_length_std: std,
									aa_length_max: element.aa_length_max,
									aa_length_mean: element.aa_length_mean,
									aa_length_min: element.aa_length_min,
									description: familyRefHash[familyId],
									genomes: familyGenomeIdCountMap[familyId].join("")
								};
							}
						});
						window.performance.mark('mark_end_stat4');
						window.performance.measure('measure_protein_family_stat4', 'mark_start_stat4', 'mark_end_stat4');
						// console.log(data);

						window.performance.mark('mark_start_stat5');

						//var gridData = [];
						//Object.keys(data).forEach(function(key){
						//	gridData.push(data[key]);
						//});
						var arrayKeys = Object.keys(data);
						var arrayLength = arrayKeys.length;
						var gridData = new Array(arrayLength);
						for(var i = 0; i < arrayLength; i++){
							gridData[i] = data[arrayKeys[i]];
						}
						window.performance.mark('mark_end_stat5');
						window.performance.measure('measure_protein_family_stat5', 'mark_start_stat5', 'mark_end_stat5');
						window.performance.measure('measure_total', 'mark_start_stat1', 'mark_end_stat5');

						var measures = window.performance.getEntriesByType('measure');
						for(var i = 0, len = measures.length; i < len; ++i){
							console.log(measures[i].name + ' took ' + measures[i].duration + ' ms');
						}
						console.log("Set Data: ", gridData);
						_self.setData(gridData);
						_self._loaded = true;
						return true;
					}, function(err){
						console.log("Error in ProteinFamiliesStore: ", err)
					});
				});
			});
			return this._loadingDeferred;
		}
	});
});<commit_msg>remove console log<commit_after>define([
	"dojo/_base/declare", "dojo/request",
	"dojo/store/Memory", "dojo/store/util/QueryResults",
	"dojo/when", "dojo/_base/lang", "dojo/Stateful", "dojo/_base/Deferred"
], function(declare, request,
			Memory, QueryResults,
			when, lang, Stateful, Deferred){
	return declare([Memory, Stateful], {
		baseQuery: {},
		apiServer: window.App.dataServiceURL,
		idProperty: "family_id",
		state: null,

		onSetState: function(attr, oldVal, state){
			//console.log("ProteinFamiliesMemoryStore setState: ", state.genome_ids);
			var cur = (this.genome_ids || []).join("");
			var next = (state.genome_ids || []).join("");
			if(cur != next){
				this.set("genome_ids", state.genome_ids || []);
				this._loaded = false;
				delete this._loadingDeferred;
			}

		},
		constructor: function(options){
			this._loaded = false;
			this.genome_ids = [];
			if(options.apiServer){
				this.apiServer = options.apiServer;
			}
			this.watch('state', lang.hitch(this, 'onSetState'));
		},

		query: function(query, opts){
			query = query || {};
			if(this._loaded){
				return this.inherited(arguments);
			}
			else{
				var _self = this;
				var results;
				var qr = QueryResults(when(this.loadData(), function(){
					results = _self.query(query, opts);
					qr.total = when(results, function(results){
						return results.total || results.length
					});
					return results;
				}));

				return qr;
			}
		},

		get: function(id, opts){
			if(this._loaded){
				return this.inherited(arguments);
			}else{
				var _self = this;
				return when(this.loadData(), function(){
					return _self.get(id, options)
				})
			}
		},

		loadData: function(){
			if(this._loadingDeferred){
				return this._loadingDeferred;
			}

			var state = this.state || {};

			if(!state.genome_ids || state.genome_ids.length < 1){
				console.log("No Genome IDS, use empty data set for initial store");

				//this is done as a deferred instead of returning an empty array
				//in order to make it happen on the next tick.  Otherwise it
				//in the query() function above, the callback happens before qr exists
				var def = new Deferred();
				setTimeout(lang.hitch(this, function(){
					this.setData([]);
					this._loaded = true;
					def.resolve(true);
				}), 0);
				return def.promise;

			}

			// TODO: change family Id based on params
			var familyType = 'figfam';
			var familyId = familyType + '_id';

			var query = {
				q: "genome_id:(" + this.genome_ids.join(' OR ') + ")",
				fq: "annotation:PATRIC AND feature_type:CDS AND " + familyId + ":[* TO *]",
				rows: 0,
				facet: true,
				'json.facet': '{stat:{type:field,field:' + familyId + ',limit:-1,facet:{aa_length_min:"min(aa_length)",aa_length_max:"max(aa_length)",aa_length_mean:"avg(aa_length)",ss:"sumsq(aa_length)",sum:"sum(aa_length)"}}}'
			};
			var q = Object.keys(query).map(function(p){
				return p + "=" + query[p]
			}).join("&");

			var _self = this;

			this._loadingDeferred = when(request.post(this.apiServer + '/genome_feature/', {
				handleAs: 'json',
				headers: {
					'Accept': "application/solr+json",
					'Content-Type': "application/solrquery+x-www-form-urlencoded",
					'X-Requested-With': null,
					'Authorization': this.token ? this.token : (window.App.authorizationToken || "")
				},
				data: q
			}), function(response){
				var familyStat = response.facets.stat.buckets;

				var familyIdList = [];
				familyStat.forEach(function(element){
					if(element.val != ""){
						familyIdList.push(element.val);
					}
				});

				// sub query - genome distribution
				query = q + '&json.facet={stat:{type:field,field:genome_id,limit:-1,facet:{families:{type:field,field:' + familyId + ',limit:-1,sort:{index:asc}}}}}';

				console.log("Do Second Request to /genome_feature/");
				return when(request.post(_self.apiServer + '/genome_feature/', {
					handleAs: 'json',
					headers: {
						'Accept': "application/solr+json",
						'Content-Type': "application/solrquery+x-www-form-urlencoded",
						'X-Requested-With': null,
						'Authorization': _self.token ? _self.token : (window.App.authorizationToken || "")
					},
					data: query
				}), function(response){

					return when(request.post(_self.apiServer + '/protein_family_ref/', {
						handleAs: 'json',
						headers: {
							'Accept': "application/solr+json",
							'Content-Type': "application/solrquery+x-www-form-urlencoded",
							'X-Requested-With': null,
							'Authorization': _self.token ? _self.token : (window.App.authorizationToken || "")
						},
						data: {
							q: 'family_type:' + familyType + ' AND family_id:(' + familyIdList.join(' OR ') + ')',
							rows: 1000000
						}
					}), function(res){
						var genomeFamilyDist = response.facets.stat.buckets;
						var familyGenomeCount = {};
						var familyGenomeIdCountMap = {};
						var familyGenomeIdSet = {};
						var genomePosMap = {};
						_self.genome_ids.forEach(function(genomeId, idx){
							genomePosMap[genomeId] = idx;
						});

						window.performance.mark('mark_start_stat1');
						genomeFamilyDist.forEach(function(genome){
							var genomeId = genome.val;
							var genomePos = genomePosMap[genomeId];
							var familyBuckets = genome.families.buckets;

							familyBuckets.forEach(function(bucket){
								var familyId = bucket.val;
								if(familyId != ""){
									var genomeCount = bucket.count.toString(16);
									if(genomeCount.length < 2) genomeCount = '0' + genomeCount;

									if(familyId in familyGenomeIdCountMap){
										familyGenomeIdCountMap[familyId][genomePos] = genomeCount;
									}
									else{
										var genomeIdCount = new Array(_self.genome_ids.length);
										genomeIdCount[genomePos] = genomeCount;
										familyGenomeIdCountMap[familyId] = genomeIdCount;
									}

									if(familyId in familyGenomeIdSet){
										familyGenomeIdSet[familyId].push(genomeId);
									}
									else{
										var genomeIds = new Array(_self.genome_ids.length);
										genomeIds.push(genomeId);
										familyGenomeIdSet[familyId] = genomeIds;
									}
								}
							});
						});

						window.performance.mark('mark_end_stat1');
						window.performance.measure('measure_protein_family_stat1', 'mark_start_stat1', 'mark_end_stat1');

						window.performance.mark('mark_start_stat2');
						Object.keys(familyGenomeIdCountMap).forEach(function(familyId){
							var hashSet = {};
							familyGenomeIdSet[familyId].forEach(function(value){
								hashSet[value] = true;
							});
							familyGenomeCount[familyId] = Object.keys(hashSet).length;
						});

						window.performance.mark('mark_end_stat2');
						window.performance.measure('measure_protein_family_stat2', 'mark_start_stat2', 'mark_end_stat2');

						window.performance.mark('mark_start_stat3');

						var data = {};
						var familyRefHash = {};
						res.response.docs.forEach(function(el){
							if(!(el.family_id in familyRefHash)){
								familyRefHash[el.family_id] = el.family_product;
							}
						});
						window.performance.mark('mark_end_stat3');
						window.performance.measure('measure_protein_family_stat3', 'mark_start_stat3', 'mark_end_stat3');

						window.performance.mark('mark_start_stat4');
						familyStat.forEach(function(element){
							var familyId = element.val;
							if(familyId != ""){
								var featureCount = element.count;
								var std = 0;
								if(featureCount > 1){
									var sumSq = element.ss || 0;
									var sum = element.sum || 0;
									var realSq = sumSq - (sum * sum) / featureCount;
									std = Math.sqrt(realSq / (featureCount - 1));
								}

								data[familyId] = {
									family_id: familyId,
									feature_count: featureCount,
									genome_count: familyGenomeCount[familyId],
									aa_length_std: std,
									aa_length_max: element.aa_length_max,
									aa_length_mean: element.aa_length_mean,
									aa_length_min: element.aa_length_min,
									description: familyRefHash[familyId],
									genomes: familyGenomeIdCountMap[familyId].join("")
								};
							}
						});
						window.performance.mark('mark_end_stat4');
						window.performance.measure('measure_protein_family_stat4', 'mark_start_stat4', 'mark_end_stat4');
						// console.log(data);

						window.performance.mark('mark_start_stat5');

						//var gridData = [];
						//Object.keys(data).forEach(function(key){
						//	gridData.push(data[key]);
						//});
						var arrayKeys = Object.keys(data);
						var arrayLength = arrayKeys.length;
						var gridData = new Array(arrayLength);
						for(var i = 0; i < arrayLength; i++){
							gridData[i] = data[arrayKeys[i]];
						}
						window.performance.mark('mark_end_stat5');
						window.performance.measure('measure_protein_family_stat5', 'mark_start_stat5', 'mark_end_stat5');
						window.performance.measure('measure_total', 'mark_start_stat1', 'mark_end_stat5');

						var measures = window.performance.getEntriesByType('measure');
						for(var i = 0, len = measures.length; i < len; ++i){
							console.log(measures[i].name + ' took ' + measures[i].duration + ' ms');
						}
						console.log("Set Data: ", gridData);
						_self.setData(gridData);
						_self._loaded = true;
						return true;
					}, function(err){
						console.log("Error in ProteinFamiliesStore: ", err)
					});
				});
			});
			return this._loadingDeferred;
		}
	});
});<|endoftext|>


<commit_before>'use strict';
const _ = require('lodash');
const async = require('async');
const validator = require('validator');
const request = require('request');
const Driver = require('../models/Driver.js');
const User = require('../models/User.js');
const EventEmitter = require('events');
const version = "0.0.0";

class ApiEvenEmmitter extends EventEmitter {}
const apiEmmiter = new ApiEvenEmmitter();

apiEmmiter.on('event', () => {
	console.log('an event occurred!');
});
apiEmmiter.on('test', (param) => {
	console.log('We saw the event!', param);
});
apiEmmiter.on('car_full', (driver) => {
	console.log("car full: ", driver.profile.name);
	exports.send_car(driver);
});
apiEmmiter.on('car_loiter_timeout', (driver) => {
	console.log("car timeout: ", driver.profile.name);
	exports.send_car(driver);
});
apiEmmiter.on('car_add', (driver) => {
	driver.minutestotimout += 1;
	driver.save();
});

exports.get_route_riders = (req, res) => {
	var drvr = Driver.findOne({
		email: req.query.email
	}).exec();

	drvr.then(function(drvr) {
		if (drvr === null || drvr === undefined) {
			return res.send("no such driver found");
		}
		return res.send(drvr.riders);
	}).catch(function(err) {
		return res.send(err.message);
	});
}
exports.emit_arbitrary_event = (req, res) => {
	console.log("Emitting arbitrary event...", req.body.event, req.body.param);
	return res.send(apiEmmiter.emit(req.body.event, req.body.param));
}
exports.get_drivers = (req, res) => {
	var dprom = Driver.find().exec();
	dprom.then(function(drvrs) {
			res.send(JSON.stringify(drvrs));
		})
		.catch(function(err) {
			res.send(err.message);
		});
}
exports.assign_rider_to_arbitrary_car = (req, res) => {
	var drvr = Driver.findOne({
		email: req.query.d_email
	}).exec();

	drvr.then(function(drv) {
		if (drv === null || drv === undefined) {
			return res.send("no such driver found");
		}
		if (drvr.currentseats <= 0) {
			return res.send("Cannot add , car is full");
		}
		var usr = User.findOne({
			email: req.query.u_email
		}).exec();
		usr.then(function(usr) {
			if (usr === null || usr === undefined) {
				return res.send("no such user found");
			}
			drv.riders.push(usr);
			drv.currentseats--;
			usr.scheduled = true;
			drv.save();
			// console.log("Added");
			return res.send(JSON.stringify(drv));
		}).catch(function(err) {
			return res.send(err.message);
		});
	}).catch(function(err) {
		return res.send(err.message);
	});
}

exports.version = (req, res) => {
	apiEmmiter.emit('test', "hello");
	res.send(version);
};
exports.drop_off_car_by_email = (req, res) => {
	var drvr = Driver.findOne({
		email: req.query.email
	}).exec();

	drvr.then(function(drvr) {
			if (drvr === null || drvr === undefined) {
				return res.send("No such driver found");
			}
			drvr.ridesgiven += 1;
			drvr.riders = [];
			drvr.currentseats = drvr.profile.numberseats;
			drvr.availible = true;
			drvr.enroute = false;
			drvr.save();
			return res.send(JSON.stringify(drvr));
		})
		.catch(function(err) {
			return res.send(err.message);
		});
}
exports.send_car_by_email = (req, res) => {
	var drvr = Driver.findOne({
		email: req.query.email
	}).exec();

	drvr.then(function(drvr) {
			if (drvr === null || drvr === undefined) {
				return res.send("No such driver found");
			}
			return res.send(exports.send_car(drvr));
		})
		.catch(function(err) {
			return res.send(err.message);
		});
}
exports.send_car = (driver) => {
	console.log('Sending car: ', driver.profile.name);
	driver.enroute = true;
	driver.save();
	return JSON.stringify(driver);
};
//promises are horrible
exports.schedule_ride = (req, res) => {
	var pn = req.query.phonenum
	if (pn === undefined || pn === null) {
		return req.send("invalid phonenumber");
	}
	var usr = User.findOne({
		"phonenum": pn
	}).exec();

	usr.then(function(usr) {
			if (usr === null || usr === undefined) {
				return res.send("no such user found");
			}
			if (!((usr.scheduled === null) || (usr.scheduled === undefined))) {
				if (usr.scheduled) {
					return res.send("user already scheduled for a ride");
				}
			}

			console.log(usr.location);
			var long = usr.location.coordinates[0];
			var lat = usr.location.coordinates[1];

			var query = {};

			query.availible = true;
			query.location = {
				$near: {
					$geometry: {
						type: "Point",
						coordinates: [long, lat]
					},
					$maxDistance: 1000
				}
			}

			var drvr = Driver.findOne(query).exec();

			drvr.then(function(drvr) {
				if (drvr === undefined || drvr == null) {
					console.log("no driver found");
					return res.send("no driver could be located");
				}
				if (drvr.riders === null || drvr.riders === undefined) {
					drvr.riders.push(usr);
					usr.scheduled = true;
					drvr.save(function(err) {
						if (err) return res.send(err.message);
						console.log("saved!");
					});
					usr.save(function(err) {
						if (err) return res.send(err.message);
						console.log("saved!");
					});
					console.log(drvr.riders);
					apiEmmiter.emit('car_add', drvr);
					return res.send("success");
				}
				if (drvr.riders.length < drvr.profile.numberseats) {
					drvr.riders.push(usr);
					usr.scheduled = true;
					if (drvr.riders.length == drvr.profile.numberseats) {
						drvr.availible = false;
						apiEmmiter.emit('car_full', drvr);

					}
					drvr.save(function(err) {
						if (err) return res.send(err.message);
						console.log("saved!");
					});
					usr.save(function(err) {
						if (err) return res.send(err.message);
						console.log("saved!");
					});

					console.log(drvr.riders);
					return res.send(JSON.stringify(drvr));
				} else {
					console.log("invalid match formed, retry request");
					console.log(drvr.riders, drvr.riders.length, drvr.profile.numberseats);
					return res.send("failed to add user to ride, try again");
					drvr.availible = false;

				}
			}).catch(function(err) {
				console.log(err.message);
			});
		})
		.catch(function(err) {
			console.log(err.message);
		});
}

exports.find_closest_driver = (req, res) => {
	console.log(req.query);
	if ((req.query.lat === undefined) || (req.query.long === undefined)) {
		return res.send('lat long undefined!');
	}
	var distance;
	if (req.query.distance === undefined) {
		distance = 1000;
	} else {
		distance = req.query.distance;
	}
	var query = {};

	query.location = {
		$near: {
			$geometry: {
				type: "Point",
				coordinates: [req.query.long, req.query.lat]
			},
			$maxDistance: distance
		}
	}
	var drivers = Driver.find(query, function(err, drv) {
		if (err) {
			console.log(err.message);
		}
		return res.send(JSON.stringify(drv));

	});
}
exports.find_closest_user = (req, res) => {
	console.log(req.query);
	if ((req.query.lat === undefined) || (req.query.long === undefined)) {
		return res.send('lat long undefined!');
	}
	var distance;
	if (req.query.distance === undefined) {
		distance = 1000;
	} else {
		distance = req.query.distance;
	}
	var query = {};

	query.location = {
		$near: {
			$geometry: {
				type: "Point",
				coordinates: [req.query.long, req.query.lat]
			},
			$maxDistance: distance
		}
	}
	var users = User.find(query, function(err, drv) {
		if (err) {
			console.log(err.message);
		}
		return res.send(JSON.stringify(drv));

	});
}

//route handlers for rides<commit_msg>add local functions<commit_after>'use strict';
const _ = require('lodash');
const async = require('async');
const validator = require('validator');
const request = require('request');
const Driver = require('../models/Driver.js');
const User = require('../models/User.js');
const EventEmitter = require('events');
const version = "0.0.0";

class ApiEvenEmmitter extends EventEmitter {}
const apiEmmiter = new ApiEvenEmmitter();

apiEmmiter.on('event', () => {
	console.log('an event occurred!');
});
apiEmmiter.on('test', (param) => {
	console.log('We saw the event!', param);
});
apiEmmiter.on('car_full', (driver) => {
	console.log("car full: ", driver.profile.name);
	exports.send_car(driver);
});
apiEmmiter.on('car_loiter_timeout', (driver) => {
	console.log("car timeout: ", driver.profile.name);
	exports.send_car(driver);
});
apiEmmiter.on('car_add', (driver) => {
	driver.minutestotimout += 1;
	driver.save();
});

exports.get_route_riders = (req, res) => {
	var drvr = Driver.findOne({
		email: req.query.email
	}).exec();

	drvr.then(function(drvr) {
		if (drvr === null || drvr === undefined) {
			return res.send("no such driver found");
		}
		return res.send(drvr.riders);
	}).catch(function(err) {
		return res.send(err.message);
	});
}
exports.emit_arbitrary_event = (req, res) => {
	console.log("Emitting arbitrary event...", req.body.event, req.body.param);
	return res.send(apiEmmiter.emit(req.body.event, req.body.param));
}

exports._get_drivers = () =>{
	var dprom = Driver.find().exec();
	dprom.then(function(drvrs) {
			return(drvrs);
		})
		.catch(function(err) {
			return(err);
		});
}

exports.get_drivers = (req, res) => {
	var dprom = Driver.find().exec();
	dprom.then(function(drvrs) {
			res.send(JSON.stringify(drvrs));
		})
		.catch(function(err) {
			res.send(err.message);
		});
}
exports.assign_rider_to_arbitrary_car = (req, res) => {
	var drvr = Driver.findOne({
		email: req.query.d_email
	}).exec();

	drvr.then(function(drv) {
		if (drv === null || drv === undefined) {
			return res.send("no such driver found");
		}
		if (drvr.currentseats <= 0) {
			return res.send("Cannot add , car is full");
		}
		var usr = User.findOne({
			email: req.query.u_email
		}).exec();
		usr.then(function(usr) {
			if (usr === null || usr === undefined) {
				return res.send("no such user found");
			}
			drv.riders.push(usr);
			drv.currentseats--;
			usr.scheduled = true;
			drv.save();
			// console.log("Added");
			return res.send(JSON.stringify(drv));
		}).catch(function(err) {
			return res.send(err.message);
		});
	}).catch(function(err) {
		return res.send(err.message);
	});
}

exports.version = (req, res) => {
	apiEmmiter.emit('test', "hello");
	res.send(version);
};
exports.drop_off_car_by_email = (req, res) => {
	var drvr = Driver.findOne({
		email: req.query.email
	}).exec();

	drvr.then(function(drvr) {
			if (drvr === null || drvr === undefined) {
				return res.send("No such driver found");
			}
			drvr.ridesgiven += 1;
			drvr.riders = [];
			drvr.currentseats = drvr.profile.numberseats;
			drvr.availible = true;
			drvr.enroute = false;
			drvr.save();
			return res.send(JSON.stringify(drvr));
		})
		.catch(function(err) {
			return res.send(err.message);
		});
}
exports.send_car_by_email = (req, res) => {
	var drvr = Driver.findOne({
		email: req.query.email
	}).exec();

	drvr.then(function(drvr) {
			if (drvr === null || drvr === undefined) {
				return res.send("No such driver found");
			}
			return res.send(exports.send_car(drvr));
		})
		.catch(function(err) {
			return res.send(err.message);
		});
}
exports.send_car = (driver) => {
	console.log('Sending car: ', driver.profile.name);
	driver.enroute = true;
	driver.save();
	return JSON.stringify(driver);
};
//promises are horrible
exports.schedule_ride = (req, res) => {
	var pn = req.query.phonenum
	if (pn === undefined || pn === null) {
		return req.send("invalid phonenumber");
	}
	var usr = User.findOne({
		"phonenum": pn
	}).exec();

	usr.then(function(usr) {
			if (usr === null || usr === undefined) {
				return res.send("no such user found");
			}
			if (!((usr.scheduled === null) || (usr.scheduled === undefined))) {
				if (usr.scheduled) {
					return res.send("user already scheduled for a ride");
				}
			}

			console.log(usr.location);
			var long = usr.location.coordinates[0];
			var lat = usr.location.coordinates[1];

			var query = {};

			query.availible = true;
			query.location = {
				$near: {
					$geometry: {
						type: "Point",
						coordinates: [long, lat]
					},
					$maxDistance: 1000
				}
			}

			var drvr = Driver.findOne(query).exec();

			drvr.then(function(drvr) {
				if (drvr === undefined || drvr == null) {
					console.log("no driver found");
					return res.send("no driver could be located");
				}
				if (drvr.riders === null || drvr.riders === undefined) {
					drvr.riders.push(usr);
					usr.scheduled = true;
					drvr.save(function(err) {
						if (err) return res.send(err.message);
						console.log("saved!");
					});
					usr.save(function(err) {
						if (err) return res.send(err.message);
						console.log("saved!");
					});
					console.log(drvr.riders);
					apiEmmiter.emit('car_add', drvr);
					return res.send("success");
				}
				if (drvr.riders.length < drvr.profile.numberseats) {
					drvr.riders.push(usr);
					usr.scheduled = true;
					if (drvr.riders.length == drvr.profile.numberseats) {
						drvr.availible = false;
						apiEmmiter.emit('car_full', drvr);

					}
					drvr.save(function(err) {
						if (err) return res.send(err.message);
						console.log("saved!");
					});
					usr.save(function(err) {
						if (err) return res.send(err.message);
						console.log("saved!");
					});

					console.log(drvr.riders);
					return res.send(JSON.stringify(drvr));
				} else {
					console.log("invalid match formed, retry request");
					console.log(drvr.riders, drvr.riders.length, drvr.profile.numberseats);
					return res.send("failed to add user to ride, try again");
					drvr.availible = false;

				}
			}).catch(function(err) {
				console.log(err.message);
			});
		})
		.catch(function(err) {
			console.log(err.message);
		});
}

exports.find_closest_driver = (req, res) => {
	console.log(req.query);
	if ((req.query.lat === undefined) || (req.query.long === undefined)) {
		return res.send('lat long undefined!');
	}
	var distance;
	if (req.query.distance === undefined) {
		distance = 1000;
	} else {
		distance = req.query.distance;
	}
	var query = {};

	query.location = {
		$near: {
			$geometry: {
				type: "Point",
				coordinates: [req.query.long, req.query.lat]
			},
			$maxDistance: distance
		}
	}
	var drivers = Driver.find(query, function(err, drv) {
		if (err) {
			console.log(err.message);
		}
		return res.send(JSON.stringify(drv));

	});
}
exports.find_closest_user = (req, res) => {
	console.log(req.query);
	if ((req.query.lat === undefined) || (req.query.long === undefined)) {
		return res.send('lat long undefined!');
	}
	var distance;
	if (req.query.distance === undefined) {
		distance = 1000;
	} else {
		distance = req.query.distance;
	}
	var query = {};

	query.location = {
		$near: {
			$geometry: {
				type: "Point",
				coordinates: [req.query.long, req.query.lat]
			},
			$maxDistance: distance
		}
	}
	var users = User.find(query, function(err, drv) {
		if (err) {
			console.log(err.message);
		}
		return res.send(JSON.stringify(drv));

	});
}

//route handlers for rides<|endoftext|>


<commit_before>'use strict';

// Setting up route
angular.module('core').config(['$stateProvider', '$urlRouterProvider',
	function($stateProvider, $urlRouterProvider, Authorization) {
		// Redirect to home view when route not found
		$urlRouterProvider.otherwise('/#!/forms');
	}
]);
<commit_msg>fixed url redirection<commit_after>'use strict';

// Setting up route
angular.module('core').config(['$stateProvider', '$urlRouterProvider',
	function($stateProvider, $urlRouterProvider, Authorization) {
		// Redirect to home view when route not found
		$urlRouterProvider.otherwise('/forms');
	}
]);
<|endoftext|>


<commit_before>var fs = require('fs'),
    levelup = require('levelup'),
    leveldown = require('leveldown'),
    queue = require('queue-async'),
    key = require('./lib/key.js'),
    rimraf = require('rimraf');

function fixed(callback) {

    var dbs = fs.readdirSync('./ldb/').filter(function(item) {
       return item.indexOf('.ldb') > -1;
    });

    if (!fs.existsSync('./fixed')) {
        fs.mkdirSync('./fixed');
    }

    var q = queue();

    dbs.forEach(function(ldb, idx) {
        q.defer(function(qcallback) {
            levelup('./ldb/' + ldb, {
                createIfMissing: false,
                max_open_files: 500
            }, function(err, db) {
                if (err) return console.log(err);
                var file = fs.createWriteStream('./fixed/' + ldb.split('.ldb')[0]);
                file.once('open', function() {
                    db.createReadStream({lt: '0001'})
                        .on('data', function(data) {
                            file.write(key.decompose(data.key).hash + '\n');
                        })
                        .on('end', function(data) {
                            file.end();
                            db.close(function(err){
                                qcallback(err);
                            });
                        });
                });
            });
        });
    });

    q.awaitAll(function(err, results){
        if (callback) callback(err);
    });
}

module.exports = fixed;

if (require.main === module) { fixed(); }
<commit_msg>nonworking attempt to avoid illegal filesystem operation -- need to determine what's causing illegal paths to be passed at all, though<commit_after>var fs = require('fs'),
    levelup = require('levelup'),
    leveldown = require('leveldown'),
    queue = require('queue-async'),
    key = require('./lib/key.js'),
    rimraf = require('rimraf');

function fixed(callback) {

    var dbs = fs.readdirSync('./ldb/').filter(function(item) {
       return item.indexOf('.ldb') > -1;
    });

    if (!fs.existsSync('./fixed')) {
        fs.mkdirSync('./fixed');
    }

    var q = queue();

    dbs.forEach(function(ldb, idx) {
        q.defer(function(qcallback) {
            levelup('./ldb/' + ldb, {
                createIfMissing: false,
                max_open_files: 500
            }, function(err, db) {
                if (err) return console.log(err);
                // test to ensure this is a file, not a directory
                // unclear why this is newly necessary, but it is
                var filePath = './fixed/' + ldb.split('.ldb')[0];
                fs.stat(filePath, function(err, stats) {
                    if (err) return qcallback(err);
                    if (stats.isFile()) {
                        var file = fs.createWriteStream(filePath);
                        file.once('open', function() {
                            db.createReadStream({lt: '0001'})
                                .on('data', function(data) {
                                    file.write(key.decompose(data.key).hash + '\n');
                                })
                                .on('end', function(data) {
                                    file.end();
                                    db.close(function(err){
                                        qcallback(err);
                                    });
                                });
                        });
                    }
                    else {
                        qcallback(null);
                    }

                });

            });
        });
    });

    q.awaitAll(function(err, results){
        if (callback) callback(err);
    });
}

module.exports = fixed;

if (require.main === module) { fixed(); }
<|endoftext|>


<commit_before>import { includes, defaults, isFunction, range, without } from "lodash";
import Scale from "../../helpers/scale";
import Axis from "../../helpers/axis";
import Domain from "../../helpers/domain";
import { Helpers } from "victory-core";

const orientationSign = {
  top: -1,
  left: -1,
  right: 1,
  bottom: 1
};

export default {
  // exposed for use by VictoryChart
  getDomain(props, axis) {
    const inherentAxis = this.getAxis(props);
    if (axis && axis !== inherentAxis) {
      return undefined;
    }
    let domain;
    if (Array.isArray(props.domain)) {
      domain = props.domain;
    } else if (props.domain && props.domain[inherentAxis]) {
      domain = props.domain[inherentAxis];
    } else if (props.tickValues) {
      domain = Domain.getDomainFromTickValues(props);
    }
    const paddedDomain = Domain.padDomain(domain, props, inherentAxis);
    return domain ? Domain.cleanDomain(paddedDomain, props, inherentAxis) : undefined;
  },

  // exposed for use by VictoryChart
  getAxis(props, flipped) {
    if (props.orientation) {
      const vertical = {top: "x", bottom: "x", left: "y", right: "y"};
      return vertical[props.orientation];
    }
    const axisType = props.dependentAxis ? "dependent" : "independent";
    const flippedAxis = { dependent: "x", independent: "y"};
    const normalAxis = { independent: "x", dependent: "y"};
    return flipped ? flippedAxis[axisType] : normalAxis[axisType];
  },

  // exposed for use by VictoryChart
  getScale(props) {
    const axis = this.getAxis(props);
    const scale = Scale.getBaseScale(props, axis);
    const domain = this.getDomain(props) || scale.domain();
    scale.range(Helpers.getRange(props, axis));
    scale.domain(domain);
    return scale;
  },

  getStyles(props, styleObject) {
    const style = props.style || {};
    const parentStyleProps = { height: "auto", width: "100%" };
    return {
      parent: defaults(parentStyleProps, style.parent, styleObject.parent),
      axis: defaults({}, style.axis, styleObject.axis),
      axisLabel: defaults({}, style.axisLabel, styleObject.axisLabel),
      grid: defaults({}, style.grid, styleObject.grid),
      ticks: defaults({}, style.ticks, styleObject.ticks),
      tickLabels: defaults({}, style.tickLabels, styleObject.tickLabels)
    };
  },

  getBaseProps(props, fallbackProps) {
    const modifiedProps = Helpers.modifyProps(props, fallbackProps);
    const calculatedValues = this.getCalculatedValues(modifiedProps, fallbackProps);
    const {
      style, padding, orientation, isVertical, scale, ticks, tickFormat,
      stringTicks, anchors
    } = calculatedValues;

    const { width, height } = modifiedProps;
    const offset = this.getOffset(modifiedProps, calculatedValues);

    const globalTransform = this.getTransform(modifiedProps, calculatedValues, offset);

    const gridOffset = this.getGridOffset(modifiedProps, calculatedValues, offset);
    const gridEdge = this.getGridEdge(modifiedProps, calculatedValues);

    const axisProps = {
      style: style.axis,
      x1: isVertical ? globalTransform.x : padding.left + globalTransform.x,
      x2: isVertical ? globalTransform.x : modifiedProps.width - padding.right + globalTransform.x,
      y1: isVertical ? padding.top + globalTransform.y : globalTransform.y,
      y2: isVertical ? modifiedProps.height - padding.bottom + globalTransform.y : globalTransform.y
    };

    const parentProps = {style: style.parent, ticks, scale, width, height};
    const axisLabelProps = this.getAxisLabelProps(modifiedProps, calculatedValues, globalTransform);

    return ticks.reduce((memo, data, index) => {
      const tick = stringTicks ? modifiedProps.tickValues[data - 1] : data;
      const tickStyle = Helpers.evaluateStyle(style.ticks, tick, index);
      const scaledTick = scale(data);
      const tickPosition = this.getTickPosition(tickStyle, orientation, isVertical);
      const tickTransform = {
        x: isVertical ? globalTransform.x : scaledTick + globalTransform.x,
        y: isVertical ? scaledTick + globalTransform.y : globalTransform.y
      };

      const gridTransform = {
        x: isVertical ? -gridOffset.x + globalTransform.x : scaledTick + globalTransform.x,
        y: isVertical ? scaledTick + globalTransform.y : gridOffset.y + globalTransform.y
      };

      const tickProps = {
        x1: tickTransform.x,
        y1: tickTransform.y,
        x2: tickTransform.x + tickPosition.x2,
        y2: tickTransform.y + tickPosition.y2,
        style: tickStyle,
        tick
      };
      const text = tickFormat(tick, index);
      const labelStyle = Helpers.evaluateStyle(style.tickLabels, tick, index);
      const tickLabelProps = {
        style: labelStyle,
        x: tickTransform.x + tickPosition.x,
        y: tickTransform.y + tickPosition.y,
        verticalAnchor: labelStyle.verticalAnchor || anchors.verticalAnchor,
        textAnchor: labelStyle.textAnchor || anchors.textAnchor,
        angle: labelStyle.angle,
        text,
        tick
      };

      const gridProps = {
        x1: gridTransform.x,
        y1: gridTransform.y,
        x2: gridEdge.x + gridTransform.x,
        y2: gridEdge.y + gridTransform.y,
        style: Helpers.evaluateStyle(style.grid, tick, index),
        tick
      };

      memo[index] = {
        axis: axisProps,
        axisLabel: axisLabelProps,
        ticks: tickProps,
        tickLabels: tickLabelProps,
        grid: gridProps
      };

      return memo;
    }, {parent: parentProps});
  },

  getCalculatedValues(props, fallbackProps) {
    const defaultStyles = props.theme && props.theme.axis ? props.theme.axis : fallbackProps.style;
    const style = this.getStyles(props, defaultStyles);
    const padding = Helpers.getPadding(props);
    const orientation = props.orientation || (props.dependentAxis ? "left" : "bottom");
    const isVertical = Axis.isVertical(props);
    const labelPadding = this.getLabelPadding(props, style);
    const stringTicks = Axis.stringTicks(props);
    const scale = this.getScale(props);
    const ticks = this.getTicks(props, scale);
    const tickFormat = this.getTickFormat(props, scale, ticks);
    const anchors = this.getAnchors(orientation, isVertical);

    return {
      style, padding, orientation, isVertical, labelPadding, stringTicks,
      anchors, scale, ticks, tickFormat
    };
  },

  getAxisLabelProps(props, calculatedValues, globalTransform) {
    const {style, orientation, padding, labelPadding, isVertical} = calculatedValues;
    const sign = orientationSign[orientation];
    const hPadding = padding.left + padding.right;
    const vPadding = padding.top + padding.bottom;
    const verticalAnchor = sign < 0 ? "end" : "start";
    const labelStyle = style.axisLabel;
    const angle = isVertical ? -90 : 0;
    const x = isVertical ? globalTransform.x + (sign * labelPadding) :
      ((props.width - hPadding) / 2) + padding.left + globalTransform.x;
    const y = isVertical ?
      ((props.height - vPadding) / 2) + padding.bottom + globalTransform.y :
      (sign * labelPadding) + globalTransform.y;
    return {
      x,
      y,
      verticalAnchor: labelStyle.verticalAnchor || verticalAnchor,
      textAnchor: labelStyle.textAnchor || "middle",
      angle: labelStyle.angle || angle,
      style: labelStyle,
      text: props.label
    };
  },

  getTicks(props, scale) {
    if (props.tickValues) {
      if (Axis.stringTicks(props)) {
        return range(1, props.tickValues.length + 1);
      }
      return props.tickValues;
    } else if (scale.ticks && isFunction(scale.ticks)) {
      const ticks = scale.ticks(props.tickCount);
      if (props.crossAxis) {
        return includes(ticks, 0) ? without(ticks, 0) : ticks;
      }
      return ticks;
    }
    return scale.domain();
  },

  getAnchors(orientation, isVertical) {
    const anchorOrientation = { top: "end", left: "end", right: "start", bottom: "start" };
    const anchor = anchorOrientation[orientation];
    return {
      textAnchor: isVertical ? anchor : "middle",
      verticalAnchor: isVertical ? "middle" : anchor
    };
  },

  getTickFormat(props, scale) {
    if (props.tickFormat && isFunction(props.tickFormat)) {
      return props.tickFormat;
    } else if (props.tickFormat && Array.isArray(props.tickFormat)) {
      return (x, index) => props.tickFormat[index];
    } else if (Axis.stringTicks(props)) {
      return (x, index) => props.tickValues[index];
    } else if (scale.tickFormat && isFunction(scale.tickFormat)) {
      return scale.tickFormat();
    } else {
      return (x) => x;
    }
  },

  getLabelPadding(props, style) {
    const labelStyle = style.axisLabel;
    if (typeof labelStyle.padding !== "undefined" && labelStyle.padding !== null) {
      return labelStyle.padding;
    }
    const isVertical = Axis.isVertical(props);
    // TODO: magic numbers
    return props.label ? (labelStyle.fontSize * (isVertical ? 2.3 : 1.6)) : 0;
  },

  getOffset(props, calculatedValues) {
    const {
      style, padding, isVertical, orientation, labelPadding, stringTicks, ticks
    } = calculatedValues;
    const xPadding = orientation === "right" ? padding.right : padding.left;
    const yPadding = orientation === "top" ? padding.top : padding.bottom;
    const fontSize = style.axisLabel.fontSize;
    const offsetX = (props.offsetX !== null) && (props.offsetX !== undefined)
      ? props.offsetX : xPadding;
    const offsetY = (props.offsetY !== null) && (props.offsetY !== undefined)
      ? props.offsetY : yPadding;
    const tickSizes = ticks.map((data) => {
      const tick = stringTicks ? props.tickValues[data - 1] : data;
      const tickStyle = Helpers.evaluateStyle(style.ticks, tick);
      return tickStyle.size;
    });
    const totalPadding = fontSize + (2 * Math.max(...tickSizes)) + labelPadding;
    const minimumPadding = 1.2 * fontSize; // TODO: magic numbers
    const x = isVertical ? totalPadding : minimumPadding;
    const y = isVertical ? minimumPadding : totalPadding;
    return {
      x: (offsetX !== null) && (offsetX !== undefined) ? offsetX : x,
      y: (offsetY !== null) && (offsetY !== undefined) ? offsetY : y
    };
  },

  getTransform(props, calculatedValues, offset) {
    const {orientation} = calculatedValues;
    return {
      top: {x: 0, y: offset.y},
      bottom: {x: 0, y: props.height - offset.y},
      left: {x: offset.x, y: 0},
      right: {x: props.width - offset.x, y: 0}
    }[orientation];
  },

  getTickPosition(style, orientation, isVertical) {
    const tickSpacing = style.size + style.padding;
    const sign = orientationSign[orientation];
    return {
      x: isVertical ? sign * tickSpacing : 0,
      x2: isVertical ? sign * style.size : 0,
      y: isVertical ? 0 : sign * tickSpacing,
      y2: isVertical ? 0 : sign * style.size
    };
  },

  getGridEdge(props, calculatedValues) {
    const {orientation, padding, isVertical} = calculatedValues;
    const sign = -orientationSign[orientation];
    const x = isVertical ?
      sign * (props.width - (padding.left + padding.right)) : 0;
    const y = isVertical ?
      0 : sign * (props.height - (padding.top + padding.bottom));
    return {x, y};
  },

  getGridOffset(props, calculatedValues, offset) {
    const {padding, orientation } = calculatedValues;
    const xPadding = orientation === "right" ? padding.right : padding.left;
    const yPadding = orientation === "top" ? padding.top : padding.bottom;
    return {
      x: props.crossAxis ? offset.x - xPadding : 0,
      y: props.crossAxis ? offset.y - yPadding : 0
    };
  }
};
<commit_msg>commit changes to review during pairing session<commit_after>import { includes, defaults, isFunction, range, without } from "lodash";
import Scale from "../../helpers/scale";
import Axis from "../../helpers/axis";
import Domain from "../../helpers/domain";
import { Helpers } from "victory-core";

const orientationSign = {
  top: -1,
  left: -1,
  right: 1,
  bottom: 1
};

export default {
  // exposed for use by VictoryChart
  getDomain(props, axis) {
    const inherentAxis = this.getAxis(props);
    if (axis && axis !== inherentAxis) {
      return undefined;
    }
    let domain;
    if (Array.isArray(props.domain)) {
      domain = props.domain;
    } else if (props.domain && props.domain[inherentAxis]) {
      domain = props.domain[inherentAxis];
    } else if (props.tickValues) {
      domain = Domain.getDomainFromTickValues(props);
    }
    const paddedDomain = Domain.padDomain(domain, props, inherentAxis);
    console.log("DOMAIN", Domain.cleanDomain(paddedDomain, props, inherentAxis), axis);
    return domain ? Domain.cleanDomain(paddedDomain, props, inherentAxis) : undefined;
  },

  // exposed for use by VictoryChart
  getAxis(props, flipped) {
    if (props.orientation) {
      const vertical = {top: "x", bottom: "x", left: "y", right: "y"};
      return vertical[props.orientation];
    }
    const axisType = props.dependentAxis ? "dependent" : "independent";
    const flippedAxis = { dependent: "x", independent: "y"};
    const normalAxis = { independent: "x", dependent: "y"};
    return flipped ? flippedAxis[axisType] : normalAxis[axisType];
  },

  // exposed for use by VictoryChart
  getScale(props) {
    const axis = this.getAxis(props);
    console.log("PROPS", props);
    const scale = Scale.getBaseScale(props, axis);
    const domain = this.getDomain(props) || scale.domain();
    scale.range(Helpers.getRange(props, axis));
    scale.domain(domain);
    return scale;
  },

  getStyles(props, styleObject) {
    const style = props.style || {};
    const parentStyleProps = { height: "auto", width: "100%" };
    return {
      parent: defaults(parentStyleProps, style.parent, styleObject.parent),
      axis: defaults({}, style.axis, styleObject.axis),
      axisLabel: defaults({}, style.axisLabel, styleObject.axisLabel),
      grid: defaults({}, style.grid, styleObject.grid),
      ticks: defaults({}, style.ticks, styleObject.ticks),
      tickLabels: defaults({}, style.tickLabels, styleObject.tickLabels)
    };
  },

  getBaseProps(props, fallbackProps) {
    const modifiedProps = Helpers.modifyProps(props, fallbackProps);
    const calculatedValues = this.getCalculatedValues(modifiedProps, fallbackProps);
    const {
      style, padding, orientation, isVertical, scale, ticks, tickFormat,
      stringTicks, anchors
    } = calculatedValues;

    const { width, height } = modifiedProps;
    const offset = this.getOffset(modifiedProps, calculatedValues);

    const globalTransform = this.getTransform(modifiedProps, calculatedValues, offset);

    const gridOffset = this.getGridOffset(modifiedProps, calculatedValues, offset);
    const gridEdge = this.getGridEdge(modifiedProps, calculatedValues);

    const axisProps = {
      style: style.axis,
      x1: isVertical ? globalTransform.x : padding.left + globalTransform.x,
      x2: isVertical ? globalTransform.x : modifiedProps.width - padding.right + globalTransform.x,
      y1: isVertical ? padding.top + globalTransform.y : globalTransform.y,
      y2: isVertical ? modifiedProps.height - padding.bottom + globalTransform.y : globalTransform.y
    };

    const parentProps = {style: style.parent, ticks, scale, width, height};
    const axisLabelProps = this.getAxisLabelProps(modifiedProps, calculatedValues, globalTransform);

    return ticks.reduce((memo, data, index) => {
      const tick = stringTicks ? modifiedProps.tickValues[data - 1] : data;
      const tickStyle = Helpers.evaluateStyle(style.ticks, tick, index);
      const scaledTick = scale(data);
      const tickPosition = this.getTickPosition(tickStyle, orientation, isVertical);
      const tickTransform = {
        x: isVertical ? globalTransform.x : scaledTick + globalTransform.x,
        y: isVertical ? scaledTick + globalTransform.y : globalTransform.y
      };

      const gridTransform = {
        x: isVertical ? -gridOffset.x + globalTransform.x : scaledTick + globalTransform.x,
        y: isVertical ? scaledTick + globalTransform.y : gridOffset.y + globalTransform.y
      };

      const tickProps = {
        x1: tickTransform.x,
        y1: tickTransform.y,
        x2: tickTransform.x + tickPosition.x2,
        y2: tickTransform.y + tickPosition.y2,
        style: tickStyle,
        tick
      };
      const text = tickFormat(tick, index);
      const labelStyle = Helpers.evaluateStyle(style.tickLabels, tick, index);
      const tickLabelProps = {
        style: labelStyle,
        x: tickTransform.x + tickPosition.x,
        y: tickTransform.y + tickPosition.y,
        verticalAnchor: labelStyle.verticalAnchor || anchors.verticalAnchor,
        textAnchor: labelStyle.textAnchor || anchors.textAnchor,
        angle: labelStyle.angle,
        text,
        tick
      };

      const gridProps = {
        x1: gridTransform.x,
        y1: gridTransform.y,
        x2: gridEdge.x + gridTransform.x,
        y2: gridEdge.y + gridTransform.y,
        style: Helpers.evaluateStyle(style.grid, tick, index),
        tick
      };

      memo[index] = {
        axis: axisProps,
        axisLabel: axisLabelProps,
        ticks: tickProps,
        tickLabels: tickLabelProps,
        grid: gridProps
      };

      return memo;
    }, {parent: parentProps});
  },

  getCalculatedValues(props, fallbackProps) {
    const defaultStyles = props.theme && props.theme.axis ? props.theme.axis : fallbackProps.style;
    const style = this.getStyles(props, defaultStyles);
    const padding = Helpers.getPadding(props);
    const orientation = props.orientation || (props.dependentAxis ? "left" : "bottom");
    const isVertical = Axis.isVertical(props);
    const labelPadding = this.getLabelPadding(props, style);
    const stringTicks = Axis.stringTicks(props);
    const scale = this.getScale(props);
    const ticks = this.getTicks(props, scale);
    const tickFormat = this.getTickFormat(props, scale, ticks);
    const anchors = this.getAnchors(orientation, isVertical);

    return {
      style, padding, orientation, isVertical, labelPadding, stringTicks,
      anchors, scale, ticks, tickFormat
    };
  },

  getAxisLabelProps(props, calculatedValues, globalTransform) {
    const {style, orientation, padding, labelPadding, isVertical} = calculatedValues;
    const sign = orientationSign[orientation];
    const hPadding = padding.left + padding.right;
    const vPadding = padding.top + padding.bottom;
    const verticalAnchor = sign < 0 ? "end" : "start";
    const labelStyle = style.axisLabel;
    const angle = isVertical ? -90 : 0;
    const x = isVertical ? globalTransform.x + (sign * labelPadding) :
      ((props.width - hPadding) / 2) + padding.left + globalTransform.x;
    const y = isVertical ?
      ((props.height - vPadding) / 2) + padding.bottom + globalTransform.y :
      (sign * labelPadding) + globalTransform.y;
    return {
      x,
      y,
      verticalAnchor: labelStyle.verticalAnchor || verticalAnchor,
      textAnchor: labelStyle.textAnchor || "middle",
      angle: labelStyle.angle || angle,
      style: labelStyle,
      text: props.label
    };
  },

  getTicks(props, scale) {
    if (props.tickValues) {
      if (Axis.stringTicks(props)) {
        return range(1, props.tickValues.length + 1);
      }
      return props.tickValues;
    } else if (scale.ticks && isFunction(scale.ticks)) {
      const ticks = scale.ticks(props.tickCount);
      if (props.crossAxis) {
        return includes(ticks, 0) ? without(ticks, 0) : ticks;
      }
      return ticks;
    }
    return scale.domain();
  },

  getAnchors(orientation, isVertical) {
    const anchorOrientation = { top: "end", left: "end", right: "start", bottom: "start" };
    const anchor = anchorOrientation[orientation];
    return {
      textAnchor: isVertical ? anchor : "middle",
      verticalAnchor: isVertical ? "middle" : anchor
    };
  },

  getTickFormat(props, scale) {
    if (props.tickFormat && isFunction(props.tickFormat)) {
      return props.tickFormat;
    } else if (props.tickFormat && Array.isArray(props.tickFormat)) {
      return (x, index) => props.tickFormat[index];
    } else if (Axis.stringTicks(props)) {
      return (x, index) => props.tickValues[index];
    } else if (scale.tickFormat && isFunction(scale.tickFormat)) {
      return scale.tickFormat();
    } else {
      return (x) => x;
    }
  },

  getLabelPadding(props, style) {
    const labelStyle = style.axisLabel;
    if (typeof labelStyle.padding !== "undefined" && labelStyle.padding !== null) {
      return labelStyle.padding;
    }
    const isVertical = Axis.isVertical(props);
    // TODO: magic numbers
    return props.label ? (labelStyle.fontSize * (isVertical ? 2.3 : 1.6)) : 0;
  },

  getOffset(props, calculatedValues) {
    const {
      style, padding, isVertical, orientation, labelPadding, stringTicks, ticks
    } = calculatedValues;
    const xPadding = orientation === "right" ? padding.right : padding.left;
    const yPadding = orientation === "top" ? padding.top : padding.bottom;
    const fontSize = style.axisLabel.fontSize;
    const offsetX = (props.offsetX !== null) && (props.offsetX !== undefined)
      ? props.offsetX : xPadding;
    const offsetY = (props.offsetY !== null) && (props.offsetY !== undefined)
      ? props.offsetY : yPadding;
    const tickSizes = ticks.map((data) => {
      const tick = stringTicks ? props.tickValues[data - 1] : data;
      const tickStyle = Helpers.evaluateStyle(style.ticks, tick);
      return tickStyle.size;
    });
    const totalPadding = fontSize + (2 * Math.max(...tickSizes)) + labelPadding;
    const minimumPadding = 1.2 * fontSize; // TODO: magic numbers
    const x = isVertical ? totalPadding : minimumPadding;
    const y = isVertical ? minimumPadding : totalPadding;
    return {
      x: (offsetX !== null) && (offsetX !== undefined) ? offsetX : x,
      y: (offsetY !== null) && (offsetY !== undefined) ? offsetY : y
    };
  },

  getTransform(props, calculatedValues, offset) {
    const {orientation} = calculatedValues;
    return {
      top: {x: 0, y: offset.y},
      bottom: {x: 0, y: props.height - offset.y},
      left: {x: offset.x, y: 0},
      right: {x: props.width - offset.x, y: 0}
    }[orientation];
  },

  getTickPosition(style, orientation, isVertical) {
    const tickSpacing = style.size + style.padding;
    const sign = orientationSign[orientation];
    return {
      x: isVertical ? sign * tickSpacing : 0,
      x2: isVertical ? sign * style.size : 0,
      y: isVertical ? 0 : sign * tickSpacing,
      y2: isVertical ? 0 : sign * style.size
    };
  },

  getGridEdge(props, calculatedValues) {
    const {orientation, padding, isVertical} = calculatedValues;
    const sign = -orientationSign[orientation];
    const x = isVertical ?
      sign * (props.width - (padding.left + padding.right)) : 0;
    const y = isVertical ?
      0 : sign * (props.height - (padding.top + padding.bottom));
    return {x, y};
  },

  getGridOffset(props, calculatedValues, offset) {
    const {padding, orientation } = calculatedValues;
    const xPadding = orientation === "right" ? padding.right : padding.left;
    const yPadding = orientation === "top" ? padding.top : padding.bottom;
    return {
      x: props.crossAxis ? offset.x - xPadding : 0,
      y: props.crossAxis ? offset.y - yPadding : 0
    };
  }
};
<|endoftext|>


<commit_before>class Adapter {

  constructor($scope, $parse, $attr, viewport, buffer, doAdjust, reload) {
    this.$parse = $parse;
    this.$attr = $attr;
    this.viewport = viewport;
    this.buffer = buffer;

    this.doAdjust = doAdjust;
    this.reload = reload;

    this.isLoading = false;
    this.disabled = false;

    const viewportScope = viewport.getScope();
    this.startScope = viewportScope.$parent ? viewportScope : $scope;

    this.publicContext = {};
    this.assignAdapter($attr.adapter);
    this.generatePublicContext();
  }

  assignAdapter(adapterAttr) {
    if (!adapterAttr || !(adapterAttr = adapterAttr.replace(/^\s+|\s+$/gm, ''))) {
      return;
    }
    let adapterOnScope;

    try {
      this.$parse(adapterAttr).assign(this.startScope, {});
      adapterOnScope = this.$parse(adapterAttr)(this.startScope);
    }
    catch (error) {
      error.message = `Angular ui-scroll Adapter assignment exception.\n` +
        `Can't parse "${adapterAttr}" expression.\n` +
        error.message;
      throw error;
    }

    angular.extend(adapterOnScope, this.publicContext);
    this.publicContext = adapterOnScope;
  }

  generatePublicContext() {
    // these methods will be accessible out of ui-scroll via user defined adapter
    const publicMethods = ['reload', 'applyUpdates', 'append', 'prepend', 'isBOF', 'isEOF', 'isEmpty'];
    for (let i = publicMethods.length - 1; i >= 0; i--) {
      this.publicContext[publicMethods[i]] = this[publicMethods[i]].bind(this);
    }

    // these read-only props will be accessible out of ui-scroll via user defined adapter
    const publicProps = ['isLoading', 'topVisible', 'topVisibleElement', 'topVisibleScope', 'bottomVisible', 'bottomVisibleElement', 'bottomVisibleScope'];
    for (let i = publicProps.length - 1; i >= 0; i--) {
      let property, attr = this.$attr[publicProps[i]];
      Object.defineProperty(this, publicProps[i], {
        get: () => property,
        set: (value) => {
          property = value;
          this.publicContext[publicProps[i]] = value;
          if (attr) {
            this.$parse(attr).assign(this.startScope, value);
          }
        }
      });
    }

    // read-only immediately calculated public properties
    const publicPropsImmediate = ['bufferFirst', 'bufferLast', 'bufferLength'];
    for (let i = publicPropsImmediate.length - 1; i >= 0; i--) {
      Object.defineProperty(this.publicContext, publicPropsImmediate[i], {
        get: () => this[publicPropsImmediate[i]]
      });
    }

    // non-read-only public property
    Object.defineProperty(this.publicContext, 'disabled', {
      get: () => this.disabled,
      set: (value) => (!(this.disabled = value)) ? this.doAdjust() : null
    });
  }

  loading(value) {
    this.isLoading = value;
  }

  isBOF() {
    return this.buffer.bof;
  }

  isEOF() {
    return this.buffer.eof;
  }

  isEmpty() {
    return !this.buffer.length;
  }

  get bufferLength() {
    return this.buffer.getItems().length;
  }

  get bufferFirst() {
    return this.buffer.getFirstItem();
  }

  get bufferLast() {
    return this.buffer.getLastItem();
  }

  append(newItems) {
    this.buffer.append(newItems);
    this.doAdjust();
    this.viewport.clipTop();
    this.viewport.clipBottom();
  }

  prepend(newItems) {
    this.buffer.prepend(newItems);
    this.doAdjust();
    this.viewport.clipTop();
    this.viewport.clipBottom();
  }

  applyUpdates(arg1, arg2) {
    if (typeof arg1 === 'function') {
      this.applyUpdatesFunc(arg1);
    } else {
      this.applyUpdatesIndex(arg1, arg2);
    }
    this.doAdjust();
  }

  applyUpdatesFunc(cb) {
    this.buffer.slice(0).forEach((wrapper) => {
      // we need to do it on the buffer clone, because buffer content
      // may change as we iterate through
      this.applyUpdate(wrapper, cb(wrapper.item, wrapper.scope, wrapper.element));
    });
  }

  applyUpdatesIndex(index, newItems) {
    if (index % 1 !== 0) {
      throw new Error('applyUpdates - ' + index + ' is not a valid index (should be an integer)');
    }
    const _index = index - this.buffer.first;

    // apply updates only within buffer
    if (_index >= 0 && _index < this.buffer.length) {
      this.applyUpdate(this.buffer[_index], newItems);
    }
    // out-of-buffer case: deletion may affect Paddings
    else if(index >= this.buffer.getAbsMinIndex() && index <= this.buffer.getAbsMaxIndex()) {
      if(angular.isArray(newItems) && !newItems.length) {
        this.viewport.removeCacheItem(index, index === this.buffer.minIndex);
        if(index === this.buffer.getAbsMinIndex()) {
          this.buffer.incrementMinIndex();
        }
        else {
          this.buffer.decrementMaxIndex();
        }
      }
    }
  }

  applyUpdate(wrapper, newItems) {
    if (!angular.isArray(newItems)) {
      return;
    }
    let position = this.buffer.indexOf(wrapper);
    if (!newItems.reverse().some(newItem => newItem === wrapper.item)) {
      wrapper.op = 'remove';
      if(position === 0 && !newItems.length) {
        wrapper._op = 'isTop'; // to catch "first" edge case on remove
      }
    }
    newItems.forEach((newItem) => {
      if (newItem === wrapper.item) {
        position--;
      } else {
        // 3 parameter (isTop) is to catch "first" edge case on insert
        this.buffer.insert(position + 1, newItem, position === -1);
      }
    });
  }

  calculateProperties() {
    let rowTop = null, topHeight = 0;
    let topDone = false, bottomDone = false;
    const length = this.buffer.length;

    for (let i = 0; i < length; i++) {
      const item = this.buffer[i];
      const itemTop = item.element.offset().top;

      if (rowTop !== itemTop) { // a new row condition
        const itemHeight = item.element.outerHeight(true);
        const top = this.viewport.topDataPos() + topHeight + itemHeight;

        if (!topDone && top > this.viewport.topVisiblePos()) {
          topDone = true;
          this['topVisible'] = item.item;
          this['topVisibleElement'] = item.element;
          this['topVisibleScope'] = item.scope;
        }
        if (!bottomDone && (top >= this.viewport.bottomVisiblePos() || (i === length - 1 && this.isEOF()))) {
          bottomDone = true;
          this['bottomVisible'] = item.item;
          this['bottomVisibleElement'] = item.element;
          this['bottomVisibleScope'] = item.scope;
        }
        topHeight += itemHeight;
      }
      rowTop = itemTop;

      if (topDone && bottomDone) {
        break;
      }
    }
  }

}

export default Adapter;
<commit_msg>immutableTop option implementation<commit_after>class Adapter {

  constructor($scope, $parse, $attr, viewport, buffer, doAdjust, reload) {
    this.$parse = $parse;
    this.$attr = $attr;
    this.viewport = viewport;
    this.buffer = buffer;

    this.doAdjust = doAdjust;
    this.reload = reload;

    this.isLoading = false;
    this.disabled = false;

    const viewportScope = viewport.getScope();
    this.startScope = viewportScope.$parent ? viewportScope : $scope;

    this.publicContext = {};
    this.assignAdapter($attr.adapter);
    this.generatePublicContext();
  }

  assignAdapter(adapterAttr) {
    if (!adapterAttr || !(adapterAttr = adapterAttr.replace(/^\s+|\s+$/gm, ''))) {
      return;
    }
    let adapterOnScope;

    try {
      this.$parse(adapterAttr).assign(this.startScope, {});
      adapterOnScope = this.$parse(adapterAttr)(this.startScope);
    }
    catch (error) {
      error.message = `Angular ui-scroll Adapter assignment exception.\n` +
        `Can't parse "${adapterAttr}" expression.\n` +
        error.message;
      throw error;
    }

    angular.extend(adapterOnScope, this.publicContext);
    this.publicContext = adapterOnScope;
  }

  generatePublicContext() {
    // these methods will be accessible out of ui-scroll via user defined adapter
    const publicMethods = ['reload', 'applyUpdates', 'append', 'prepend', 'isBOF', 'isEOF', 'isEmpty'];
    for (let i = publicMethods.length - 1; i >= 0; i--) {
      this.publicContext[publicMethods[i]] = this[publicMethods[i]].bind(this);
    }

    // these read-only props will be accessible out of ui-scroll via user defined adapter
    const publicProps = ['isLoading', 'topVisible', 'topVisibleElement', 'topVisibleScope', 'bottomVisible', 'bottomVisibleElement', 'bottomVisibleScope'];
    for (let i = publicProps.length - 1; i >= 0; i--) {
      let property, attr = this.$attr[publicProps[i]];
      Object.defineProperty(this, publicProps[i], {
        get: () => property,
        set: (value) => {
          property = value;
          this.publicContext[publicProps[i]] = value;
          if (attr) {
            this.$parse(attr).assign(this.startScope, value);
          }
        }
      });
    }

    // read-only immediately calculated public properties
    const publicPropsImmediate = ['bufferFirst', 'bufferLast', 'bufferLength'];
    for (let i = publicPropsImmediate.length - 1; i >= 0; i--) {
      Object.defineProperty(this.publicContext, publicPropsImmediate[i], {
        get: () => this[publicPropsImmediate[i]]
      });
    }

    // non-read-only public property
    Object.defineProperty(this.publicContext, 'disabled', {
      get: () => this.disabled,
      set: (value) => (!(this.disabled = value)) ? this.doAdjust() : null
    });
  }

  loading(value) {
    this.isLoading = value;
  }

  isBOF() {
    return this.buffer.bof;
  }

  isEOF() {
    return this.buffer.eof;
  }

  isEmpty() {
    return !this.buffer.length;
  }

  get bufferLength() {
    return this.buffer.getItems().length;
  }

  get bufferFirst() {
    return this.buffer.getFirstItem();
  }

  get bufferLast() {
    return this.buffer.getLastItem();
  }

  append(newItems) {
    this.buffer.append(newItems);
    this.doAdjust();
    this.viewport.clipTop();
    this.viewport.clipBottom();
  }

  prepend(newItems) {
    this.buffer.prepend(newItems);
    this.doAdjust();
    this.viewport.clipTop();
    this.viewport.clipBottom();
  }

  applyUpdates(arg1, arg2, arg3) {
    if (typeof arg1 === 'function') {
      this.applyUpdatesFunc(arg1, arg2);
    } else {
      this.applyUpdatesIndex(arg1, arg2, arg3);
    }
    this.doAdjust();
  }

  applyUpdatesFunc(cb, options) {
    this.buffer.slice(0).forEach((wrapper) => {
      // we need to do it on the buffer clone, because buffer content
      // may change as we iterate through
      this.applyUpdate(wrapper, cb(wrapper.item, wrapper.scope, wrapper.element), options);
    });
  }

  applyUpdatesIndex(index, newItems, options = {}) {
    if (index % 1 !== 0) {
      throw new Error('applyUpdates - ' + index + ' is not a valid index (should be an integer)');
    }
    const _index = index - this.buffer.first;

    // apply updates only within buffer
    if (_index >= 0 && _index < this.buffer.length) {
      this.applyUpdate(this.buffer[_index], newItems, options);
    }
    // out-of-buffer case: deletion may affect Paddings
    else if(index >= this.buffer.getAbsMinIndex() && index <= this.buffer.getAbsMaxIndex()) {
      if(angular.isArray(newItems) && !newItems.length) {
        this.viewport.removeCacheItem(index, !options.immutableTop && index === this.buffer.minIndex);
        if (!options.immutableTop && index === this.buffer.getAbsMinIndex()) {
          this.buffer.incrementMinIndex();
        }
        else {
          this.buffer.decrementMaxIndex();
        }
      }
    }
  }

  applyUpdate(wrapper, newItems, options = {}) {
    if (!angular.isArray(newItems)) {
      return;
    }
    let position = this.buffer.indexOf(wrapper);
    if (!newItems.reverse().some(newItem => newItem === wrapper.item)) {
      wrapper.op = 'remove';
      if (!options.immutableTop && position === 0 && !newItems.length) {
        wrapper._op = 'isTop'; // to catch "first" edge case on remove
      }
    }
    newItems.forEach((newItem) => {
      if (newItem === wrapper.item) {
        position--;
      } else {
        // 3 parameter (isTop) is to catch "first" edge case on insert
        this.buffer.insert(position + 1, newItem, !options.immutableTop && position === -1);
      }
    });
  }

  calculateProperties() {
    let rowTop = null, topHeight = 0;
    let topDone = false, bottomDone = false;
    const length = this.buffer.length;

    for (let i = 0; i < length; i++) {
      const item = this.buffer[i];
      const itemTop = item.element.offset().top;

      if (rowTop !== itemTop) { // a new row condition
        const itemHeight = item.element.outerHeight(true);
        const top = this.viewport.topDataPos() + topHeight + itemHeight;

        if (!topDone && top > this.viewport.topVisiblePos()) {
          topDone = true;
          this['topVisible'] = item.item;
          this['topVisibleElement'] = item.element;
          this['topVisibleScope'] = item.scope;
        }
        if (!bottomDone && (top >= this.viewport.bottomVisiblePos() || (i === length - 1 && this.isEOF()))) {
          bottomDone = true;
          this['bottomVisible'] = item.item;
          this['bottomVisibleElement'] = item.element;
          this['bottomVisibleScope'] = item.scope;
        }
        topHeight += itemHeight;
      }
      rowTop = itemTop;

      if (topDone && bottomDone) {
        break;
      }
    }
  }

}

export default Adapter;
<|endoftext|>