From 2bdde17502ed5b790b87f6c05a4414ddb4a3418d Mon Sep 17 00:00:00 2001 From: Talgat Date: Tue, 17 Oct 2023 12:48:36 +0600 Subject: [PATCH] add exercise4 --- exercise4/problem1/README.md | 14 +++++ exercise4/problem1/index.test.ts | 37 +++++++++++++ exercise4/problem1/index.ts | 3 ++ exercise4/problem2/README.md | 19 +++++++ exercise4/problem2/index.test.ts | 33 ++++++++++++ exercise4/problem2/index.ts | 3 ++ exercise4/problem3/README.md | 15 ++++++ exercise4/problem3/index.test.ts | 50 +++++++++++++++++ exercise4/problem3/index.ts | 8 +++ exercise4/problem4/README.md | 17 ++++++ exercise4/problem4/index.test.ts | 47 ++++++++++++++++ exercise4/problem4/index.ts | 8 +++ exercise4/problem5/README.md | 22 ++++++++ exercise4/problem5/index.test.ts | 62 +++++++++++++++++++++ exercise4/problem5/index.ts | 3 ++ exercise4/problem6/README.md | 27 ++++++++++ exercise4/problem6/index.test.ts | 7 +++ exercise4/problem6/index.ts | 19 +++++++ exercise4/problem7/README.md | 17 ++++++ exercise4/problem7/index.test.ts | 74 +++++++++++++++++++++++++ exercise4/problem7/index.ts | 3 ++ exercise4/problem8/README.md | 16 ++++++ exercise4/problem8/index.test.ts | 93 ++++++++++++++++++++++++++++++++ exercise4/problem8/index.ts | 3 ++ 24 files changed, 600 insertions(+) create mode 100644 exercise4/problem1/README.md create mode 100644 exercise4/problem1/index.test.ts create mode 100644 exercise4/problem1/index.ts create mode 100644 exercise4/problem2/README.md create mode 100644 exercise4/problem2/index.test.ts create mode 100644 exercise4/problem2/index.ts create mode 100644 exercise4/problem3/README.md create mode 100644 exercise4/problem3/index.test.ts create mode 100644 exercise4/problem3/index.ts create mode 100644 exercise4/problem4/README.md create mode 100644 exercise4/problem4/index.test.ts create mode 100644 exercise4/problem4/index.ts create mode 100644 exercise4/problem5/README.md create mode 100644 exercise4/problem5/index.test.ts create mode 100644 exercise4/problem5/index.ts create mode 100644 exercise4/problem6/README.md create mode 100644 exercise4/problem6/index.test.ts create mode 100644 exercise4/problem6/index.ts create mode 100644 exercise4/problem7/README.md create mode 100644 exercise4/problem7/index.test.ts create mode 100644 exercise4/problem7/index.ts create mode 100644 exercise4/problem8/README.md create mode 100644 exercise4/problem8/index.test.ts create mode 100644 exercise4/problem8/index.ts diff --git a/exercise4/problem1/README.md b/exercise4/problem1/README.md new file mode 100644 index 0000000..cecf3ca --- /dev/null +++ b/exercise4/problem1/README.md @@ -0,0 +1,14 @@ +# Problem 1 + +Create a method in the `Person` class which returns how another person's age compares. Format is **{other person name} +is {older than / younger than / the same age as} me.** + +```ts +const p1 = Person("Samuel", 24) +const p2 = Person("Joel", 36) +const p3 = Person("Lily", 24) + +p1.compareAge(p2) // "Joel is older than me." +p2.compareAge(p1) // "Samuel is younger than me." +p1.compareAge(p3) // "Lily is the same age as me." +``` \ No newline at end of file diff --git a/exercise4/problem1/index.test.ts b/exercise4/problem1/index.test.ts new file mode 100644 index 0000000..6454c78 --- /dev/null +++ b/exercise4/problem1/index.test.ts @@ -0,0 +1,37 @@ +import { describe, expect, test } from "vitest"; +import Person from "./index"; + +describe("exercise4 - problem1", () => { + const p1 = new Person("Samuel", 24); + const p2 = new Person("Joel", 36); + const p3 = new Person("Lily", 24); + + test.each([ + { + output: p1.compareAge(p2), + expected: "Joel is older than me.", + }, + { + output: p1.compareAge(p3), + expected: "Lily is the same age as me.", + }, + { + output: p2.compareAge(p1), + expected: "Samuel is younger than me.", + }, + { + output: p2.compareAge(p3), + expected: "Lily is younger than me.", + }, + { + output: p3.compareAge(p1), + expected: "Samuel is the same age as me.", + }, + { + output: p3.compareAge(p2), + expected: "Joel is older than me.", + }, + ])(".compareAge", ({ output, expected }) => { + expect(output).toBe(expected); + }); +}); diff --git a/exercise4/problem1/index.ts b/exercise4/problem1/index.ts new file mode 100644 index 0000000..030be96 --- /dev/null +++ b/exercise4/problem1/index.ts @@ -0,0 +1,3 @@ +class Person {} + +export default Person; diff --git a/exercise4/problem2/README.md b/exercise4/problem2/README.md new file mode 100644 index 0000000..9376a15 --- /dev/null +++ b/exercise4/problem2/README.md @@ -0,0 +1,19 @@ +# Problem 2 + +Write a class called `Name` and create the following attributes given a first name and last name (as `firstName` +and `lastName`): + +* An attribute called `fullName` which returns the first and last names. +* An attribute called `initials` which returns the first letters of the first and last name. Put a `.` between the two + letters. + +Remember to allow the attributes `firstName` and `lastName` to be accessed individually as well. + +```ts +const p1 = new Name("john", "SMITH") + +p1.firstName // "John" +p1.lastName // "Smith" +p1.fullName // "John Smith" +p1.initials // "J.S" +``` \ No newline at end of file diff --git a/exercise4/problem2/index.test.ts b/exercise4/problem2/index.test.ts new file mode 100644 index 0000000..69d599e --- /dev/null +++ b/exercise4/problem2/index.test.ts @@ -0,0 +1,33 @@ +import { describe, expect, test } from "vitest"; +import Name from "./index"; + +describe("exercise4 - problem2", () => { + test.each([ + { + firstName: "john", + lastName: "SMITH", + expected: { + firstName: "John", + lastName: "Smith", + fullName: "John Smith", + initials: "J.S", + }, + }, + { + firstName: "sARah", + lastName: "SMITH", + expected: { + firstName: "John", + lastName: "Smith", + fullName: "John Smith", + initials: "J.S", + }, + }, + ])(".Name", ({ firstName, lastName, expected }) => { + const person = new Name(firstName, lastName); + expect(person.firstName).toBe(expected.firstName); + expect(person.lastName).toBe(expected.lastName); + expect(person.fullName).toBe(expected.fullName); + expect(person.initials).toBe(expected.initials); + }); +}); diff --git a/exercise4/problem2/index.ts b/exercise4/problem2/index.ts new file mode 100644 index 0000000..dc59f55 --- /dev/null +++ b/exercise4/problem2/index.ts @@ -0,0 +1,3 @@ +class Name {} + +export default Name; diff --git a/exercise4/problem3/README.md b/exercise4/problem3/README.md new file mode 100644 index 0000000..07974ca --- /dev/null +++ b/exercise4/problem3/README.md @@ -0,0 +1,15 @@ +# Problem 3 + +**Inheritance** + +Complete `class`: `Rectangle` and `Circle` and combine it in order to calculate sum of all areas. _Do it in OOP way_. + +```ts +const circle1 = new Circle(2); +const circle2 = new Circle(3); +const rect1 = new Rectangle(2, 4); +const rect2 = new Rectangle(3, 2); + +console.log(sumOfAllAreas(circle1, circle2)) // ~ 40. ... +console.log(sumOfAllAreas(circle1, rect1)) // ~ 20. ... +``` \ No newline at end of file diff --git a/exercise4/problem3/index.test.ts b/exercise4/problem3/index.test.ts new file mode 100644 index 0000000..babdb9c --- /dev/null +++ b/exercise4/problem3/index.test.ts @@ -0,0 +1,50 @@ +import { describe, expect, test } from "vitest"; +import { Circle, Rectangle, sumOfAllAreas } from "./index"; + +describe("exercise4 - problem3", () => { + test("inherits from the same parent", () => { + const circle = new Circle(2); + const rect = new Rectangle(3, 2); + + expect(Object.getPrototypeOf(circle.constructor).name).not.toBe(""); + expect(Object.getPrototypeOf(rect.constructor).name).not.toBe(""); + expect(Object.getPrototypeOf(circle.constructor).name).toBe( + Object.getPrototypeOf(rect.constructor).name + ); + }); + + describe("find sum of all areas", () => { + const circle1 = new Circle(2); + const circle2 = new Circle(3); + const rect1 = new Rectangle(2, 4); + const rect2 = new Rectangle(3, 2); + + test.each([ + { + shapes: [circle1, circle2], + expected: 40, + }, + { + shapes: [rect1, rect2], + expected: 14, + }, + { + shapes: [circle1, rect1], + expected: 20, + }, + { + shapes: [circle1, rect2, circle2], + expected: 46, + }, + { + shapes: [rect1, circle1, rect2, circle2], + expected: 54, + }, + ])( + "Math.floor(sumOfAllAreas($shapes)) -> ~$expected", + ({ shapes, expected }) => { + expect(Math.floor(sumOfAllAreas(...shapes))).toBe(expected); + } + ); + }); +}); diff --git a/exercise4/problem3/index.ts b/exercise4/problem3/index.ts new file mode 100644 index 0000000..377d2ec --- /dev/null +++ b/exercise4/problem3/index.ts @@ -0,0 +1,8 @@ +// Update it as much as you want, just don't change the name +export class Circle {} + +// Update it as much as you want, just don't change the name +export class Rectangle {} + +// Update it as much as you want, just don't change the name +export function sumOfAllAreas() {} diff --git a/exercise4/problem4/README.md b/exercise4/problem4/README.md new file mode 100644 index 0000000..b7ea6dd --- /dev/null +++ b/exercise4/problem4/README.md @@ -0,0 +1,17 @@ +# Problem 4 + +The same as problem 3, but in FP style. + +Complete `class`: `Rectangle` and `Circle` and combine it in order to calculate sum of all areas. _Do it in FP way_. + +```ts +const circle1 = new Circle(2); +const circle2 = new Circle(3); +const rect1 = new Rectangle(2, 4); +const rect2 = new Rectangle(3, 2); + +console.log(sumOfAllAreas(circle1, circle2)) // ~ 40. ... +console.log(sumOfAllAreas(circle1, rect1)) // ~ 20. ... +``` + +**HINT**: use `interface` instead of `inheritance`. \ No newline at end of file diff --git a/exercise4/problem4/index.test.ts b/exercise4/problem4/index.test.ts new file mode 100644 index 0000000..0188d78 --- /dev/null +++ b/exercise4/problem4/index.test.ts @@ -0,0 +1,47 @@ +import { describe, expect, test } from "vitest"; +import { Circle, Rectangle, sumOfAllAreas } from "./index"; + +describe("exercise4 - problem4", () => { + test("DOES NOT inherits", () => { + const circle = new Circle(2); + const rect = new Rectangle(3, 2); + + expect(Object.getPrototypeOf(circle.constructor).name).toBe(""); + expect(Object.getPrototypeOf(rect.constructor).name).toBe(""); + }); + + describe("find sum of all areas", () => { + const circle1 = new Circle(2); + const circle2 = new Circle(3); + const rect1 = new Rectangle(2, 4); + const rect2 = new Rectangle(3, 2); + + test.each([ + { + shapes: [circle1, circle2], + expected: 40, + }, + { + shapes: [rect1, rect2], + expected: 14, + }, + { + shapes: [circle1, rect1], + expected: 20, + }, + { + shapes: [circle1, rect2, circle2], + expected: 46, + }, + { + shapes: [rect1, circle1, rect2, circle2], + expected: 54, + }, + ])( + "Math.floor(sumOfAllAreas($shapes)) -> ~$expected", + ({ shapes, expected }) => { + expect(Math.floor(sumOfAllAreas(...shapes))).toBe(expected); + } + ); + }); +}); diff --git a/exercise4/problem4/index.ts b/exercise4/problem4/index.ts new file mode 100644 index 0000000..377d2ec --- /dev/null +++ b/exercise4/problem4/index.ts @@ -0,0 +1,8 @@ +// Update it as much as you want, just don't change the name +export class Circle {} + +// Update it as much as you want, just don't change the name +export class Rectangle {} + +// Update it as much as you want, just don't change the name +export function sumOfAllAreas() {} diff --git a/exercise4/problem5/README.md b/exercise4/problem5/README.md new file mode 100644 index 0000000..a5c35de --- /dev/null +++ b/exercise4/problem5/README.md @@ -0,0 +1,22 @@ +# Problem 5 + +**Encapsulation** + +Complete `class`: `BankAccount`. With only 2 public methods, no public properties: + +1. `withdraw`: Withdraws money from balance. But only if amount does exceed balance. Return balance in success, + otherwise `-1` +2. `deposit`: Deposits money to balance. But only if amount does exceed `1_000_000`. Return balance in success, + otherwise `-1` + +_Do it in OOP way_. + +```ts +const account = new BankAccount(); + +console.log(account.withdraw(100)) // -1 +console.log(account.deposit(100)) // 100 +console.log(account.withdraw(10)) // 90 +console.log(account.deposit(10_000_000)) // -1 +console.log(account.withdraw(10)) // 80 +``` \ No newline at end of file diff --git a/exercise4/problem5/index.test.ts b/exercise4/problem5/index.test.ts new file mode 100644 index 0000000..59a003d --- /dev/null +++ b/exercise4/problem5/index.test.ts @@ -0,0 +1,62 @@ +import { describe, expect, test } from "vitest"; +import BankAccount from "./index"; + +describe("exercise4 - problem5", () => { + test("should deposit to balance", () => { + const account = new BankAccount(); + + account.deposit(300); + + expect(account.deposit(3000)).toBe(3300); + }); + + test("should withdraw balance", () => { + const account = new BankAccount(); + + account.deposit(200); + + expect(account.withdraw(100)).toBe(100); + }); + + test("should deposit and withdraw several times", () => { + const account = new BankAccount(); + + account.deposit(200); + account.withdraw(100); + account.withdraw(50); + account.deposit(100); + + expect(account.withdraw(50)).toBe(200 - 100 - 50 + 100 - 50); + }); + + test("should deposit only if not greater than 1 000 000", () => { + const account = new BankAccount(); + + expect(account.deposit(1_000_000)).toBe(1_000_000); + expect(account.deposit(1_000_001)).toBe(-1); + expect(account.deposit(2_000_000)).toBe(-1); + expect(account.withdraw(100_000)).toBe(900_000); + }); + + test("should withdraw only if has sufficient funds", () => { + const account = new BankAccount(); + + account.deposit(1_000_000); + + expect(account.withdraw(1_000_000)).toBe(0); + expect(account.withdraw(1_000_000)).toBe(-1); + expect(account.withdraw(1)).toBe(-1); + expect(account.deposit(1)).toBe(1); + }); + + test("should only have 2 public methods: withdraw, deposit; 0 public properties", () => { + const account = new BankAccount(); + + expect(Object.getOwnPropertyNames(Object.getPrototypeOf(account))).toEqual([ + "constructor", + "withdraw", + "deposit", + ]); + expect(Object.getOwnPropertyNames(account)).toEqual([]); + }); +}); diff --git a/exercise4/problem5/index.ts b/exercise4/problem5/index.ts new file mode 100644 index 0000000..2577d93 --- /dev/null +++ b/exercise4/problem5/index.ts @@ -0,0 +1,3 @@ +class BankAccount {} + +export default BankAccount; diff --git a/exercise4/problem6/README.md b/exercise4/problem6/README.md new file mode 100644 index 0000000..4b14666 --- /dev/null +++ b/exercise4/problem6/README.md @@ -0,0 +1,27 @@ +# Problem 6 + +Take `BankAccount` from previous problem. And create 2 new: `FedexAccount` and `KazPostAccount` + +1. `FedexAccount`: has 2 public methods `sendMail(recipient)` and `recieveMail(sender)`. Just use `console.log` with any + random text within the body. +2. `KazPostAccount`: has all public methods of `BankAccount` and `FedexAccount`. + +Task: + +* function `withdrawMoney` should only accept `BankAccount` and `KazPostAccount` instances. **HINT** only forbidden by + typescript +* function `sendLetterTo` should only accept `FedexAccount` and `KazPostAccount` instances. **HINT** only forbidden by + typescript + +```ts +const normanOsborne = new BankAccount(); +const peterParker = new FedexAccount(); +const auntMay = new KazPostAccount(); + +withdrawMoney([normanOsborne, auntMay], 10); // no error +sendLetterTo([peterParker, auntMay], "Mary Jane"); // no error + +withdrawMoney([peterParker, auntMay], 10); // peterParker error +``` + +**NOTE**: no tests because it is more about types and structure than implementation. But please do not ignore this task. \ No newline at end of file diff --git a/exercise4/problem6/index.test.ts b/exercise4/problem6/index.test.ts new file mode 100644 index 0000000..d8fbfbe --- /dev/null +++ b/exercise4/problem6/index.test.ts @@ -0,0 +1,7 @@ +import { describe, expect, test } from "vitest"; + +describe("exercise4 - problem6", () => { + test("always true", () => { + expect(true).toBe(true); + }); +}); diff --git a/exercise4/problem6/index.ts b/exercise4/problem6/index.ts new file mode 100644 index 0000000..dc55253 --- /dev/null +++ b/exercise4/problem6/index.ts @@ -0,0 +1,19 @@ +// Update it as much as you want, just don't change the names + +export class BankAccount {} + +export class FedexAccount {} + +export class KazPostAccount {} + +export function withdrawMoney(accounts, amount) { + for (const account of accounts) { + account.withdraw(amount); + } +} + +export function sendLetterTo(accounts, recipient) { + for (const account of accounts) { + account.sendMail(recipient); + } +} diff --git a/exercise4/problem7/README.md b/exercise4/problem7/README.md new file mode 100644 index 0000000..7109c04 --- /dev/null +++ b/exercise4/problem7/README.md @@ -0,0 +1,17 @@ +# Problem 7 + +Create `is` which will check values validity. + +* `is.bool` - checks if value is `boolean` +* `is.num`: checks if value is `number` +* `is.str` - checks if value is `string` +* `is.fun` - checks if value is `function` + +```ts +is.bool(true) // true +is.fun(() => { +}); //true +is.fun({}); //false + +is.num(NaN); //true +``` diff --git a/exercise4/problem7/index.test.ts b/exercise4/problem7/index.test.ts new file mode 100644 index 0000000..d013439 --- /dev/null +++ b/exercise4/problem7/index.test.ts @@ -0,0 +1,74 @@ +import { describe, expect, test } from "vitest"; +import is from "./index"; + +describe("exercise4 - problem7", () => { + test.each([ + { + method: "bool", + arg: true, + expected: true, + }, + { + method: "bool", + arg: false, + expected: true, + }, + { + method: "bool", + arg: "false", + expected: false, + }, + { + method: "num", + arg: 20, + expected: true, + }, + { + method: "num", + arg: NaN, + expected: true, + }, + { + method: "num", + arg: {}, + expected: false, + }, + { + method: "str", + arg: "Hello", + expected: true, + }, + { + method: "str", + arg: "", + expected: true, + }, + { + method: "str", + arg: 42, + expected: false, + }, + { + method: "fun", + arg: () => {}, + expected: true, + }, + { + method: "fun", + arg: function () {}, + expected: true, + }, + { + method: "fun", + arg: Date, + expected: true, + }, + { + method: "fun", + arg: true, + expected: false, + }, + ])('.is["$method"]($arg) -> expected', ({ method, arg, expected }) => { + expect(is[method](arg)).toBe(expected); + }); +}); diff --git a/exercise4/problem7/index.ts b/exercise4/problem7/index.ts new file mode 100644 index 0000000..81e95a0 --- /dev/null +++ b/exercise4/problem7/index.ts @@ -0,0 +1,3 @@ +const is; + +export default is; diff --git a/exercise4/problem8/README.md b/exercise4/problem8/README.md new file mode 100644 index 0000000..053312d --- /dev/null +++ b/exercise4/problem8/README.md @@ -0,0 +1,16 @@ +# Problem 8 + +Create `Calculator` with initial value. And create several methods: `add`, `subtract`, `divide`, `multiply` +and `logResult` + +```ts +const calc = new Calculator(10); + +calc + .add(10) + .subtract(5) + .divide(5) + .multiply(3) + .logResult() // logs: 9 + .add(2) +``` diff --git a/exercise4/problem8/index.test.ts b/exercise4/problem8/index.test.ts new file mode 100644 index 0000000..a8c0a38 --- /dev/null +++ b/exercise4/problem8/index.test.ts @@ -0,0 +1,93 @@ +import { describe, expect, test, vi } from "vitest"; +import Calculator from "./index"; + +type Call = + | { + method: "logResult"; + log: number; + } + | { + method: "add" | "subtract" | "multiply" | "divide"; + arg: number; + }; + +describe("exercise4 - problem8", () => { + const cases: { first: number; calls: Call[] }[] = [ + { + first: 10, + calls: [ + { + method: "add", + arg: 10, + }, + { + method: "subtract", + arg: 5, + }, + { + method: "divide", + arg: 5, + }, + { + method: "multiply", + arg: 3, + }, + { + method: "logResult", + log: 9, + }, + { + method: "add", + arg: 2, + }, + ], + }, + { + first: 2, + calls: [ + { + method: "add", + arg: 12, + }, + { + method: "subtract", + arg: 6, + }, + { + method: "divide", + arg: 2, + }, + { + method: "multiply", + arg: 1, + }, + { + method: "logResult", + log: 4, + }, + { + method: "subtract", + arg: 2, + }, + { + method: "logResult", + log: 2, + }, + ], + }, + ]; + + test.each(cases)(".calc($first)", ({ first, calls }) => { + const consoleLogMock = vi.spyOn(console, "log"); + const calc = new Calculator(first); + + for (const call of calls) { + if (call.method != "logResult") { + calc[call.method](call.arg); + } else { + calc[call.method](); + expect(consoleLogMock).toHaveBeenCalledWith(call.log); + } + } + }); +}); diff --git a/exercise4/problem8/index.ts b/exercise4/problem8/index.ts new file mode 100644 index 0000000..b69fa2a --- /dev/null +++ b/exercise4/problem8/index.ts @@ -0,0 +1,3 @@ +class Calculator {} + +export default Calculator;