Completed
Push — master ( b52df4...612930 )
by Andres
30s
created

angular.controller(ꞌct_fusionꞌ)   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
c 0
b 0
f 0
nc 1
dl 0
loc 5
rs 9.4285
nop 1
1
/**
2
 fusion
3
 Component that handles the fusion of isotopes to create new ones.
4
5
 @namespace Components
6
 */
7
'use strict';
8
9
angular.module('game').component('fusion', {
10
  templateUrl: 'views/fusion.html',
11
  controller:  'ct_fusion',
12
  controllerAs: 'ct'
13
});
14
15
angular.module('game').controller('ct_fusion', ['state', 'format', 'visibility', 'data', 'util', 'reaction',
16
  function (state, format, visibility, data, util, reactionService) {
17
    let ct = this;
18
    ct.state = state;
19
    ct.data = data;
20
    ct.util = util;
21
    ct.format = format;
22
23
    ct.getReactorArea = function(player) {
24
      let level = player.global_upgrades.fusion_area;
25
      let upgrade = data.global_upgrades.fusion_area;
26
      let basePower = upgrade.power;
27
      let multiplier = upgrade.power_mult;
28
      return basePower * Math.floor(multiplier * level);
29
    };
30
31
    ct.getBandwidth = function(player){
32
        let level = player.global_upgrades.fusion_bandwidth;
33
        let upgrade = data.global_upgrades.fusion_bandwidth;
34
        let basePower = upgrade.power;
35
        let exp = upgrade.power_exp;
36
        return basePower * Math.pow(exp, level);
37
    }
38
39
    function getFermiRadius(resource) {
40
      let isotope = data.resources[resource];
41
      let A = isotope.energy/data.constants.U_TO_EV;
42
      return data.constants.FERMI_RADIUS * Math.pow(A, 0.3333);
43
    }
44
45
    function getZ(resource){
46
      let isotope = data.resources[resource];
47
      let element = Object.keys(isotope.elements)[0];
48
      return data.elements[element].number;
49
    }
50
51
    ct.getCapacity = function(resource, player) {
52
      let isotope = data.resources[resource];
53
      let element = Object.keys(isotope.elements)[0];
54
      let r = data.elements[element].van_der_waals;
55
      let area = Math.PI*r*r;
56
      return ct.getReactorArea(player)/area;
57
    };
58
59
    ct.getTime = function(player) {
60
      let time = ct.getFusionReaction(player).reactant.eV/ct.getBandwidth(player);
61
      time = Math.floor(time);
62
      return Math.max(1, time);
63
    }
64
65
    ct.getProductIsotope = function(beam, target) {
66
      let beamN = parseInt(beam, 10);
67
      let targetN = parseInt(target, 10);
68
69
      let beamZ = getZ(beam);
70
      let targetZ = getZ(target);
71
72
      let productN = beamN+targetN;
73
      let productZ = beamZ+targetZ;
74
75
      return data.resource_matrix[productZ][productN];
76
    };
77
78
    ct.getProductEnergy = function(beam, target) {
79
      let product = ct.getProductIsotope(beam, target);
80
      if(!product){
81
        return 0;
82
      }
83
      let beamBE = data.resources[beam].binding_energy;
84
      let targetBE = data.resources[target].binding_energy;
85
      let productBE = data.resources[product].binding_energy;
86
87
      return productBE - (beamBE + targetBE);
88
    };
89
90
    ct.getCoulombBarrier = function(beam, target) {
91
      let beamZ = getZ(beam);
92
      let beamR = getFermiRadius(beam);
93
94
      let targetZ = getZ(target);
95
      let targetR = getFermiRadius(target);
96
97
      let coulombBarrier = data.constants.COULOMB_CONSTANT*beamZ*targetZ*
98
              Math.pow(data.constants.ELECTRON_CHARGE, 2)/(beamR+targetR);
99
      return coulombBarrier * data.constants.JOULE_TO_EV;
100
    };
101
102
    ct.getYieldPercent = function(player) {
103
      let beam = state.player.fusion[0].beam;
104
      let target = state.player.fusion[0].target;
105
      let beamR = getFermiRadius(beam.name);
106
      let targetR = getFermiRadius(target.name);
107
      let beamArea = Math.PI*beamR*beamR;
108
      let targetArea = Math.PI*targetR*targetR;
109
110
      let beamPercentArea = beamArea*beam.number/ct.getReactorArea(player);
111
      let targetPercentArea = targetArea*target.number/ct.getReactorArea(player);
112
113
      return beamPercentArea*targetPercentArea;
114
    };
115
116
    ct.getYield = function(player){
117
      let percentYield = ct.getYieldPercent(player);
118
      let target = state.player.fusion[0].target.number;
119
      let beam = state.player.fusion[0].beam.number;
120
      // the yield comes from wherever source is more abundant
121
      let impacted = Math.max(target, beam);
122
      return Math.floor(percentYield*impacted);
123
    };
124
125
    ct.getFusionReaction = function(player) {
126
      let reaction = {
127
        reactant: {},
128
        product: {}
129
      };
130
131
      let beam = state.player.fusion[0].beam;
132
      let target = state.player.fusion[0].target;
133
134
      reaction.reactant[beam.name] = beam.number;
135
      reaction.reactant[target.name] = target.number;
136
137
      let coulombBarrier = ct.getCoulombBarrier(beam.name, target.name);
138
      reaction.reactant.eV = coulombBarrier*beam.number;
139
140
      let product = ct.getProductIsotope(beam.name, target.name);
141
      let numberYield = ct.getYield(player);
142
143
      reaction.product[product] = numberYield;
144
145
      // return the leftovers from the reaction
146
      if(numberYield < beam.number){
147
        reaction.product[beam.name] = beam.number - numberYield;
148
      }
149
      if(numberYield < target.number){
150
        reaction.product[target.name] = target.number - numberYield;
151
      }
152
153
      let energyExchange = ct.getProductEnergy(beam.name, target.name);
154
      if(energyExchange < 0){
155
        reaction.reactant.eV += energyExchange*numberYield;
156
      }else if(energyExchange > 0){
157
        reaction.product.eV = energyExchange*numberYield;
158
      }
159
160
      return reaction;
161
    };
162
163
    function activateFusion(player){
164
      let beam = player.fusion[0].beam;
165
      let target = player.fusion[0].target;
166
167
      if(player.resources[beam.name].number < beam.number ||
168
        player.resources[target.name].number < target.number){
169
        player.fusion[0].running = false;
170
        return;
171
      }
172
      player.resources[beam.name].number -= beam.number;
173
      player.resources[target.name].number -= target.number;
174
175
      player.fusion[0].running = true;
176
    }
177
178
    ct.stopFusion = function(player, fusion) {
179
      if(fusion.running){
180
        let beam = state.player.fusion[0].beam;
181
        let target = state.player.fusion[0].target;
182
183
        player.resources[beam.name].number += fusion.beam.number
184
        player.resources[target.name].number += fusion.target.number
185
      }
186
187
      fusion.eV = 0;
188
      fusion.active = false;
189
      fusion.running = false;
190
      fusion.run = false;
191
    }
192
193
    function updateFusion(player, fusion) {
194
        let bandwidth = ct.getBandwidth(player);
195
        let spent = Math.min(player.resources.eV.number, bandwidth);
196
        fusion.eV += spent;
197
        player.resources.eV.number -= spent;
198
    }
199
200
    function endFusion(player, fusion, reaction) {
201
      // energy is not lost! if there are leftovers, give them back to the player
202
      let leftover = fusion.eV - reaction.reactant.eV;
203
      reaction.product.eV = reaction.product.eV + leftover || leftover;
204
      // Reaction checks that the player has the quantity necessary
205
      // to react, but here eV is stored in the fusion object. By setting the cost to 0
206
      // we make sure that it always work
207
      reaction.reactant= {eV:0};
208
      reactionService.react(1, reaction, player);
209
210
      fusion.eV = 0;
211
      player.fusion[0].running = false;
212
    }
213
214
    function update(player){
215
      for(let fusion of player.fusion){
216
        if(!fusion.active){
217
          continue;
218
        }
219
        if(fusion.eV === 0 && fusion.run){
220
          activateFusion(player);
221
        }
222
        if(!fusion.running){
223
          continue;
224
        }
225
        updateFusion(player, fusion);
226
        let reaction = ct.getFusionReaction(player);
227
        if(fusion.eV >= reaction.reactant.eV){
228
          endFusion(player, fusion, reaction)
229
        }
230
      }
231
    }
232
233
    state.registerUpdate('fusion', update);
234
  }
235
]);
236