Skip to content

Commit ae3203d

Browse files
authored
Merge pull request #5386 from hozlucas28/Solution-32-TypeScript
#32 - TypeScript
2 parents cb6a4ab + 1e94be9 commit ae3203d

File tree

1 file changed

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

1 file changed

+295
-0
lines changed
Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
import {setTimeout} from 'timers/promises'
2+
3+
/* -------------------------------------------------------------------------- */
4+
/* SUPERHEROREGENERATINGERROR (ERROR) */
5+
/* -------------------------------------------------------------------------- */
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+
victim.setRegenerating(false)
203+
204+
this.turn = {
205+
attacker: victim,
206+
number: number + 1,
207+
victim: attacker,
208+
}
209+
210+
try {
211+
const damageProducedByAttacker = attacker.produceDamage()
212+
const attackerAttackDamage: Readonly<[number, number]> =
213+
attacker.getAttackDamage()
214+
215+
const victimAvoidAttack = victim.evadeAttack()
216+
217+
if (!victimAvoidAttack) {
218+
victim.receiveDamage(damageProducedByAttacker)
219+
victim.setRegenerating(
220+
damageProducedByAttacker === attackerAttackDamage[1]
221+
)
222+
223+
if (victim.getLifePoints() <= 0) this.winner = attacker
224+
}
225+
226+
return {
227+
attacker,
228+
victim,
229+
number,
230+
damageProducedByAttacker,
231+
victimAvoidAttack,
232+
damageReceivedByVictim: victimAvoidAttack
233+
? 0
234+
: damageProducedByAttacker,
235+
}
236+
} catch (error) {
237+
throw error
238+
}
239+
}
240+
}
241+
242+
/* -------------------------------------------------------------------------- */
243+
/* MAIN */
244+
/* -------------------------------------------------------------------------- */
245+
246+
;(async () => {
247+
const deadpool: Deadpool = new Deadpool({lifePoints: 500})
248+
const wolverine: Wolverine = new Wolverine({lifePoints: 500})
249+
250+
const superheroFight: SuperheroFight = new SuperheroFight({
251+
superHeroOne: deadpool,
252+
superHeroTwo: wolverine,
253+
})
254+
255+
while (!superheroFight.getWinner()) {
256+
await setTimeout(1000)
257+
const currentTurn: Readonly<Turn> = superheroFight.getTurn()
258+
259+
try {
260+
const executedTurn: Readonly<ExecutedTurn> =
261+
superheroFight.executeTurn()
262+
263+
if (executedTurn.victimAvoidAttack) {
264+
console.log(
265+
`\n> Turn N°${
266+
currentTurn.number
267+
}: ${currentTurn.victim.getName()} avoided ${currentTurn.attacker.getName()} attack.`
268+
)
269+
270+
continue
271+
}
272+
273+
console.log(
274+
`\n> Turn N°${
275+
currentTurn.number
276+
}: ${currentTurn.attacker.getName()} attacked ${currentTurn.victim.getName()} with ${
277+
executedTurn.damageProducedByAttacker
278+
} points of damage.`
279+
)
280+
281+
console.log(
282+
`[ Life points of Deadpool: ${deadpool.getLifePoints()} ]\n` +
283+
`[ Life points of Wolverine: ${wolverine.getLifePoints()} ]`
284+
)
285+
} catch (error) {
286+
if (error instanceof SuperheroRegeneratingError) {
287+
console.log(
288+
`\n> Turn N°${currentTurn.number}: ${error.message}.`
289+
)
290+
}
291+
}
292+
}
293+
294+
console.log(`\n¡The winner is ${superheroFight.getWinner()?.getName()}!`)
295+
})()

0 commit comments

Comments
 (0)