Skip to content

Commit

Permalink
feat: add geometry trapezoid
Browse files Browse the repository at this point in the history
  • Loading branch information
saahil-mahato committed Oct 1, 2024
1 parent 9010481 commit dfded06
Show file tree
Hide file tree
Showing 2 changed files with 234 additions and 0 deletions.
93 changes: 93 additions & 0 deletions Geometry/Test/Trapezoid.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import Trapezoid from '../Trapezoid'

describe('Trapezoid', () => {
describe('Constructor', () => {
test('creates a trapezoid with valid dimensions', () => {
const trapezoid = new Trapezoid(5, 10, 7)
expect(trapezoid).toBeInstanceOf(Trapezoid)
expect(trapezoid.base1).toBe(5)
expect(trapezoid.base2).toBe(10)
expect(trapezoid.height).toBe(7)
expect(trapezoid.sides).toEqual([null, null])
})

test('creates a trapezoid with all sides known', () => {
const trapezoid = new Trapezoid(5, 10, 7, 3, 4)
expect(trapezoid.sides).toEqual([3, 4])
})

test('throws an error if any dimension is invalid', () => {
expect(() => new Trapezoid(-5, 10, 7)).toThrow(
'base1 must be a positive number.'
)
expect(() => new Trapezoid(5, -10, -7)).toThrow(
'base2 must be a positive number.'
)
expect(() => new Trapezoid(5, NaN, 7)).toThrow(
'base2 must be a positive number.'
)
expect(() => new Trapezoid(5, 10, -7)).toThrow(
'height must be a positive number.'
)
})
})

describe('Area Calculation', () => {
test('calculates area correctly', () => {
const trapezoid = new Trapezoid(5, 10, 7)
expect(trapezoid.area()).toBe(52.5) // Area = ((5 + 10) / 2) * 7
})
})

describe('Perimeter Calculation', () => {
test('calculates perimeter correctly when all sides are known', () => {
const trapezoid = new Trapezoid(5, 10, 7, 3, 4)
expect(trapezoid.perimeter()).toBe(22) // Perimeter = base1 + base2 + sideA + sideB
})

test('throws an error if not all sides are known', () => {
const trapezoid = new Trapezoid(5, 10, 7)
expect(() => trapezoid.perimeter()).toThrow(
'Cannot calculate perimeter: not all sides are known.'
)
})
})

describe('Getters', () => {
test('base1 getter returns correct value', () => {
const trapezoid = new Trapezoid(5, 10, 7)
expect(trapezoid.base1).toBe(5)
})

test('base2 getter returns correct value', () => {
const trapezoid = new Trapezoid(5, 10, 7)
expect(trapezoid.base2).toBe(10)
})

test('height getter returns correct value', () => {
const trapezoid = new Trapezoid(5, 10, 7)
expect(trapezoid.height).toBe(7)
})

test('sides getter returns correct values', () => {
const trapezoid = new Trapezoid(5, 10, 7, 3, 4)
expect(trapezoid.sides).toEqual([3, 4])
})
})

describe('String Representation', () => {
test('returns correct string representation when sides are unknown', () => {
const trapezoid = new Trapezoid(5, 10, 7)
expect(trapezoid.toString()).toBe(
'Trapezoid: base1 = 5, base2 = 10, height = 7, sideA = unknown, sideB = unknown, area = 52.5, perimeter = unknown'
)
})

test('returns correct string representation when all sides are known', () => {
const trapezoid = new Trapezoid(5, 10, 7, 3, 4)
expect(trapezoid.toString()).toBe(
'Trapezoid: base1 = 5, base2 = 10, height = 7, sideA = 3, sideB = 4, area = 52.5, perimeter = 22'
)
})
})
})
141 changes: 141 additions & 0 deletions Geometry/Trapezoid.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/**
* This class represents a Trapezoid and provides methods to calculate its area and perimeter.
* @see {@link https://en.wikipedia.org/wiki/Trapezoid|Trapezoid}
* @class
*/
export default class Trapezoid {
/** @private */
#base1

/** @private */
#base2

/** @private */
#height

/** @private */
#sideA

/** @private */
#sideB

/**
* Creates a trapezoid instance.
* @constructor
* @param {number} base1 - The length of the first base.
* @param {number} base2 - The length of the second base.
* @param {number} height - The height of the trapezoid.
* @param {number} [sideA] - The length of side A (optional).
* @param {number} [sideB] - The length of side B (optional).
* @throws {Error} Will throw an error if any dimension is invalid.
*/
constructor(base1, base2, height, sideA = null, sideB = null) {
this.#validateDimension(base1, 'base1')
this.#validateDimension(base2, 'base2')
this.#validateDimension(height, 'height')

this.#base1 = base1
this.#base2 = base2
this.#height = height
this.#sideA = sideA
this.#sideB = sideB
}

/**
* Validates that a dimension is a positive number.
* @private
* @param {number} value - The value to validate.
* @param {string} name - The name of the dimension (for error reporting).
* @throws {Error} Will throw an error if the value is not a positive number.
*/
#validateDimension(value, name) {
if (typeof value !== 'number' || isNaN(value) || value <= 0) {
throw new Error(`${name} must be a positive number.`)
}
}

/**
* Calculates the area of the trapezoid.
* @public
* @returns {number} The area of the trapezoid.
*/
area() {
return ((this.#base1 + this.#base2) / 2) * this.#height
}

/**
* Calculates the perimeter of the trapezoid.
* @public
* @returns {number} The perimeter of the trapezoid.
* @throws {Error} Will throw an error if not all sides are known.
*/
perimeter() {
if (this.#sideA === null || this.#sideB === null) {
throw new Error('Cannot calculate perimeter: not all sides are known.')
}
return this.#base1 + this.#base2 + this.#sideA + this.#sideB
}

/**
* Returns a string representation of the trapezoid.
* @public
* @returns {string} A string describing the trapezoid's dimensions and area/perimeter.
*/
toString() {
const areaValue = this.area()
let perimeterValue

// Check if all sides are known for perimeter calculation
if (this.#sideA === null || this.#sideB === null) {
perimeterValue = 'unknown'
} else {
perimeterValue = this.perimeter()
}

return (
`Trapezoid: base1 = ${this.#base1}, base2 = ${this.#base2}, height = ${
this.#height
}, ` +
`sideA = ${this.#sideA ?? 'unknown'}, sideB = ${
this.#sideB ?? 'unknown'
}, ` +
`area = ${areaValue}, perimeter = ${perimeterValue}`
)
}

/**
* Gets the first base of the trapezoid.
* @public
* @returns {number} The first base of the trapezoid.
*/
get base1() {
return this.#base1
}

/**
* Gets the second base of the trapezoid.
* @public
* @returns {number} The second base of the trapezoid.
*/
get base2() {
return this.#base2
}

/**
* Gets the height of the trapezoid.
* @public
* @returns {number} The height of the trapezoid.
*/
get height() {
return this.#height
}

/**
* Gets the lengths of sides A and B of the trapezoid.
* @public
* @returns {Array<number|null>} An array containing lengths of side A and side B or null for unknown sides.
*/
get sides() {
return [this.#sideA, this.#sideB]
}
}

0 comments on commit dfded06

Please sign in to comment.