const Item = require('./item');
/**
* A base class for all the generators.
* <p>
* Generators are used to produce resources (e.g. currencies), and
* can be controlled either manually or automatically by using
* an Automator.
*/
class Generator extends Item {
constructor(build){
super(build.mWorld, build.mName);
this.maxItemLevel = build.mMaxLevel;
this.amountMultiplier = build.mAmountMultiplier;
this.useRemainder = build.mUseRemainder;
this.timesProcessed = build.mTimesProcessed;
this.currency = build.mCurrency;
this.baseAmount = build.mBaseAmount;
this.remainder = 0;
this.modifiers = [];
}
/**
* Builder class for creating new generators
*/
static get Builder() {
class Builder {
constructor(world) {
this.mWorld = world;
this.mName = "Nameless generator";
this.mOnProcessed = null;
this.mCurrency = null;
this.mBaseAmount = 1;
this.mAmountMultiplier = 1.1;
this.mMaxLevel = 999999999;
this.mBasePrice = 999999999;//BigInteger.ONE;
this.mPriceMultiplier = 1.1;
this.mProbability = 1.0;
this.mProbabilitySet = false;
this.mUseRemainder = true;
this.mCooldown = 0.0;
this.mTimesProcessed = 0;
}
/**
* Sets the cooldown of this generator (in seconds).
* This is the minimum time between processing this
* generator.
*
* @param cooldown in seconds
* @return This builder for chaining
*/
cooldown(cooldown) {
this.cooldown = cooldown;
return this;
}
/**
* Store remainder of resources and generate an extra
* when the remainder "overflows"
*
* @return This builder for chaining
*/
useRemainder() {
this.useRemainder = true;
return this;
}
/**
* Discard remainder of resources when generating.
*
* @return This builder for chaining
*/
discardRemainder() {
this.useRemainder = false;
return this;
}
/**
* Sets the name for the generator
*
* @param name Name for the generator
* @return This builder for chaining
*/
name(name) {
this.name = name;
return this;
}
/**
* Sets the multiplier for resource generation. This multiplier
* is used in the formula (amount) = (base amount) * (multiplier) ^ (level)
*
* @param multiplier Amount generation multiplier per level
* @return This builder for chaining
*/
multiplier(multiplier) {
this.mAmountMultiplier = multiplier;
return this;
}
/**
* Sets the maximum allowed level for this generator. The max level must
* be greated than zero.
*
* @param maxLevel Maximum allowed level for this generator
* @return This builder for chaining
*/
/*this.maxLevel = function(maxLevel) {
//if (maxLevel <= 0)
// throw new IllegalArgumentException("Max level must be greater than 0");
self.maxLevel = maxLevel;
return this;
}*/
/**
* Sets the base amount of resources generated by this generator.
* This is the amount the generator generates at level 1 and is used
* as the base for the higher levels.
*
* @param amount Base amount of resources generated at level 1
* @return This builder for chaining
*/
baseAmount(amount) {
if (amount == null) throw "Base amount cannot be null";
this.mBaseAmount = amount;
return this;
}
/**
* Sets the currency that should be generated by the generator.
*
* @param resource Resource to generate
* @return This builder for chaining
* @throws IllegalArgumentException Thrown if the currency is null
*/
generate(resource) { //throws IllegalArgumentException {
if (resource == null) throw "Currency cannot be null";
this.mCurrency = resource;
return this;
}
/**
* Sets a callback for the generator to be called when the generator
* has finished its processing cycle (i.e. has generated something).
*
* @param callback Callback to call after generating something
* @return This builder for chaining
*/
callback(callback) {
this.onProcessed = callback;
return this;
}
price(price) {
this.basePrice = price;
return this;
}
priceMultiplier(multiplier) {
this.priceMultiplier = multiplier;
return this;
}
/**
* Set a probability for this generator to "work" when it's processed
*
* @param probability Probability percentage (between 0.0 and 1.0)
* @return This builder for chaining
*/
probability(probability) {
if (probability < 0 || probability > 1.0)
throw "Probability should be between 0.0 and 1.0";
this.probability = probability;
this.probabilitySet = true;
return this;
}
build() {
return new Generator(this);
}
}
return Builder;
}
equals(a,b) {
return JSON.stringify(a) === JSON.stringify(b);
}
upgrade() {
if (this.itemLevel < this.maxItemLevel) {
this.itemLevel++;
}
}
/**
* Downgrades this generator by one level
*/
downgrade() {
if (this.itemLevel > 0) {
this.itemLevel--;
}
}
/**
* Retrieves the amount this generator currently is generating per
* processing cycle
*
* @return Amount of resources generated by this generator
* BIG INTEGER
*/
getGeneratedAmount() {
if (this.itemLevel == 0) return 0;
var tmp = this.baseAmount;
tmp = tmp * Math.pow(this.amountMultiplier, this.itemLevel - 1);
if (this.useRemainder) {
var tmpRem = tmp % 1;
this.remainder += tmpRem;
if (this.remainder >= 0.999) {
this.remainder -= 1.0;
tmp = tmp + 1;
}
}
tmp = this.processModifiers(tmp);
return parseInt(tmp);
}
processModifiers(val) {
if (this.modifiers.length == 0) return val;
for(var i = 0; i<this.modifiers.length; i++){
var d = this.modifiers[i].getMultiplier();
if (d != 1.0) {
val = val * d;
}
}
return val;
}
/**
* Determines if this generator should generate anything based on its
* properties such as item level and probability.
*
* @return True if should work, false otherwise
*/
isWorking() {
if (this.itemLevel > 0) {
if (!this.useProbability || Math.Random() < this.probability) return true;
}
return false;
}
/**
* Processes this generator, generating resources as per the rules
* of this generator.
*/
process() {
if (this.isWorking()) {
this.currency.add(this.getGeneratedAmount());
this.timesProcessed++;
//if (callback != null) callback.onProcessed();
}
}
/**
* Retrieves the number of times this generator has done its processing
*
* @return Number of times processed
*/
getTimesProcessed() {
return this.timesProcessed;
}
attachModifier(modifier) {
if (modifier && !this.modifiers.contains(modifier)) {
this.modifiers.push(modifier);
}
}
detachModifier(modifier) {
if (modifier) {
this.modifiers.remove(modifier);
}
}
}
module.exports = Generator;