/*
    [{anyField:1,weight:1},{anyField:2,weight:2}].getRandomWeighted()
    will return the first array entry with 1/3 chance and the second with 2/3 chance
    Any fields are allowed as long as a weight-field is present.
    Any array-size is allowed.
*/
Array.prototype.avg ??= function(){
	return this.reduce( ( p, c ) => p + c, 0 ) / (this.length || 1);
}

Array.prototype.filterByObject ??= function(filter){
	let result = [];
	entryloop:for(const entry of this){
		filterloop:for(const [filterKey, filterValue] of Object.entries(filter)){
			const fieldValueOfEntry = entry[filterKey];
			if(typeof filterValue == "object"){
				if(Object.keys(filterValue).length == 0){
					if(typeof fieldValueOfEntry == "object")
						continue filterloop;
					continue entryloop;
				}
				if("max" in filterValue){
					if(typeof fieldValueOfEntry != "number" || fieldValueOfEntry > filterValue.max)
						continue entryloop;
				}
				if("min" in filterValue){
					if(typeof fieldValueOfEntry != "number" || fieldValueOfEntry < filterValue.min)
						continue entryloop;
				}
			}else{
				if(fieldValueOfEntry != filterValue)
					continue entryloop;
			}
			
		}
		result.push(entry);
	}
	return result;
}



Array.prototype.getRandomWeightedId = function(flags={}){
	if(flags.isKeyValuePair){
		const mapped = this.map(([key,entry]) => Object.assign({},entry,{id:key}));
		return mapped.getRandomWeighted();
	}

	let weightSum = this.reduce((accumulator, currentValue) => accumulator + currentValue.weight,0);
	let weightRandom = rand(1,weightSum);
	//for(let entry of this){
	for(const entryId in this){
		const entry = this[entryId];
		weightRandom -= entry.weight;
		if(weightRandom <= 0)
			return entryId;
	}
}

Array.prototype.pluckRandomWeighted = function(){
	if(this.length == 0)
		return null;
	const resultId = this.getRandomWeightedId();
	const result = this[resultId];
	this.splice(resultId,1);
	return result;
}

Array.prototype.groupBy = function(key){
	let result = {};
	for(const entry of this){
		result[entry[key]] ??= [];
		result[entry[key]].push(entry);
	}
	return result;
}


if(!Array.prototype.toReversed)
    Array.prototype.toReversed = function(){
        let copy = clone(this);
        return copy.reverse();
    }



Array.prototype.keepSize ??= function(n) {
	if (this.length > n) {
		const elementsToRemove = this.length - n;
		this.splice(0, elementsToRemove);
	}
};