Skip to content

Commit 8dba128

Browse files
committed
Solution 32 - TypeScript
1 parent 5b5dd62 commit 8dba128

File tree

1 file changed

+296
-0
lines changed
  • Roadmap/32 - BATALLA DEADPOOL Y WOLVERINE/typescript

1 file changed

+296
-0
lines changed
Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
/* -------------------------------------------------------------------------- */
2+
/* SUPERHEROREGENERATINGERROR (ERROR) */
3+
/* -------------------------------------------------------------------------- */
4+
5+
import {setTimeout} from 'timers/promises'
6+
7+
class SuperheroRegeneratingError extends Error {
8+
public constructor(superhero: ISuperhero) {
9+
super(`${superhero.getName()} is regenerating`)
10+
this.name = 'SuperheroRegeneratingError'
11+
}
12+
}
13+
14+
/* -------------------------------------------------------------------------- */
15+
/* SUPERHERO (CLASS) */
16+
/* -------------------------------------------------------------------------- */
17+
18+
interface ISuperhero {
19+
getAttackDamage: () => Readonly<[number, number]>
20+
getLifePoints: () => number
21+
getName: () => Capitalize<string>
22+
isRegenerating: () => boolean
23+
setRegenerating: (regenerating: boolean) => this
24+
evadeAttack: () => boolean
25+
produceDamage: () => number | never
26+
receiveDamage: (damage: number) => this
27+
}
28+
29+
interface SuperheroConstructor {
30+
lifePoints: number
31+
attackDamage: [number, number]
32+
evadePercentage: number
33+
name: Capitalize<string>
34+
}
35+
36+
class Superhero implements ISuperhero {
37+
private lifePoints: number
38+
private regenerating: boolean
39+
private readonly attackDamage: Readonly<[number, number]>
40+
private readonly evadePercentage: number
41+
private readonly name: Capitalize<string>
42+
43+
protected constructor({
44+
attackDamage,
45+
evadePercentage,
46+
lifePoints,
47+
name,
48+
}: SuperheroConstructor) {
49+
this.lifePoints = lifePoints
50+
this.regenerating = false
51+
this.attackDamage = attackDamage
52+
this.evadePercentage = evadePercentage
53+
this.name = name
54+
}
55+
56+
public getAttackDamage(): Readonly<[number, number]> {
57+
return this.attackDamage
58+
}
59+
60+
public getLifePoints(): number {
61+
return this.lifePoints
62+
}
63+
64+
public getName(): Capitalize<string> {
65+
return this.name
66+
}
67+
68+
public isRegenerating(): boolean {
69+
return this.regenerating
70+
}
71+
72+
public setRegenerating(regenerating: boolean): this {
73+
this.regenerating = regenerating
74+
return this
75+
}
76+
77+
public evadeAttack(): boolean {
78+
const rndNumber: number = Math.random()
79+
return rndNumber <= this.evadePercentage
80+
}
81+
82+
public produceDamage(): number | never {
83+
if (this.isRegenerating()) throw new SuperheroRegeneratingError(this)
84+
85+
const [minAttackDamage, maxAttackDamage]: readonly [number, number] =
86+
this.getAttackDamage()
87+
88+
const rndDamage: number = Math.max(
89+
minAttackDamage,
90+
Math.round(Math.random() * maxAttackDamage)
91+
)
92+
93+
return rndDamage
94+
}
95+
96+
public receiveDamage(damage: number): this {
97+
this.lifePoints -= damage
98+
return this
99+
}
100+
}
101+
102+
/* -------------------------------------------------------------------------- */
103+
/* WOLVERINE (CLASS) */
104+
/* -------------------------------------------------------------------------- */
105+
106+
interface IWolverine {}
107+
108+
interface WolverineConstructor
109+
extends Omit<
110+
SuperheroConstructor,
111+
'attackDamage' | 'evadePercentage' | 'name'
112+
> {}
113+
114+
class Wolverine extends Superhero implements IWolverine {
115+
public constructor({lifePoints}: WolverineConstructor) {
116+
super({
117+
attackDamage: [10, 120],
118+
evadePercentage: 0.2,
119+
lifePoints,
120+
name: 'Wolverine',
121+
})
122+
}
123+
}
124+
125+
/* -------------------------------------------------------------------------- */
126+
/* DEADPOOL (CLASS) */
127+
/* -------------------------------------------------------------------------- */
128+
129+
interface IDeadpool {}
130+
131+
interface DeadpoolConstructor
132+
extends Omit<
133+
SuperheroConstructor,
134+
'attackDamage' | 'evadePercentage' | 'name'
135+
> {}
136+
137+
class Deadpool extends Superhero implements IDeadpool {
138+
public constructor({lifePoints}: DeadpoolConstructor) {
139+
super({
140+
attackDamage: [10, 100],
141+
evadePercentage: 0.25,
142+
lifePoints,
143+
name: 'Deadpool',
144+
})
145+
}
146+
}
147+
148+
/* -------------------------------------------------------------------------- */
149+
/* SUPERHEROESFIGHT (CLASS) */
150+
/* -------------------------------------------------------------------------- */
151+
152+
interface Turn {
153+
attacker: ISuperhero
154+
number: number
155+
victim: ISuperhero
156+
}
157+
158+
interface ExecutedTurn extends Turn {
159+
damageProducedByAttacker: number
160+
damageReceivedByVictim: number
161+
victimAvoidAttack: boolean
162+
}
163+
164+
interface ISuperheroFight {
165+
getTurn: () => Readonly<Turn>
166+
getWinner: () => ISuperhero | undefined
167+
executeTurn: () => Readonly<ExecutedTurn> | never
168+
}
169+
170+
interface SuperheroFightConstructor {
171+
superHeroOne: ISuperhero
172+
superHeroTwo: ISuperhero
173+
}
174+
175+
class SuperheroFight implements ISuperheroFight {
176+
private turn: Readonly<Turn>
177+
private winner: undefined | ISuperhero
178+
179+
public constructor({
180+
superHeroOne,
181+
superHeroTwo,
182+
}: SuperheroFightConstructor) {
183+
this.turn = {
184+
attacker: superHeroOne,
185+
number: 1,
186+
victim: superHeroTwo,
187+
}
188+
189+
this.winner = undefined
190+
}
191+
192+
public getTurn(): Readonly<Turn> {
193+
return this.turn
194+
}
195+
196+
public getWinner(): undefined | ISuperhero {
197+
return this.winner
198+
}
199+
200+
public executeTurn(): Readonly<ExecutedTurn> | never {
201+
const {attacker, number, victim} = this.getTurn()
202+
203+
victim.setRegenerating(false)
204+
205+
this.turn = {
206+
attacker: victim,
207+
number: number + 1,
208+
victim: attacker,
209+
}
210+
211+
try {
212+
const damageProducedByAttacker = attacker.produceDamage()
213+
const victimAvoidAttack = victim.evadeAttack()
214+
215+
if (!victimAvoidAttack)
216+
victim.receiveDamage(damageProducedByAttacker)
217+
218+
if (victim.getLifePoints() <= 0) this.winner = attacker
219+
220+
return {
221+
attacker,
222+
victim,
223+
number,
224+
damageProducedByAttacker,
225+
victimAvoidAttack,
226+
damageReceivedByVictim: victimAvoidAttack
227+
? 0
228+
: damageProducedByAttacker,
229+
}
230+
} catch (error) {
231+
throw error
232+
}
233+
}
234+
}
235+
236+
/* -------------------------------------------------------------------------- */
237+
/* MAIN */
238+
/* -------------------------------------------------------------------------- */
239+
240+
;(async () => {
241+
const deadpool: Deadpool = new Deadpool({lifePoints: 500})
242+
const wolverine: Wolverine = new Wolverine({lifePoints: 500})
243+
244+
const superheroFight: SuperheroFight = new SuperheroFight({
245+
superHeroOne: deadpool,
246+
superHeroTwo: wolverine,
247+
})
248+
249+
while (!superheroFight.getWinner()) {
250+
await setTimeout(1000)
251+
const currentTurn: Readonly<Turn> = superheroFight.getTurn()
252+
253+
try {
254+
const executedTurn: Readonly<ExecutedTurn> =
255+
superheroFight.executeTurn()
256+
const attackerAttackDamage: Readonly<[number, number]> =
257+
executedTurn.attacker.getAttackDamage()
258+
259+
if (executedTurn.victimAvoidAttack) {
260+
console.log(
261+
`\n> Turn N°${
262+
currentTurn.number
263+
}: ${currentTurn.victim.getName()} avoided ${currentTurn.attacker.getName()} attack.`
264+
)
265+
266+
continue
267+
}
268+
269+
currentTurn.victim.setRegenerating(
270+
executedTurn.damageProducedByAttacker ===
271+
attackerAttackDamage[1]
272+
)
273+
274+
console.log(
275+
`\n> Turn N°${
276+
currentTurn.number
277+
}: ${currentTurn.attacker.getName()} attacked ${currentTurn.victim.getName()} with ${
278+
executedTurn.damageProducedByAttacker
279+
} points of damage.`
280+
)
281+
282+
console.log(
283+
`[ Life points of Deadpool: ${deadpool.getLifePoints()} ]\n` +
284+
`[ Life points of Wolverine: ${wolverine.getLifePoints()} ]`
285+
)
286+
} catch (error) {
287+
if (error instanceof SuperheroRegeneratingError) {
288+
console.log(
289+
`\n> Turn N°${currentTurn.number}: ${error.message}.`
290+
)
291+
}
292+
}
293+
}
294+
295+
console.log(`\n¡The winner is ${superheroFight.getWinner()?.getName()}!`)
296+
})()

0 commit comments

Comments
 (0)