Skip to content

Commit bade28f

Browse files
committed
refactor: rewrite with modern standard
1 parent e727eb6 commit bade28f

File tree

2 files changed

+166
-52
lines changed

2 files changed

+166
-52
lines changed

Geometry/Test/Triangle.test.js

Lines changed: 70 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,94 @@
11
import Triangle from '../Triangle'
22

33
describe('Triangle', () => {
4-
describe('Triangle created with sides', () => {
5-
const triangle = new Triangle(3, 4, 5)
4+
describe('Constructor', () => {
5+
test('creates a triangle with base and height', () => {
6+
const triangle = new Triangle(5, 10)
7+
expect(triangle).toBeInstanceOf(Triangle)
8+
expect(triangle.base).toBe(5)
9+
expect(triangle.height).toBe(10)
10+
expect(triangle.sides).toEqual([5, null, null])
11+
})
12+
13+
test('creates a triangle with three sides', () => {
14+
const triangle = new Triangle(3, 4, 5)
15+
expect(triangle).toBeInstanceOf(Triangle)
16+
expect(triangle.sides).toEqual([3, 4, 5])
17+
expect(triangle.base).toBe(3) // Assuming base is one of the sides
18+
expect(triangle.height).toBe(null)
19+
})
620

7-
test('The area of a triangle with sides 3, 4, 5', () => {
8-
expect(parseFloat(triangle.area().toFixed(2))).toEqual(6.0)
21+
test('throws an error if invalid number of arguments', () => {
22+
expect(() => new Triangle()).toThrow(
23+
'Invalid number of arguments. Use either (base, height) or (sideA, sideB, sideC).'
24+
)
25+
expect(() => new Triangle(1)).toThrow(
26+
'Invalid number of arguments. Use either (base, height) or (sideA, sideB, sideC).'
27+
)
928
})
1029

11-
test('The perimeter of a triangle with sides 3, 4, 5', () => {
12-
expect(parseFloat(triangle.perimeter().toFixed(2))).toEqual(12.0)
30+
test('throws an error if the triangle is invalid', () => {
31+
expect(() => new Triangle(1, 2, 3)).toThrow(
32+
'Invalid triangle: The sum of any two sides must be greater than the third side.'
33+
)
1334
})
1435
})
1536

16-
describe('Triangle created with base and height', () => {
17-
const triangle = new Triangle(6, 4)
37+
describe('Area Calculation', () => {
38+
test('calculates area correctly using base and height', () => {
39+
const triangle = new Triangle(5, 10)
40+
expect(triangle.area()).toBe(25)
41+
})
42+
43+
test("calculates area correctly using Heron's formula", () => {
44+
const triangle = new Triangle(3, 4, 5)
45+
expect(triangle.area()).toBe(6) // Area of a 3-4-5 triangle
46+
})
47+
})
1848

19-
test('The area of a triangle with base 6 and height 4', () => {
20-
expect(parseFloat(triangle.area().toFixed(2))).toEqual(12.0)
49+
describe('Perimeter Calculation', () => {
50+
test('calculates perimeter correctly for three sides', () => {
51+
const triangle = new Triangle(3, 4, 5)
52+
expect(triangle.perimeter()).toBe(12) // 3 + 4 + 5
2153
})
2254

23-
test('The perimeter calculation throws an error for base-height triangle', () => {
55+
test('throws an error if not all sides are known', () => {
56+
const triangle = new Triangle(5, 10)
2457
expect(() => triangle.perimeter()).toThrow(
2558
'Cannot calculate perimeter: not all sides are known.'
2659
)
2760
})
2861
})
2962

30-
describe('Invalid triangle creation', () => {
31-
test('Creating a triangle with invalid sides throws an error', () => {
32-
expect(() => new Triangle(1, 1, 10)).toThrow(
33-
'Invalid triangle: The sum of any two sides must be greater than the third side.'
63+
describe('Getters', () => {
64+
test('base getter returns correct value', () => {
65+
const triangle = new Triangle(5, 10)
66+
expect(triangle.base).toBe(5)
67+
})
68+
69+
test('height getter returns correct value', () => {
70+
const triangle = new Triangle(5, 10)
71+
expect(triangle.height).toBe(10)
72+
})
73+
74+
test('sides getter returns correct values', () => {
75+
const triangle = new Triangle(3, 4, 5)
76+
expect(triangle.sides).toEqual([3, 4, 5])
77+
})
78+
})
79+
80+
describe('String Representation', () => {
81+
test('returns correct string representation for base and height', () => {
82+
const triangle = new Triangle(5, 10)
83+
expect(triangle.toString()).toBe(
84+
'Triangle: base = 5, height = 10, sides = 5, unknown, unknown, area = 25, perimeter = unknown'
3485
)
3586
})
3687

37-
test('Creating a triangle with invalid number of arguments throws an error', () => {
38-
expect(() => new Triangle(1)).toThrow(
39-
'Invalid number of arguments. Use either (base, height) or (sideA, sideB, sideC).'
88+
test('returns correct string representation for three sides', () => {
89+
const triangle = new Triangle(3, 4, 5)
90+
expect(triangle.toString()).toBe(
91+
'Triangle: base = 3, height = unknown, sides = 3, 4, 5, area = 6, perimeter = 12'
4092
)
4193
})
4294
})

Geometry/Triangle.js

Lines changed: 96 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,30 @@
11
/**
2-
* This class represents a Triangle and can calculate its area and perimeter with either all three sides or the base and height.
3-
* https://en.wikipedia.org/wiki/Triangle
2+
* Represents a Triangle and provides methods to calculate its area and perimeter
3+
* based on either all three sides or the base and height.
4+
* @see {@link https://en.wikipedia.org/wiki/Triangle|Triangle}
45
* @class
56
*/
67
export default class Triangle {
8+
/** @private */
9+
#base
10+
11+
/** @private */
12+
#height
13+
14+
/** @private */
15+
#sides
16+
717
/**
8-
* Create a triangle.
18+
* Creates a triangle instance.
919
* @constructor
10-
* @param {...number} args - The triangle dimensions.
20+
* @param {...number} args - The dimensions of the triangle.
1121
* @throws {Error} Will throw an error if the number of arguments is invalid or if the triangle is invalid.
1222
*/
1323
constructor(...args) {
1424
if (args.length === 2) {
15-
this.initializeFromBaseAndHeight(...args)
25+
this.#initializeFromBaseAndHeight(...args)
1626
} else if (args.length === 3) {
17-
this.initializeFromSides(...args)
27+
this.#initializeFromSides(...args)
1828
} else {
1929
throw new Error(
2030
'Invalid number of arguments. Use either (base, height) or (sideA, sideB, sideC).'
@@ -23,73 +33,125 @@ export default class Triangle {
2333
}
2434

2535
/**
26-
* Initialize the triangle from base and height.
36+
* Initializes the triangle from base and height.
37+
* @private
2738
* @param {number} base - The base of the triangle.
2839
* @param {number} height - The height of the triangle.
29-
* @private
3040
*/
31-
initializeFromBaseAndHeight = (base, height) => {
32-
this.base = base
33-
this.height = height
34-
this.sides = [base, null, null]
41+
#initializeFromBaseAndHeight(base, height) {
42+
this.#base = base
43+
this.#height = height
44+
this.#sides = [base, null, null]
3545
}
3646

3747
/**
38-
* Initialize the triangle from three sides.
48+
* Initializes the triangle from three sides.
49+
* @private
3950
* @param {number} sideA - The length of side A.
4051
* @param {number} sideB - The length of side B.
4152
* @param {number} sideC - The length of side C.
4253
* @throws {Error} Will throw an error if the triangle is invalid.
43-
* @private
4454
*/
45-
initializeFromSides = (sideA, sideB, sideC) => {
46-
if (!this.isValidTriangle(sideA, sideB, sideC)) {
55+
#initializeFromSides(sideA, sideB, sideC) {
56+
if (!this.#isValidTriangle(sideA, sideB, sideC)) {
4757
throw new Error(
4858
'Invalid triangle: The sum of any two sides must be greater than the third side.'
4959
)
5060
}
51-
this.sides = [sideA, sideB, sideC]
52-
this.base = sideA
53-
this.height = null
61+
this.#sides = [sideA, sideB, sideC]
62+
this.#base = sideA // Assuming base is one of the sides for consistency
63+
this.#height = null
5464
}
5565

5666
/**
57-
* Check if three sides can form a valid triangle.
67+
* Checks if three sides can form a valid triangle.
68+
* @private
5869
* @param {number} a - The length of side A.
5970
* @param {number} b - The length of side B.
6071
* @param {number} c - The length of side C.
61-
* @returns {boolean} True if the triangle is valid, false otherwise.
62-
* @private
72+
* @returns {boolean} True if the triangle is valid; false otherwise.
6373
*/
64-
isValidTriangle = (a, b, c) => {
74+
#isValidTriangle(a, b, c) {
6575
return a + b > c && b + c > a && c + a > b
6676
}
6777

6878
/**
69-
* Calculate the area of the triangle.
70-
* @returns {number} The area of the triangle.
79+
* Calculates the area of the triangle.
7180
* @public
81+
* @returns {number} The area of the triangle.
7282
*/
73-
area = () => {
74-
if (this.height !== null) {
75-
return 0.5 * this.base * this.height
83+
area() {
84+
if (this.#height !== null) {
85+
return 0.5 * this.#base * this.#height
7686
}
7787
// Using Heron's formula
78-
const [a, b, c] = this.sides
88+
const [a, b, c] = this.#sides
7989
const s = (a + b + c) / 2
8090
return Math.sqrt(s * (s - a) * (s - b) * (s - c))
8191
}
8292

8393
/**
84-
* Calculate the perimeter of the triangle.
94+
* Calculates the perimeter of the triangle.
95+
* @public
8596
* @returns {number} The perimeter of the triangle.
8697
* @throws {Error} Will throw an error if not all sides are known.
87-
* @public
8898
*/
89-
perimeter = () => {
90-
if (this.sides.some((side) => side === null)) {
99+
perimeter() {
100+
if (this.#sides.some((side) => side === null)) {
91101
throw new Error('Cannot calculate perimeter: not all sides are known.')
92102
}
93-
return this.sides.reduce((sum, side) => sum + side, 0)
103+
return this.#sides.reduce((sum, side) => sum + side, 0)
104+
}
105+
106+
/**
107+
* Returns a string representation of the triangle.
108+
* @public
109+
* @returns {string} A string describing the triangle's dimensions and area/perimeter.
110+
*/
111+
toString() {
112+
const areaValue = this.area()
113+
let perimeterValue
114+
115+
// Check if all sides are known for perimeter calculation
116+
if (this.#sides.some((side) => side === null)) {
117+
perimeterValue = 'unknown'
118+
} else {
119+
perimeterValue = this.perimeter()
120+
}
121+
122+
return (
123+
`Triangle: base = ${this.#base}, height = ${
124+
this.#height ?? 'unknown'
125+
}, ` +
126+
`sides = ${this.#sides.map((side) => side ?? 'unknown').join(', ')}, ` +
127+
`area = ${areaValue}, perimeter = ${perimeterValue}`
128+
)
129+
}
130+
131+
/**
132+
* Gets the base of the triangle.
133+
* @public
134+
* @returns {number} The base of the triangle.
135+
*/
136+
get base() {
137+
return this.#base
138+
}
139+
140+
/**
141+
* Gets the height of the triangle.
142+
* @public
143+
* @returns {number|null} The height of the triangle or null if not defined.
144+
*/
145+
get height() {
146+
return this.#height
147+
}
148+
149+
/**
150+
* Gets the lengths of all sides of the triangle.
151+
* @public
152+
* @returns {Array<number|null>} An array containing lengths of all three sides or null for unknown sides.
153+
*/
154+
get sides() {
155+
return this.#sides
94156
}
95157
}

0 commit comments

Comments
 (0)