543 lines
23 KiB
TypeScript
543 lines
23 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
||
import { UsersService } from '../users/users.service';
|
||
import { ReservationsService } from '../reservations/reservations.service';
|
||
import { ReviewsService } from '../reviews/reviews.service';
|
||
import {
|
||
CatalogItemShortDto,
|
||
CatalogItemLongDto,
|
||
} from './dto/catalog-item.dto';
|
||
import { CatalogParamsDto } from './dto/catalog-params.dto';
|
||
import { CatalogResponseDto } from './dto/catalog-response.dto';
|
||
import { MainPageCatalogResponseDto } from './dto/main-page-catalog-response.dto';
|
||
|
||
@Injectable()
|
||
export class CatalogService {
|
||
constructor(
|
||
private readonly usersService: UsersService,
|
||
private readonly reservationsService: ReservationsService,
|
||
private readonly reviewsService: ReviewsService,
|
||
) {}
|
||
|
||
private catalogItems: CatalogItemLongDto[] = [
|
||
{
|
||
id: 1,
|
||
name: 'Азимут 55',
|
||
length: 16.7,
|
||
speed: 32,
|
||
minCost: 85000,
|
||
mainImageUrl: 'api/uploads/1765727362318-238005198.jpg',
|
||
galleryUrls: [
|
||
'api/uploads/1765727362318-238005198.jpg',
|
||
'api/uploads/1765727637471-474231444.webp',
|
||
'api/uploads/1765727743466-187581713.webp',
|
||
'api/uploads/1765727819793-158598111.webp',
|
||
'api/uploads/1765727903961-559930753.webp',
|
||
'api/uploads/1765727928577-55944164.webp',
|
||
'api/uploads/1765727948691-389175954.webp',
|
||
'api/uploads/1765727961591-243584836.webp',
|
||
'api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: true,
|
||
isFeatured: true,
|
||
year: 2022,
|
||
comfortCapacity: 8,
|
||
maxCapacity: 12,
|
||
width: 4.8,
|
||
cabinsCount: 3,
|
||
matherial: 'Стеклопластик',
|
||
power: 1200,
|
||
description:
|
||
'Роскошная моторная яхта Азимут 55 - это воплощение итальянского стиля и российского качества. Идеально подходит для прогулок по Финскому заливу, корпоративных мероприятий и романтических свиданий. На борту: три комфортабельные каюты, просторный салон с панорамным остеклением, полностью оборудованная кухня и две ванные комнаты. Максимальная скорость 32 узла позволяет быстро добраться до самых живописных мест Карельского перешейка.',
|
||
owner: null as any,
|
||
reviews: [],
|
||
reservations: [],
|
||
},
|
||
{
|
||
id: 2,
|
||
name: 'Сансикер Манхэттен 52',
|
||
length: 15.8,
|
||
speed: 34,
|
||
minCost: 92000,
|
||
mainImageUrl: 'api/uploads/1765728068963-634185622.webp',
|
||
galleryUrls: [
|
||
'api/uploads/1765728068963-634185622.webp',
|
||
'api/uploads/1765727637471-474231444.webp',
|
||
'api/uploads/1765727743466-187581713.webp',
|
||
'api/uploads/1765727819793-158598111.webp',
|
||
'api/uploads/1765727903961-559930753.webp',
|
||
'api/uploads/1765727928577-55944164.webp',
|
||
'api/uploads/1765727948691-389175954.webp',
|
||
'api/uploads/1765727961591-243584836.webp',
|
||
'api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: false,
|
||
isFeatured: false,
|
||
topText: '🔥 Лучшее предложение',
|
||
year: 2023,
|
||
comfortCapacity: 6,
|
||
maxCapacity: 10,
|
||
width: 4.5,
|
||
cabinsCount: 3,
|
||
matherial: 'Стеклопластик',
|
||
power: 1400,
|
||
description:
|
||
'Британский шик и русская душа в одной яхте! Сансикер Манхэттен 52 - выбор настоящих ценителей морских путешествий. Просторный кокпит с мягкими диванами, бар на 8 персон, система мультимедиа премиум-класса. Идеальна для празднования дня рождения на воде или деловой встречи с партнерами. Отличная маневренность позволяет заходить в марины Санкт-Петербурга и Кронштадта.',
|
||
owner: null as any,
|
||
reviews: [],
|
||
reservations: [],
|
||
},
|
||
{
|
||
id: 3,
|
||
name: 'Принцесс V55',
|
||
length: 16.7,
|
||
speed: 33,
|
||
minCost: 78000,
|
||
mainImageUrl: 'api/uploads/1765728152179-305707681.webp',
|
||
galleryUrls: [
|
||
'api/uploads/1765728152179-305707681.webp',
|
||
'api/uploads/1765727637471-474231444.webp',
|
||
'api/uploads/1765727743466-187581713.webp',
|
||
'api/uploads/1765727819793-158598111.webp',
|
||
'api/uploads/1765727903961-559930753.webp',
|
||
'api/uploads/1765727928577-55944164.webp',
|
||
'api/uploads/1765727948691-389175954.webp',
|
||
'api/uploads/1765727961591-243584836.webp',
|
||
'api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: true,
|
||
isFeatured: false,
|
||
topText: '🍷 Идеальна для заката с бокалом вина',
|
||
year: 2021,
|
||
comfortCapacity: 8,
|
||
maxCapacity: 12,
|
||
width: 4.7,
|
||
cabinsCount: 4,
|
||
matherial: 'Стеклопластик',
|
||
power: 1100,
|
||
description:
|
||
'Принцесс V55 - королева российских вод! Эта яхта создана для тех, кто ценит комфорт и элегантность. Четыре уютные каюты с кондиционером, гальюн с душем, полностью оборудованная камбузная зона. Особенность - огромный платц с гидравлическим трапом для купания в Ладожском озере. Отличный выбор для семейного отдыха или рыбалки с друзьями.',
|
||
owner: null as any,
|
||
reviews: [],
|
||
reservations: [],
|
||
},
|
||
{
|
||
id: 4,
|
||
name: 'Ферретти 500',
|
||
length: 15.2,
|
||
speed: 31,
|
||
minCost: 68000,
|
||
mainImageUrl: 'api/uploads/1765728169750-667674217.webp',
|
||
galleryUrls: [
|
||
'api/uploads/1765728169750-667674217.webp',
|
||
'api/uploads/1765727637471-474231444.webp',
|
||
'api/uploads/1765727743466-187581713.webp',
|
||
'api/uploads/1765727819793-158598111.webp',
|
||
'api/uploads/1765727903961-559930753.webp',
|
||
'api/uploads/1765727928577-55944164.webp',
|
||
'api/uploads/1765727948691-389175954.webp',
|
||
'api/uploads/1765727961591-243584836.webp',
|
||
'api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: true,
|
||
isFeatured: false,
|
||
topText: '⏳ Часто бронируется - успей',
|
||
year: 2020,
|
||
comfortCapacity: 6,
|
||
maxCapacity: 8,
|
||
width: 4.3,
|
||
cabinsCount: 3,
|
||
matherial: 'Стеклопластик',
|
||
power: 900,
|
||
description:
|
||
'Итальянская страсть в русской стихии! Ферретти 500 сочетает в себе средиземноморский шарм и надежность для суровых условий Балтики. Просторный салон с панорамными окнами, обеденная зона на 6 человек, современная навигационная система. Идеально подходит для фотосессий на фоне разводных мостов Петербурга или романтического ужина под звуки волн.',
|
||
owner: null as any,
|
||
reviews: [],
|
||
reservations: [],
|
||
},
|
||
{
|
||
id: 5,
|
||
name: 'Си Рей 510 Сандансер',
|
||
length: 15.5,
|
||
speed: 35,
|
||
minCost: 72000,
|
||
mainImageUrl: 'api/uploads/1765728190017-763752836.webp',
|
||
galleryUrls: [
|
||
'api/uploads/1765728190017-763752836.webp',
|
||
'api/uploads/1765727637471-474231444.webp',
|
||
'api/uploads/1765727743466-187581713.webp',
|
||
'api/uploads/1765727819793-158598111.webp',
|
||
'api/uploads/1765727903961-559930753.webp',
|
||
'api/uploads/1765727928577-55944164.webp',
|
||
'api/uploads/1765727948691-389175954.webp',
|
||
'api/uploads/1765727961591-243584836.webp',
|
||
'api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: false,
|
||
isFeatured: false,
|
||
year: 2023,
|
||
comfortCapacity: 8,
|
||
maxCapacity: 10,
|
||
width: 4.6,
|
||
cabinsCount: 3,
|
||
matherial: 'Стеклопластик',
|
||
power: 1300,
|
||
description:
|
||
'Американская мощь для русского моря! Си Рей 510 Сандансер - самая быстрая яхта в нашем флоте. Развивает скорость до 35 узлов, что позволяет за день обогнуть весь Финский залив. Три комфортабельные каюты, система стабилизации на стоянке, мощная аудиосистема с сабвуфером. Отличный выбор для любителей острых ощущений и скоростных прогулок.',
|
||
owner: null as any,
|
||
reviews: [],
|
||
reservations: [],
|
||
},
|
||
{
|
||
id: 6,
|
||
name: 'Бавария SR41',
|
||
length: 12.5,
|
||
speed: 28,
|
||
minCost: 45000,
|
||
mainImageUrl: 'api/uploads/1765728208376-854378188.webp',
|
||
galleryUrls: [
|
||
'api/uploads/1765728208376-854378188.webp',
|
||
'api/uploads/1765727637471-474231444.webp',
|
||
'api/uploads/1765727743466-187581713.webp',
|
||
'api/uploads/1765727819793-158598111.webp',
|
||
'api/uploads/1765727903961-559930753.webp',
|
||
'api/uploads/1765727928577-55944164.webp',
|
||
'api/uploads/1765727948691-389175954.webp',
|
||
'api/uploads/1765727961591-243584836.webp',
|
||
'api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: true,
|
||
isFeatured: false,
|
||
year: 2019,
|
||
comfortCapacity: 6,
|
||
maxCapacity: 8,
|
||
width: 3.9,
|
||
cabinsCount: 2,
|
||
matherial: 'Стеклопластик',
|
||
power: 320,
|
||
description:
|
||
'Немецкое качество для русского характера! Бавария SR41 - надежная и экономичная яхта для спокойных прогулок по Ладоге. Две уютные каюты, просторный кокпит с тентом от дождя, лебедка для подъема парусов. Идеальный выбор для начинающих яхтсменов или семейного отдыха с детьми. Расход топлива всего 15 литров в час!',
|
||
owner: null as any,
|
||
reviews: [],
|
||
reservations: [],
|
||
},
|
||
{
|
||
id: 7,
|
||
name: 'Жанно Мери Фишер 895',
|
||
length: 8.9,
|
||
speed: 25,
|
||
minCost: 32000,
|
||
mainImageUrl: 'api/uploads/1765728227998-695635756.webp',
|
||
galleryUrls: [
|
||
'api/uploads/1765728227998-695635756.webp',
|
||
'api/uploads/1765727637471-474231444.webp',
|
||
'api/uploads/1765727743466-187581713.webp',
|
||
'api/uploads/1765727819793-158598111.webp',
|
||
'api/uploads/1765727903961-559930753.webp',
|
||
'api/uploads/1765727928577-55944164.webp',
|
||
'api/uploads/1765727948691-389175954.webp',
|
||
'api/uploads/1765727961591-243584836.webp',
|
||
'api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: true,
|
||
isFeatured: false,
|
||
year: 2022,
|
||
comfortCapacity: 4,
|
||
maxCapacity: 6,
|
||
width: 3.0,
|
||
cabinsCount: 1,
|
||
matherial: 'Стеклопластик',
|
||
power: 250,
|
||
description:
|
||
'Французская элегантность для русского простора! Жанно Мери Фишер 895 - компактная, но вместительная яхта для рыбалки и пикников. Одна просторная каюта, открытый кокпит, столик для барбекю. Отлично подходит для выездов на природу, ночевки в бухтах или обучения детей управлению яхтой. Самый экономичный вариант в нашем флоте!',
|
||
owner: null as any,
|
||
reviews: [],
|
||
reservations: [],
|
||
},
|
||
{
|
||
id: 8,
|
||
name: 'Бенето Свифт Троулер 41',
|
||
length: 12.5,
|
||
speed: 22,
|
||
minCost: 55000,
|
||
mainImageUrl: 'api/uploads/1765728068963-634185622.webp',
|
||
galleryUrls: [
|
||
'api/uploads/1765728068963-634185622.webp',
|
||
'api/uploads/1765727637471-474231444.webp',
|
||
'api/uploads/1765727743466-187581713.webp',
|
||
'api/uploads/1765727819793-158598111.webp',
|
||
'api/uploads/1765727903961-559930753.webp',
|
||
'api/uploads/1765727928577-55944164.webp',
|
||
'api/uploads/1765727948691-389175954.webp',
|
||
'api/uploads/1765727961591-243584836.webp',
|
||
'api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: false,
|
||
isFeatured: false,
|
||
year: 2021,
|
||
comfortCapacity: 6,
|
||
maxCapacity: 8,
|
||
width: 4.2,
|
||
cabinsCount: 2,
|
||
matherial: 'Стеклопластик',
|
||
power: 425,
|
||
description:
|
||
'Французский траулер для русского севера! Бенето Свифт Троулер 41 создан для длительных путешествий по Белому морю. Экономичный дизельный двигатель, большой запас топлива, система опреснения воды. Две комфортабельные каюты с подогревом пола. Идеальный выбор для экспедиций или многодневных круизов по северным островам.',
|
||
owner: null as any,
|
||
reviews: [],
|
||
reservations: [],
|
||
},
|
||
{
|
||
id: 9,
|
||
name: 'Лагун 450',
|
||
length: 13.5,
|
||
speed: 20,
|
||
minCost: 65000,
|
||
mainImageUrl: 'api/uploads/1765728152179-305707681.webp',
|
||
galleryUrls: [
|
||
'api/uploads/1765728152179-305707681.webp',
|
||
'api/uploads/1765727637471-474231444.webp',
|
||
'api/uploads/1765727743466-187581713.webp',
|
||
'api/uploads/1765727819793-158598111.webp',
|
||
'api/uploads/1765727903961-559930753.webp',
|
||
'api/uploads/1765727928577-55944164.webp',
|
||
'api/uploads/1765727948691-389175954.webp',
|
||
'api/uploads/1765727961591-243584836.webp',
|
||
'api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: true,
|
||
isFeatured: false,
|
||
year: 2020,
|
||
comfortCapacity: 8,
|
||
maxCapacity: 10,
|
||
width: 7.8,
|
||
cabinsCount: 4,
|
||
matherial: 'Стеклопластик',
|
||
power: 90,
|
||
description:
|
||
'Французский катамаран для русского размаха! Лагун 450 - невероятно устойчивая и просторная яхта. Четыре отдельные каюты с санузлами, огромный салон-трансформер, две кухни. Идеально подходит для больших компаний, свадебных церемоний на воде или длительных круизов всей семьей. Не кренится даже в шторм!',
|
||
owner: null as any,
|
||
reviews: [],
|
||
reservations: [],
|
||
},
|
||
{
|
||
id: 10,
|
||
name: 'Фонтен Пажо Люсия 40',
|
||
length: 11.7,
|
||
speed: 18,
|
||
minCost: 58000,
|
||
mainImageUrl: 'api/uploads/1765728169750-667674217.webp',
|
||
galleryUrls: [
|
||
'api/uploads/1765728169750-667674217.webp',
|
||
'api/uploads/1765727637471-474231444.webp',
|
||
'api/uploads/1765727743466-187581713.webp',
|
||
'api/uploads/1765727819793-158598111.webp',
|
||
'api/uploads/1765727903961-559930753.webp',
|
||
'api/uploads/1765727928577-55944164.webp',
|
||
'api/uploads/1765727948691-389175954.webp',
|
||
'api/uploads/1765727961591-243584836.webp',
|
||
'api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: true,
|
||
isFeatured: false,
|
||
year: 2023,
|
||
comfortCapacity: 8,
|
||
maxCapacity: 10,
|
||
width: 7.1,
|
||
cabinsCount: 4,
|
||
matherial: 'Стеклопластик',
|
||
power: 80,
|
||
description:
|
||
'Французский катамаран класса люкс! Фонтен Пажо Люсия 40 - это плавающий пятизвездочный отель. Четыре каюты-люкс с джакузи, салон с камином, профессиональная кухня с шеф-поваром. Система стабилизации на якоре, гидромассажный бассейн на палубе. Выбор настоящих ценителей роскоши и комфорта на воде.',
|
||
owner: null as any,
|
||
reviews: [],
|
||
reservations: [],
|
||
},
|
||
{
|
||
id: 11,
|
||
name: 'Дюфур 460',
|
||
length: 14.1,
|
||
speed: 26,
|
||
minCost: 62000,
|
||
mainImageUrl: 'api/uploads/1765728190017-763752836.webp',
|
||
galleryUrls: [
|
||
'api/uploads/1765728190017-763752836.webp',
|
||
'api/uploads/1765727637471-474231444.webp',
|
||
'api/uploads/1765727743466-187581713.webp',
|
||
'api/uploads/1765727819793-158598111.webp',
|
||
'api/uploads/1765727903961-559930753.webp',
|
||
'api/uploads/1765727928577-55944164.webp',
|
||
'api/uploads/1765727948691-389175954.webp',
|
||
'api/uploads/1765727961591-243584836.webp',
|
||
'api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: false,
|
||
isFeatured: false,
|
||
year: 2022,
|
||
comfortCapacity: 8,
|
||
maxCapacity: 10,
|
||
width: 4.5,
|
||
cabinsCount: 3,
|
||
matherial: 'Стеклопластик',
|
||
power: 380,
|
||
description:
|
||
'Французская парусная яхта для русского ветра! Дюфур 460 - мечта любого яхтсмена. Три просторные каюты, кокпит с мягкими сиденьями, современное парусное вооружение. Идеально сбалансированная, легко управляется даже новичками. Отличный выбор для регат, обучения парусному спорту или романтических круизов под парусами.',
|
||
owner: null as any,
|
||
reviews: [],
|
||
reservations: [],
|
||
},
|
||
{
|
||
id: 12,
|
||
name: 'Гранд Бэнкс 60',
|
||
length: 18.3,
|
||
speed: 24,
|
||
minCost: 125000,
|
||
mainImageUrl: 'api/uploads/1765728208376-854378188.webp',
|
||
galleryUrls: [
|
||
'api/uploads/1765728208376-854378188.webp',
|
||
'api/uploads/1765727637471-474231444.webp',
|
||
'api/uploads/1765727743466-187581713.webp',
|
||
'api/uploads/1765727819793-158598111.webp',
|
||
'api/uploads/1765727903961-559930753.webp',
|
||
'api/uploads/1765727928577-55944164.webp',
|
||
'api/uploads/1765727948691-389175954.webp',
|
||
'api/uploads/1765727961591-243584836.webp',
|
||
'api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: true,
|
||
isFeatured: false,
|
||
year: 2023,
|
||
comfortCapacity: 6,
|
||
maxCapacity: 8,
|
||
width: 5.2,
|
||
cabinsCount: 3,
|
||
matherial: 'Стеклопластик',
|
||
power: 1600,
|
||
description:
|
||
'Американская легенда для русского океана! Гранд Бэнкс 60 - экспедиционная яхта для самых смелых путешествий. Три каюты-люкс, салон с библиотекой, зимний сад, сауна. Автономность плавания - 30 дней! Способна пересечь Баренцево море и дойти до Шпицбергена. Выбор для настоящих морских волков и исследователей Арктики.',
|
||
owner: null as any,
|
||
reviews: [],
|
||
reservations: [],
|
||
},
|
||
];
|
||
|
||
private toShortDto(item: CatalogItemLongDto): CatalogItemShortDto {
|
||
const {
|
||
id,
|
||
name,
|
||
length,
|
||
speed,
|
||
minCost,
|
||
mainImageUrl,
|
||
galleryUrls,
|
||
hasQuickRent,
|
||
isFeatured,
|
||
topText,
|
||
} = item;
|
||
return {
|
||
id,
|
||
name,
|
||
length,
|
||
speed,
|
||
minCost,
|
||
mainImageUrl,
|
||
galleryUrls,
|
||
hasQuickRent,
|
||
isFeatured,
|
||
topText,
|
||
};
|
||
}
|
||
|
||
async getCatalogItemById(id: number): Promise<CatalogItemLongDto | null> {
|
||
const item = this.catalogItems.find((item) => item.id === id);
|
||
if (!item) return null;
|
||
|
||
const ownerId = [1, 2][(id - 1) % 2];
|
||
const owner = await this.usersService.findById(ownerId);
|
||
|
||
if (owner) {
|
||
item.owner = owner;
|
||
}
|
||
|
||
item.reviews = this.reviewsService.getReviewsByYachtId(id);
|
||
item.reservations = this.reservationsService.getReservationsByYachtId(id);
|
||
|
||
return item;
|
||
}
|
||
|
||
async getMainPageCatalog(): Promise<MainPageCatalogResponseDto | null> {
|
||
const clonedCatalog = [...this.catalogItems];
|
||
const filteredCatalog = clonedCatalog.filter(
|
||
({ isFeatured }) => !isFeatured,
|
||
);
|
||
|
||
const featuredYachtIndex = clonedCatalog.findIndex(
|
||
(item) => item.isFeatured === true,
|
||
);
|
||
|
||
if (featuredYachtIndex !== -1) {
|
||
const minCost = Math.min(
|
||
...filteredCatalog.map((item) => item.minCost || Infinity),
|
||
);
|
||
|
||
const mappedRestYachts = filteredCatalog.slice(0, 6).map((item) => ({
|
||
...this.toShortDto(item),
|
||
isBestOffer: item.minCost === minCost,
|
||
}));
|
||
|
||
return {
|
||
featuredYacht: this.toShortDto(clonedCatalog[featuredYachtIndex]),
|
||
restYachts: mappedRestYachts,
|
||
};
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
async getCatalog(params?: CatalogParamsDto): Promise<CatalogResponseDto> {
|
||
let filteredItems = this.catalogItems.map((item) => this.toShortDto(item));
|
||
|
||
if (params?.search) {
|
||
const searchTerm = params.search.toLowerCase();
|
||
filteredItems = filteredItems.filter((item) =>
|
||
item.name.toLowerCase().includes(searchTerm),
|
||
);
|
||
}
|
||
|
||
if (params?.filter?.price) {
|
||
const { minvalue, maxvalue } = params.filter.price;
|
||
filteredItems = filteredItems.filter((item) => {
|
||
if (minvalue !== undefined && item.minCost < minvalue) return false;
|
||
if (maxvalue !== undefined && item.minCost > maxvalue) return false;
|
||
return true;
|
||
});
|
||
}
|
||
|
||
if (params?.sort?.field) {
|
||
const { field, direction = 'asc' } = params.sort;
|
||
filteredItems.sort((a, b) => {
|
||
let valueA = a[field];
|
||
let valueB = b[field];
|
||
|
||
if (typeof valueA === 'string') valueA = valueA.toLowerCase();
|
||
if (typeof valueB === 'string') valueB = valueB.toLowerCase();
|
||
|
||
if (valueA < valueB) return direction === 'asc' ? -1 : 1;
|
||
if (valueA > valueB) return direction === 'asc' ? 1 : -1;
|
||
return 0;
|
||
});
|
||
}
|
||
|
||
return {
|
||
items: filteredItems,
|
||
total: filteredItems.length,
|
||
filters: params?.filter,
|
||
sort: params?.sort,
|
||
search: params?.search,
|
||
};
|
||
}
|
||
|
||
async getAllCatalogItems(): Promise<CatalogItemShortDto[]> {
|
||
return this.catalogItems.map((item) => this.toShortDto(item));
|
||
}
|
||
}
|