Completed
Push — master ( 11ad5b...75bd7c )
by Andres
30s
created

angular.controller(ꞌct_generatorsꞌ)   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
dl 0
loc 16
rs 9.4285
c 0
b 0
f 0
nop 4
1
/**
2
 generators
3
 Component that handles generators, resource creation, isotopes and decay.
4
5
 @namespace Components
6
 */
7
'use strict';
8
9
angular.module('game').component('generators', {
10
  templateUrl: 'views/generators.html',
11
  controller: 'ct_generators',
12
  controllerAs: 'ct'
13
});
14
15
angular.module('game').controller('ct_generators', ['state', 'visibility', 'data', 'util', 'reaction', 'upgrade',
16
  function (state, visibility, data, util, reaction, upgrade) {
17
    let ct = this;
18
    ct.state = state;
19
    ct.data = data;
20
    let buyAmount = [1, 10, 25, 100, 'max'];
21
22
    /* Proceses the decay of radiactive isotopes. It uses a random draw based on the
23
    half life to decide how many atoms decay, and then spreads them over different
24
    decay forms proportionally. */
25
    function processDecay(player) {
26
      // for each radiactive isotope
27
      for (let i = 0; i < data.radioisotopes.length; i++) {
28
        let resource = data.radioisotopes[i];
29
        if (player.resources[resource].unlocked) {
30
          let number = player.resources[resource].number;
31
          let decay = data.resources[resource].decay;
32
          let halfLife = decay.half_life;
33
          let exponent = 1/halfLife;
34
          let factor = Math.pow(0.5, exponent);
35
          let totalProduction = Math.floor(number - number * factor);
36
          let remaining = totalProduction;
37
          // and decay products
38
          let highestRatio;
39
          for (let type of Object.values(decay.decay_types)) {
40
            if(!highestRatio || highestRatio.ratio < type.ratio){
41
              highestRatio = type;
42
            }
43
            let production = Math.floor(totalProduction * type.ratio);
44
            // FIXME: this is a hack to fix decay not working if the number of
45
            // neutrons is lower than the decay amount. Fixing starvation
46
            // should fix this one as well
47
            if (type.reaction.reactant && type.reaction.reactant.n) {
48
              production = Math.min(production, player.resources.n.number);
49
            }
50
            reaction.react(production, type.reaction, player);
51
            remaining -= production;
52
          }
53
          reaction.react(remaining, highestRatio.reaction, player);
0 ignored issues
show
Bug introduced by
The variable highestRatio seems to not be initialized for all possible execution paths.
Loading history...
54
        }
55
      }
56
    }
57
58
    /* Proceses the generation for each element. It generates isotopes with a random
59
    draw proportionally to their probability. */
60
    function processGenerators(player) {
61
      // we will simulate the production of isotopes proportional to their ratio
62
      for (let slot of player.element_slots) {
63
        if(!slot){
64
          continue;
65
        }
66
        let totalProduction = ct.elementProduction(player, slot);
67
        let remaining = totalProduction;
68
        // for each isotope
69
        for (let key in data.elements[slot.element].isotopes) {
70
          let isotope = data.elements[slot.element].isotopes[key];
71
          // we calculate the production proportion
72
          let production = Math.floor(isotope.ratio * totalProduction);
73
74
          // assign the player the produced isotope
75
          player.resources[key].number += production;
76
          if (production > 0 && !player.resources[key].unlocked) {
77
            player.resources[key].unlocked = true;
78
            state.addNew(key);
79
          }
80
          // keep track of the remaining production
81
          remaining -= production;
82
        }
83
        // if there is remaining production, we assign it to the main isotope
84
        let main = data.elements[slot.element].main;
85
        player.resources[main].number += remaining;
86
        if (remaining > 0 && !player.resources[main].unlocked) {
87
          player.resources[main].unlocked = true;
88
          state.addNew(main);
89
        }
90
      }
91
    }
92
93
    function update(player) {
94
      processDecay(player);
95
      processGenerators(player);
96
    }
97
98
    function generatorPrice(name, level) {
99
      return data.generators[name].price * Math.pow(data.constants.GENERATOR_PRICE_INCREASE, level);
100
    }
101
102
    ct.maxCanBuy = function (player, name, slot) {
103
      let level = slot.generators[name];
104
      let i = 0;
105
      let currency = data.elements[slot.element].main;
106
      let price = generatorPrice(name, level);
107
      // we need a loop since we use the ceil operator
108
      while (player.resources[currency].number >= price) {
109
        i++;
110
        price += generatorPrice(name, level + i);
111
      }
112
      return i;
113
    };
114
115
    ct.generatorTotalPrice = function (player, name, slot, number) {
116
      if (number === 'max') {
117
        number = ct.maxCanBuy(player, name, slot);
118
      }
119
      let level = slot.generators[name];
120
      let totalPrice = 0;
121
      for (let i = 0; i < number; i++) {
122
        let price = generatorPrice(name, level + i);
123
        totalPrice += Math.ceil(price);
124
      }
125
      return totalPrice;
126
    };
127
128
    ct.buyGenerators = function (player, name, slot, number) {
129
      if (number === 'max') {
130
        number = ct.maxCanBuy(player, name, slot);
131
      }
132
      let price = this.generatorTotalPrice(player, name, slot, number);
133
      let currency = data.elements[slot.element].main;
134
      if (ct.canBuy(player, slot, price)) {
135
        player.resources[currency].number -= price;
136
        slot.generators[name] += number;
137
      }
138
    };
139
140
    ct.canBuy = function (player, slot, price) {
141
      let currency = data.elements[slot.element].main;
142
      if (price > player.resources[currency].number) {
143
        return false;
144
      }
145
      return true;
146
    };
147
148
    ct.generatorProduction = function (player, name, slot) {
149
      let baseProduction = data.generators[name].power;
150
      return upgradedProduction(player, baseProduction, name, slot);
151
    };
152
153
    ct.tierProduction = function (player, name, slot) {
154
      let baseProduction = data.generators[name].power *
155
        slot.generators[name];
156
      return upgradedProduction(player, baseProduction, name, slot);
157
    };
158
159
    /* Upgraded production includes upgrades, exotic matter and dark matter. */
160
    function upgradedProduction(player, production, name, slot) {
161
      let args = {
162
        production: production,
163
        slot: slot
164
      }
165
      
166
      upgrade.executeAll(data.upgrades, slot.upgrades, [name, 'production'], args);
167
168
      // extract back the value from applying the upgrades
169
      let newProduction = args.production;
170
171
      let exotic = data.elements[slot.element].exotic;
172
      newProduction *= (1 + player.resources[exotic].number * data.constants.EXOTIC_POWER) *
173
        (1 + player.resources.dark_matter.number * data.constants.DARK_POWER);
174
      return Math.floor(newProduction);
175
    }
176
177
    ct.elementProduction = function (player, slot) {
178
      let total = 0;
179
      for (let tier in data.generators) {
180
        total += ct.tierProduction(player, tier, slot);
181
      }
182
      return total;
183
    };
184
185
    ct.visibleGenerators = function (slot) {
186
      return visibility.visible(data.generators, isGeneratorVisible, slot);
187
    };
188
189
    function isGeneratorVisible(name, slot) {
190
      let generator = data.generators[name];
191
      for (let dep of generator.deps) {
192
        if (slot.generators[dep] === 0) {
193
          return false;
194
        }
195
      }
196
197
      return true;
198
    }
199
200
    ct.nextBuyAmount = function () {
201
      state.buyIndex = (state.buyIndex + 1) % buyAmount.length;
202
    };
203
204
    ct.getbuyAmount = function () {
205
      return buyAmount[state.buyIndex];
206
    };
207
208
    state.registerUpdate('generators', update);
209
  }
210
]);
211