Ответ
Модели должны включать:
- Vehicle:
interface Vehicle {
id: string;
type: 'scooter' | 'monowheel';
coordinates: [number, number];
batteryLevel: number;
isAvailable: boolean;
tariff: number; // цена за минуту
}
- ParkingZone:
interface ParkingZone {
id: string;
coordinates: [number, number][]; // полигон зоны
capacity: number;
currentVehicles: number;
}
- UserRide (для истории поездок):
interface UserRide {
id: string;
vehicleId: string;
startTime: Date;
endTime: Date | null;
route: [number, number][];
cost: number;
}
Дополнительно:
- Валидация координат (lat, lng)
- Статусы доступности транспорта
- Текущее местоположение пользователя (если нужно)
- Система рейтингов/отзывов (опционально)
Ответ 18+ 🔞
А, ну это ж классика! Сидишь такой, думаешь: "Щас накидаю модельки для сервиса самокатов, всё будет красиво и тип-безопасно". А потом начинается: "А как, блядь, историю поездок хранить? А как зоны парковки, эти ваши полигоны, на карте рисовать?". Головняк, короче. Но, хуле, разбираемся.
Смотри, вот тебе базовый каркас, с которого можно начинать. Главное — не выебывайся со сложными типами сразу, а то потом сам не разберёшься.
Во-первых, сам транспорт. Тут всё просто, как три копейки. Главное — batteryLevel не забыть, а то пользователь доедет до середины реки и встанет, а потом тебе в поддержку будет писать: "Вы чё, суки, я тут на моноколесе посреди Москвы-реки застрял!". И будет прав, пидарас шерстяной.
interface Vehicle {
id: string; // Уникальный айдишник, чтоб не перепутать
type: 'scooter' | 'monowheel'; // Тип: самокат или моноколесо. Хуй с горы — это не тип, это уже инцидент.
coordinates: [number, number]; // [lat, lng] — где эта хуйня сейчас валяется
batteryLevel: number; // Заряд в процентах. 0% — это уже не транспорт, а хлам на тротуаре.
isAvailable: boolean; // Свободен или уже кто-то на нём укатил в закат
tariff: number; // Цена за минуту в рублях. Чем выше, тем больше у пользователя волнение ебать.
}
Во-вторых, зоны парковки. Вот тут уже интереснее. Нельзя же просто бросить самокат посреди проезжей части, надо в специальную зону. Координаты — это массив точек, который образует полигон. Если пользователь оставит транспорт вне зоны — с него штраф, как с говна пуля.
interface ParkingZone {
id: string;
coordinates: [number, number][]; // Массив точек [lat, lng], которые образуют эту самую зону. Закрытый полигон, блядь!
capacity: number; // Сколько всего транспорта может влезть
currentVehicles: number; // А сколько уже воткнуто. Если currentVehicles >= capacity, то пиши пропало — места нет.
}
В-третьих, история поездок. Это святое. Пользователь всегда захочет посмотреть, на какую сумму он обкатал свои булки за месяц, чтобы офигеть и пообещать больше не ездить. А ещё route — это ж лог всех координат. Полезно, если надо доказать, что он не по тротуару ехал, а по детской площадке. Для этого и пишется.
interface UserRide {
id: string;
vehicleId: string; // На чём катался — ссылка на Vehicle.id
startTime: Date; // Когда сел
endTime: Date | null; // Когда слез. null — значит, ещё едет или забыл завершить. Классика.
route: [number, number][]; // Массив координат [lat, lng] всего маршрута. Тяжёлая штука, может распухнуть.
cost: number; // Итоговая стоимость. Рассчитывается на основе tariff и времени.
}
Ну и по мелочи:
- Валидация координат: Латыш (lat) от -90 до 90, долгота (lng) от -180 до 180. Всё, что за пределами — это уже не Земля, а хуй пойми что.
- Статусы транспорта:
isAvailable— это хорошо, но можно добавитьstatus: 'active' | 'broken' | 'maintenance'. А тоisAvailable = falseможет быть и потому, что его спиздили, и потому, что он на ремонте. - Местоположение пользователя: Для поиска ближайшего транспорта тебе понадобится
userCoordinates: [number, number]. Без этого — как слепой котёнок. - Рейтинги (опционально): К
UserRideможно прикрутитьrating?: 1 | 2 | 3 | 4 | 5иcomment?: string. Чтобы пользователь мог написать: "Самокат — огонь, но в конце поездки отвалилось колесо, 2/5".
Вот, собственно, и вся матчасть. Остальное — это уже бизнес-логика: поиск ближайших самокатов, проверка, что поездка закончена в парковочной зоне, расчёт стоимости... Но это уже совсем другая история, с блэкджеком и багами в прод-окружении. Удачи, не налажай!