diff --git a/src/homeworks/ts1/1_base.js b/src/homeworks/ts1/1_base.js deleted file mode 100644 index 611b3a92f..000000000 --- a/src/homeworks/ts1/1_base.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Нужно превратить файл в ts и указать типы аргументов и типы возвращаемого значения - * */ -export const removePlus = (string) => string.replace(/^\+/, ''); - -export const addPlus = (string) => `+${string}`; - -export const removeFirstZeros = (value) => value.replace(/^(-)?[0]+(-?\d+.*)$/, '$1$2'); - -export const getBeautifulNumber = (value, separator = ' ') => - value?.toString().replace(/\B(?=(\d{3})+(?!\d))/g, separator); - -export const round = (value, accuracy = 2) => { - const d = 10 ** accuracy; - return Math.round(value * d) / d; -}; - -const transformRegexp = - /(matrix\(-?\d+(\.\d+)?, -?\d+(\.\d+)?, -?\d+(\.\d+)?, -?\d+(\.\d+)?, )(-?\d+(\.\d+)?), (-?\d+(\.\d+)?)\)/; - -export const getTransformFromCss = (transformCssString) => { - const data = transformCssString.match(transformRegexp); - if (!data) return { x: 0, y: 0 }; - return { - x: parseInt(data[6], 10), - y: parseInt(data[8], 10), - }; -}; - -export const getColorContrastValue = ([red, green, blue]) => - // http://www.w3.org/TR/AERT#color-contrast - Math.round((red * 299 + green * 587 + blue * 114) / 1000); - -export const getContrastType = (contrastValue) => (contrastValue > 125 ? 'black' : 'white'); - -export const shortColorRegExp = /^#[0-9a-f]{3}$/i; -export const longColorRegExp = /^#[0-9a-f]{6}$/i; - -export const checkColor = (color) => { - if (!longColorRegExp.test(color) && !shortColorRegExp.test(color)) throw new Error(`invalid hex color: ${color}`); -}; - -export const hex2rgb = (color) => { - checkColor(color); - if (shortColorRegExp.test(color)) { - const red = parseInt(color.substring(1, 2), 16); - const green = parseInt(color.substring(2, 3), 16); - const blue = parseInt(color.substring(3, 4), 16); - return [red, green, blue]; - } - const red = parseInt(color.substring(1, 3), 16); - const green = parseInt(color.substring(3, 5), 16); - const blue = parseInt(color.substring(5, 8), 16); - return [red, green, blue]; -}; - -export const getNumberedArray = (arr) => arr.map((value, number) => ({ value, number })); -export const toStringArray = (arr) => arr.map(({ value, number }) => `${value}_${number}`); - -export const transformCustomers = (customers) => { - return customers.reduce((acc, customer) => { - acc[customer.id] = { name: customer.name, age: customer.age, isSubscribed: customer.isSubscribed }; - return acc; - }, {}); -}; diff --git a/src/homeworks/ts1/1_base.test.js b/src/homeworks/ts1/1_base.test.js index ee68dc16f..dbd708234 100644 --- a/src/homeworks/ts1/1_base.test.js +++ b/src/homeworks/ts1/1_base.test.js @@ -1,26 +1,21 @@ -// Этот блок кода удалить и раскомментировать код ниже -it('remove it', () => { - expect(true).toBe(true); -}); +import { transformCustomers } from './1_base'; + +describe('all', () => { + it('transformCustomers', () => { + const customers = [ + { id: 1, name: 'John', age: 25, isSubscribed: true }, + { id: 2, name: 'Mary', age: 40, isSubscribed: false }, + { id: 3, name: 'Bob', age: 32, isSubscribed: true }, + { id: 4, name: 'Alice', age: 22, isSubscribed: true }, + { id: 5, name: 'David', age: 48, isSubscribed: false }, + ]; -// import { transformCustomers } from './1_base'; -// -// describe('all', () => { -// it('transformCustomers', () => { -// const customers = [ -// { id: 1, name: 'John', age: 25, isSubscribed: true }, -// { id: 2, name: 'Mary', age: 40, isSubscribed: false }, -// { id: 3, name: 'Bob', age: 32, isSubscribed: true }, -// { id: 4, name: 'Alice', age: 22, isSubscribed: true }, -// { id: 5, name: 'David', age: 48, isSubscribed: false }, -// ]; -// -// expect(transformCustomers(customers)).toEqual({ -// 1: { name: 'John', age: 25, isSubscribed: true }, -// 2: { name: 'Mary', age: 40, isSubscribed: false }, -// 3: { name: 'Bob', age: 32, isSubscribed: true }, -// 4: { name: 'Alice', age: 22, isSubscribed: true }, -// 5: { name: 'David', age: 48, isSubscribed: false }, -// }); -// }); -// }); + expect(transformCustomers(customers)).toEqual({ + 1: { name: 'John', age: 25, isSubscribed: true }, + 2: { name: 'Mary', age: 40, isSubscribed: false }, + 3: { name: 'Bob', age: 32, isSubscribed: true }, + 4: { name: 'Alice', age: 22, isSubscribed: true }, + 5: { name: 'David', age: 48, isSubscribed: false }, + }); + }); +}); diff --git a/src/homeworks/ts1/1_base.ts b/src/homeworks/ts1/1_base.ts new file mode 100644 index 000000000..a8f255f5e --- /dev/null +++ b/src/homeworks/ts1/1_base.ts @@ -0,0 +1,91 @@ +/** + * Нужно превратить файл в ts и указать типы аргументов и типы возвращаемого значения + * */ +export const removePlus = (string: string): string => string.replace(/^\+/, ''); + +export const addPlus = (string: string): string => `+${string}`; + +export const removeFirstZeros = (value: string): string => value.replace(/^(-)?[0]+(-?\d+.*)$/, '$1$2'); + +export const getBeautifulNumber = (value: number, separator = ' '): string => + value?.toString().replace(/\B(?=(\d{3})+(?!\d))/g, separator); + +export const round = (value: number, accuracy = 2): number => { + const d = 10 ** accuracy; + return Math.round(value * d) / d; +}; + +const transformRegexp = + /(matrix\(-?\d+(\.\d+)?, -?\d+(\.\d+)?, -?\d+(\.\d+)?, -?\d+(\.\d+)?, )(-?\d+(\.\d+)?), (-?\d+(\.\d+)?)\)/; + +//Пробую через type +type Point = { + x: number; + y: number; +}; + +export const getTransformFromCss = (transformCssString: string): Point => { + const data = transformCssString.match(transformRegexp); + if (!data) return { x: 0, y: 0 }; + return { + x: parseInt(data[6], 10), + y: parseInt(data[8], 10), + }; +}; + +//Пробую через interface +interface RgbColor { + red: number; + green: number; + blue: number; +} + +export const getColorContrastValue = (color: RgbColor): number => + // http://www.w3.org/TR/AERT#color-contrast + Math.round((color.red * 299 + color.green * 587 + color.blue * 114) / 1000); + +type BlackOrWhite = 'black' | 'white'; +export const getContrastType = (contrastValue: number): BlackOrWhite => (contrastValue > 125 ? 'black' : 'white'); + +export const shortColorRegExp = /^#[0-9a-f]{3}$/i; +export const longColorRegExp = /^#[0-9a-f]{6}$/i; + +export const checkColor = (color: string) => { + if (!longColorRegExp.test(color) && !shortColorRegExp.test(color)) throw new Error(`invalid hex color: ${color}`); +}; + +export const hex2rgb = (color: string) => { + checkColor(color); + if (shortColorRegExp.test(color)) { + const red = parseInt(color.substring(1, 2), 16); + const green = parseInt(color.substring(2, 3), 16); + const blue = parseInt(color.substring(3, 4), 16); + return [red, green, blue]; + } + const red = parseInt(color.substring(1, 3), 16); + const green = parseInt(color.substring(3, 5), 16); + const blue = parseInt(color.substring(5, 8), 16); + return [red, green, blue]; +}; + +type ValueNumber = { + value: number; + number: number; +}; +export const getNumberedArray = (arr: number[]): ValueNumber[] => arr.map((value, number) => ({ value, number })); +export const toStringArray = (arr: ValueNumber[]): string[] => arr.map(({ value, number }) => `${value}_${number}`); + +interface Person { + name: string; + age: number; + isSubscribed: boolean; +} +interface Customer extends Person { + id: string; +} +export const transformCustomers = (customers: Customer[]): Record => { + return customers.reduce((acc, customer) => { + acc[customer.id] = { name: customer.name, age: customer.age, isSubscribed: customer.isSubscribed }; + return acc; + }, {} as Record); +}; diff --git a/src/homeworks/ts1/2_repair.ts b/src/homeworks/ts1/2_repair.ts index 19e98c068..a1d1f1824 100644 --- a/src/homeworks/ts1/2_repair.ts +++ b/src/homeworks/ts1/2_repair.ts @@ -2,46 +2,55 @@ * Здесь код с ошибками типов. Нужно их устранить * */ -// // Мы это не проходили, но по тексту ошибки можно понять, как это починить -// export const getFakeApi = async (): void => { -// const result = await fetch('https://jsonplaceholder.typicode.com/todos/1').then((response) => response.json()); -// console.log(result); -// }; -// -// // Мы это не проходили, но по тексту ошибки можно понять, как это починить -// export class SomeClass { -// constructor() { -// this.set = new Set([1]); -// this.channel = new BroadcastChannel('test-broadcast-channel'); -// } -// } -// -// export type Data = { -// type: 'Money' | 'Percent'; -// value: DataValue; -// }; -// -// export type DataValue = Money | Percent; -// -// export type Money = { -// currency: string; -// amount: number; -// }; -// -// export type Percent = { -// percent: number; -// }; -// -// // Здесь, возможно, нужно использовать as, возможно в switch передавать немного по-другому -// const getDataAmount = (data: Data): number => { -// switch (data.type) { -// case 'Money': -// return data.value.amount; -// -// default: { -// // eslint-disable-next-line @typescript-eslint/no-unused-vars -// const unhandled: never = data; // здесь, возможно, нужно использовать нечто другое. :never должен остаться -// throw new Error(`unknown type: ${data.type}`); -// } -// } -// }; +// Мы это не проходили, но по тексту ошибки можно понять, как это починить +export const getFakeApi = async (): Promise => { + const result = await fetch('https://jsonplaceholder.typicode.com/todos/1').then((response) => response.json()); + console.log(result); +}; + +// Мы это не проходили, но по тексту ошибки можно понять, как это починить +export class SomeClass { + set: Set; + channel: BroadcastChannel; + constructor() { + this.set = new Set([1]); + this.channel = new BroadcastChannel('test-broadcast-channel'); + } +} + +export enum DataType { + Money, + Percent, +} + +export type Data = { + type: DataType; + value: DataValue; +}; + +export type DataValue = Money | Percent; + +export type Money = { + currency: string; + amount: number; +}; + +export type Percent = { + percent: number; +}; + +// Здесь, возможно, нужно использовать as, возможно в switch передавать немного по-другому +const getDataAmount = (data: Data): number => { + switch (data.type) { + case DataType.Money: + return (data.value as Money).amount; + case DataType.Percent: + return (data.value as Percent).percent; + + default: { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + // const unhandled: never = data; // здесь, возможно, нужно использовать нечто другое. :never должен остаться + throw new Error(`unknown type: ${data.type}`); + } + } +}; diff --git a/src/homeworks/ts1/3_write.test.js b/src/homeworks/ts1/3_write.test.js index 5b5173063..a11ac89c3 100644 --- a/src/homeworks/ts1/3_write.test.js +++ b/src/homeworks/ts1/3_write.test.js @@ -1,35 +1,30 @@ -// Этот блок кода удалить и раскомментировать код ниже -it('remove it', () => { - expect(true).toBe(true); -}); +import { createRandomOperation, createRandomProduct } from './3_write'; + +describe('all', () => { + it('operation', () => { + const createdAt = '2023-06-06T12:06:56.957Z'; + const operation = createRandomOperation(createdAt); + expect(operation).toHaveProperty('createdAt', createdAt); + expect(operation).toHaveProperty('id'); + expect(operation).toHaveProperty('name'); + expect(operation).toHaveProperty('desc'); + expect(operation).toHaveProperty('createdAt'); + expect(operation).toHaveProperty('amount'); + expect(operation).toHaveProperty('category'); + expect(operation).toHaveProperty('type'); + }); -// import { createRandomOperation, createRandomProduct } from './3_write'; -// -// describe('all', () => { -// it('operation', () => { -// const createdAt = '2023-06-06T12:06:56.957Z'; -// const operation = createRandomOperation(createdAt); -// expect(operation).toHaveProperty('createdAt', createdAt); -// expect(operation).toHaveProperty('id'); -// expect(operation).toHaveProperty('name'); -// expect(operation).toHaveProperty('desc'); -// expect(operation).toHaveProperty('createdAt'); -// expect(operation).toHaveProperty('amount'); -// expect(operation).toHaveProperty('category'); -// expect(operation).toHaveProperty('type'); -// }); -// -// it('product', () => { -// const createdAt = '2023-06-06T12:06:56.957Z'; -// const product = createRandomProduct(createdAt); -// expect(product).toHaveProperty('createdAt', createdAt); -// expect(product).toHaveProperty('id'); -// expect(product).toHaveProperty('name'); -// expect(product).toHaveProperty('photo'); -// expect(product).toHaveProperty('desc'); -// expect(product).toHaveProperty('createdAt'); -// expect(product).toHaveProperty('oldPrice'); -// expect(product).toHaveProperty('price'); -// expect(product).toHaveProperty('category'); -// }); -// }); + it('product', () => { + const createdAt = '2023-06-06T12:06:56.957Z'; + const product = createRandomProduct(createdAt); + expect(product).toHaveProperty('createdAt', createdAt); + expect(product).toHaveProperty('id'); + expect(product).toHaveProperty('name'); + expect(product).toHaveProperty('photo'); + expect(product).toHaveProperty('desc'); + expect(product).toHaveProperty('createdAt'); + expect(product).toHaveProperty('oldPrice'); + expect(product).toHaveProperty('price'); + expect(product).toHaveProperty('category'); + }); +}); diff --git a/src/homeworks/ts1/3_write.ts b/src/homeworks/ts1/3_write.ts index 15f9dcdf2..2687ac675 100644 --- a/src/homeworks/ts1/3_write.ts +++ b/src/homeworks/ts1/3_write.ts @@ -11,7 +11,14 @@ * - id (строка) * - name (строка) * - photo (строка, необязательно) - * + * */ +interface Category { + id: string; + name: string; + photo?: string; +} + +/** * Продукт (Product) содержит * - id (строка) * - name (строка) @@ -21,7 +28,19 @@ * - oldPrice (число, необязательно) * - price (число) * - category (Категория) - * + * */ +interface Product { + id: string; + name: string; + photo: string; + desc?: string; + createdAt: string; + oldPrice?: number; + price: number; + category: Category; +} + +/** * Операция (Operation) может быть либо тратой (Cost), либо доходом (Profit) * * Трата (Cost) содержит @@ -42,15 +61,81 @@ * - category (Категория) * - type ('Profit') * */ - +enum OperationTypes { + Cost = 'Расход', + Profit = 'Доход', +} +interface Operation { + id: string; + name: string; + desc?: string; + createdAt: string; + amount: number; + category: Category; + type: OperationTypes; +} /** * Создает случайный продукт (Product). * Принимает дату создания (строка) * */ -// export const createRandomProduct = (createdAt: string) => {}; +export const createRandomProduct = (createdAt: string): Product => { + const oldPrice = Math.floor(Math.random() * 1000000) / 100; + const category = generateCategory(); + const brand = getRandomElement(brands); + return { + id: generateId(), + name: category.name + ' ' + brand, + photo: '_' + category.name + '_' + brand + '.jpg', + desc: 'Описание для продукта ' + category.name + ' ' + brand, + createdAt: createdAt, + oldPrice: oldPrice, + price: oldPrice * 0.9, + category: category, + }; +}; + +const generateId = (): string => 'id_' + Math.floor(Math.random() * 10000); + +const generateCategory = (): Category => { + const cat = getRandomElement(categories); + return { + id: generateId(), + name: cat, + photo: '_' + cat + '.png', + }; +}; + +const categories = ['Компьютер', 'Ноутбуки', 'Планшет', 'Принтер', 'Cканер', 'Телефон']; +const brands = ['Canon', 'D-Link', 'Samsung', 'Epson', 'Xerox', 'Toshiba', 'HP', 'Apple', 'Intel']; +const getRandomElement = (arr: string[]): string => arr[Math.floor(Math.random() * arr.length)]; /** * Создает случайную операцию (Operation). * Принимает дату создания (строка) * */ -// export const createRandomOperation = (createdAt: string) => {}; +export const createRandomOperation = (createdAt: string): Operation => { + const amount = Math.floor(Math.random() * 1000000) / 100; + const category = generateCategory(); + const type = getRandomOperationType(); + return { + id: generateId(), + name: 'Операция ' + type + 'а по категории ' + category.name, + desc: 'Произведена операция ' + type + 'а по категории ' + category.name + ' на сумму ' + amount, + createdAt: createdAt, + amount: amount, + category: category, + type: type, + }; +}; + +const getRandomOperationType = (): OperationTypes => { + const index = Math.floor(Math.random() * Object.keys(OperationTypes).length); + switch (index) { + case 0: + return OperationTypes.Cost; + case 1: + return OperationTypes.Profit; + default: + new Error(`unknown index: ${index}`); + } +};