<commit_before>define([
	"dojo/_base/declare", "dojo/_base/lang", "dojo/_base/Deferred",
	"dojo/request", "dojo/when", "dojo/Stateful", "dojo/topic",
	"dojo/store/Memory", "dojo/store/util/QueryResults",
	"./ArrangeableMemoryStore", "./HeatmapDataTypes"
], function(declare, lang, Deferred,
			request, when, Stateful, Topic,
			Memory, QueryResults,
			ArrangeableMemoryStore){

	var pfState = {
		familyType: 'figfam', // default
		heatmapAxis: '',
		genomeIds: [],
		genomeFilterStatus: {},
		clusterRowOrder: [],
		clusterColumnOrder: [],
		keyword: '',
		perfectFamMatch: 'A',
		min_member_count: null,
		max_member_count: null,
		min_genome_count: null,
		max_genome_count: null
	};

	return declare([ArrangeableMemoryStore, Stateful], {
		baseQuery: {},
		apiServer: window.App.dataServiceURL,
		idProperty: "family_id",
		state: null,
		pfState: pfState,

		onSetState: function(attr, oldVal, state){
			// console.warn("onSetState", state, state.genome_ids);
			if(state && state.genome_ids){
				this._loaded = false;
				delete this._loadingDeferred;
			}
		},

		constructor: function(options){
			this._loaded = false;
			if(options.apiServer){
				this.apiServer = options.apiServer;
			}

			var self = this;

			Topic.subscribe("ProteinFamilies", function(){
				// console.log("received:", arguments);
				var key = arguments[0], value = arguments[1];

				switch(key){
					case "setFamilyType":
						self.pfState.familyType = value;
						self.reload();
						Topic.publish("ProteinFamilies", "showMainGrid");
						// TODO: need to wait until data is loaded and update heatmap data
						// self.currentData = self.getHeatmapData(self.pfState);
						// Topic.publish("ProteinFamilies", "updateHeatmapData", self.currentData);
						break;
					case "anchorByGenome":
						self.anchorByGenome(value);
						break;
					case "applyConditionFilter":
						self.pfState = value;
						self.conditionFilter(value);
						self.currentData = self.getHeatmapData(self.pfState);
						Topic.publish("ProteinFamilies", "updatePfState", self.pfState);
						Topic.publish("ProteinFamilies", "updateHeatmapData", self.currentData);
						break;
					case "requestHeatmapData":
						// console.log("requestHeatmapData with ", value.genomeIds);
						self.currentData = self.getHeatmapData(value);
						Topic.publish("ProteinFamilies", "updateHeatmapData", self.currentData);
						break;
					default:
						break;
				}
			});

			this.watch("state", lang.hitch(this, "onSetState"));
		},
		conditionFilter: function(pfState){
			var self = this;
			if(self._filtered == undefined){ // first time
				self._filtered = true;
				self._original = this.query("", {});
			}
			var data = self._original;
			var newData = [];
			var gfs = pfState.genomeFilterStatus;

			// var tsStart = window.performance.now();
			var keywordRegex = pfState.keyword.trim().toLowerCase().replace(/,/g, "~").replace(/\n/g, "~").replace(/ /g, "~").split("~");

			data.forEach(function(family){

				var skip = false;

				// genomes
				Object.keys(gfs).forEach(function(genomeId){
					var index = gfs[genomeId].getIndex();
					var status = gfs[genomeId].getStatus();
					//console.log(family.family_id, genomeId, index, status, family.genomes, parseInt(family.genomes.substr(index * 2, 2), 16));
					if(status == 1 && parseInt(family.genomes.substr(index * 2, 2), 16) > 0){
						skip = true;
					}
					else if(status == 0 && parseInt(family.genomes.substr(index * 2, 2), 16) == 0){
						skip = true;
					}
				});

				// keyword search
				if(pfState.keyword !== ''){
					skip = !keywordRegex.some(function(needle){
						return needle && (family.description.toLowerCase().indexOf(needle) >= 0 || family.family_id.toLowerCase().indexOf(needle) >= 0);
					});
				}

				// perfect family
				if(pfState.perfectFamMatch === 'Y'){
					family.feature_count !== family.genome_count ? skip = true : {};
				}else if(pfState.perfectFamMatch === 'N'){
					family.feature_count === family.genome_count ? skip = true : {};
				}

				// num proteins per family
				if(pfState.min_member_count){
					family.feature_count < pfState.min_member_count ? skip = true : {};
				}
				if(pfState.max_member_count){
					family.feature_count > pfState.max_member_count ? skip = true : {};
				}

				// num genomes per family
				if(pfState.min_genome_count){
					family.genome_count < pfState.min_genome_count ? skip = true : {};
				}
				if(pfState.max_genome_count){
					family.genome_count > pfState.max_genome_count ? skip = true : {};
				}

				if(!skip){
					newData.push(family);
				}
			});
			// console.log("genomeFilter took " + (window.performance.now() - tsStart), " ms");

			self.setData(newData);
			self.set("refresh");
		},
		reload: function(){
			var self = this;
			delete self._loadingDeferred;
			self._loaded = false;
			self.loadData();
			self.set("refresh");
		},

		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);<commit_msg>cancel request when it reloads before it gets reloaded<commit_after>define([
	"dojo/_base/declare", "dojo/_base/lang", "dojo/_base/Deferred",
	"dojo/request", "dojo/when", "dojo/Stateful", "dojo/topic",
	"dojo/store/Memory", "dojo/store/util/QueryResults",
	"./ArrangeableMemoryStore", "./HeatmapDataTypes"
], function(declare, lang, Deferred,
			request, when, Stateful, Topic,
			Memory, QueryResults,
			ArrangeableMemoryStore){

	var pfState = {
		familyType: 'figfam', // default
		heatmapAxis: '',
		genomeIds: [],
		genomeFilterStatus: {},
		clusterRowOrder: [],
		clusterColumnOrder: [],
		keyword: '',
		perfectFamMatch: 'A',
		min_member_count: null,
		max_member_count: null,
		min_genome_count: null,
		max_genome_count: null
	};

	return declare([ArrangeableMemoryStore, Stateful], {
		baseQuery: {},
		apiServer: window.App.dataServiceURL,
		idProperty: "family_id",
		state: null,
		pfState: pfState,

		onSetState: function(attr, oldVal, state){
			// console.warn("onSetState", state, state.genome_ids);
			if(state && state.genome_ids){
				this._loaded = false;
				delete this._loadingDeferred;
			}
		},

		constructor: function(options){
			this._loaded = false;
			if(options.apiServer){
				this.apiServer = options.apiServer;
			}

			var self = this;

			Topic.subscribe("ProteinFamilies", function(){
				// console.log("received:", arguments);
				var key = arguments[0], value = arguments[1];

				switch(key){
					case "setFamilyType":
						self.pfState.familyType = value;
						self.reload();
						Topic.publish("ProteinFamilies", "showMainGrid");
						// TODO: need to wait until data is loaded and update heatmap data
						// self.currentData = self.getHeatmapData(self.pfState);
						// Topic.publish("ProteinFamilies", "updateHeatmapData", self.currentData);
						break;
					case "anchorByGenome":
						self.anchorByGenome(value);
						break;
					case "applyConditionFilter":
						self.pfState = value;
						self.conditionFilter(value);
						self.currentData = self.getHeatmapData(self.pfState);
						Topic.publish("ProteinFamilies", "updatePfState", self.pfState);
						Topic.publish("ProteinFamilies", "updateHeatmapData", self.currentData);
						break;
					case "requestHeatmapData":
						// console.log("requestHeatmapData with ", value.genomeIds);
						self.currentData = self.getHeatmapData(value);
						Topic.publish("ProteinFamilies", "updateHeatmapData", self.currentData);
						break;
					default:
						break;
				}
			});

			this.watch("state", lang.hitch(this, "onSetState"));
		},
		conditionFilter: function(pfState){
			var self = this;
			if(self._filtered == undefined){ // first time
				self._filtered = true;
				self._original = this.query("", {});
			}
			var data = self._original;
			var newData = [];
			var gfs = pfState.genomeFilterStatus;

			// var tsStart = window.performance.now();
			var keywordRegex = pfState.keyword.trim().toLowerCase().replace(/,/g, "~").replace(/\n/g, "~").replace(/ /g, "~").split("~");

			data.forEach(function(family){

				var skip = false;

				// genomes
				Object.keys(gfs).forEach(function(genomeId){
					var index = gfs[genomeId].getIndex();
					var status = gfs[genomeId].getStatus();
					//console.log(family.family_id, genomeId, index, status, family.genomes, parseInt(family.genomes.substr(index * 2, 2), 16));
					if(status == 1 && parseInt(family.genomes.substr(index * 2, 2), 16) > 0){
						skip = true;
					}
					else if(status == 0 && parseInt(family.genomes.substr(index * 2, 2), 16) == 0){
						skip = true;
					}
				});

				// keyword search
				if(pfState.keyword !== ''){
					skip = !keywordRegex.some(function(needle){
						return needle && (family.description.toLowerCase().indexOf(needle) >= 0 || family.family_id.toLowerCase().indexOf(needle) >= 0);
					});
				}

				// perfect family
				if(pfState.perfectFamMatch === 'Y'){
					family.feature_count !== family.genome_count ? skip = true : {};
				}else if(pfState.perfectFamMatch === 'N'){
					family.feature_count === family.genome_count ? skip = true : {};
				}

				// num proteins per family
				if(pfState.min_member_count){
					family.feature_count < pfState.min_member_count ? skip = true : {};
				}
				if(pfState.max_member_count){
					family.feature_count > pfState.max_member_count ? skip = true : {};
				}

				// num genomes per family
				if(pfState.min_genome_count){
					family.genome_count < pfState.min_genome_count ? skip = true : {};
				}
				if(pfState.max_genome_count){
					family.genome_count > pfState.max_genome_count ? skip = true : {};
				}

				if(!skip){
					newData.push(family);
				}
			});
			// console.log("genomeFilter took " + (window.performance.now() - tsStart), " ms");

			self.setData(newData);
			self.set("refresh");
		},
		reload: function(){
			var self = this;

			if(!self._loadingDeferred.isResolved()){
				self._loadingDeferred.cancel('reloaded');
				// console.log(self._loadingDeferred.isResolved(), self._loadingDeferred.isCanceled(), self._loadingDeferred.isRejected());
			}

			delete self._loadingDeferred;
			self._loaded = false;
			self.loadData();
			self.set("refresh");
		},

		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);
{'fraction_non_alphanumeric': 0.15501081470800288, 'fraction_numerical': 0.003604902667627974, 'mean_word_length': 3.309514563106796, 'pattern_counts': {'":': 8, '<': 7, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6098580', 'n_tokens_mistral': 4610, 'n_tokens_neox': 3537, 'n_words': 670}