import BaseEntity from '../../common/entities/BaseEntity'; import ValidableInterface from '../../common/interfaces/ValidableInterface'; import RouteStop from '../../RouteStop/entity/RouteStop'; import TravelStopPricing from '../../TravelStopPricing/entity/TravelStopPricing'; import TravelStop from '../../TravelStop/entity/TravelStop'; import CloneFactory from '../../common/factories/CloneFactory/CloneFactory'; export default class Route extends BaseEntity implements ValidableInterface { protected _route_group_id: string; protected _name: string; protected _stops: Array = []; private _number_of_journeys: number; private _number_of_products: number; get route_group_id(): string { return this._route_group_id; } set route_group_id(value: string) { this._route_group_id = value; } get name(): string { return this._name; } set name(value: string) { this._name = value; } get stops(): Array { return this._stops; } set stops(value: Array) { this._stops = value; } addRouteStop(item: RouteStop) { this.stops.push(item); } removeStop(index) { this.stops.splice(index, 1); } get number_of_journeys(): number { return this._number_of_journeys; } set number_of_journeys(value: number) { this._number_of_journeys = value; } get number_of_products(): number { return this._number_of_products; } set number_of_products(value: number) { this._number_of_products = value; } // Finds existing travelPricing inside pricing list. findTravelStopPricing(pickup: TravelStop, dropoff: TravelStop): TravelStopPricing { let pricing = null; pickup.pricings.map((eachPricing: TravelStopPricing) => { if (!pricing && eachPricing.destination_stop.isEqual(dropoff)) { pricing = eachPricing; } }); return pricing; } // Just in case we want to reset the matrix. resetPricingMatrix() { this.stops = this.stops.map((eachRouteStop: RouteStop) => { eachRouteStop.pricings.length = 0; return eachRouteStop; }); } preparePricingMatrix() { /* for each valid pickup => for each valid dropoff => if combination not exists => add travel stop pricing with: travel stop destination = each dropoff both prices = null else do nothing */ this.getValidPickupPoints().forEach((eachPickup: RouteStop) => { this.getValidDropoffPoints().forEach((eachDropoff: RouteStop) => { if (eachPickup.stop_order > eachDropoff.stop_order || eachPickup.isEqual(eachDropoff)) { return; } let travelStopPricing = this.findTravelStopPricing(eachPickup, eachDropoff); if (!travelStopPricing) { travelStopPricing = new TravelStopPricing(); // TODO: rethink this to find a better solution BUT we need to clone the eachDropoff to avoid endless anidation (because of passed down by reference). travelStopPricing.destination_stop = (new CloneFactory()).clone(eachDropoff); // travelStopPricing.one_leg_price = null; // travelStopPricing.two_legs_price = null; eachPickup.addPricing(travelStopPricing); } }); }); } optimizePricingMatrix() { let valid = []; this.getValidPickupPoints().forEach((eachPickup: RouteStop) => { this.getValidDropoffPoints().forEach((eachDropoff: RouteStop) => { if (eachPickup.stop_order > eachDropoff.stop_order || eachPickup.isEqual(eachDropoff)) { return; } let travelStopPricing = this.findTravelStopPricing(eachPickup, eachDropoff); travelStopPricing && valid.push(travelStopPricing); }); }); /* Inside every stop we look for all its pricings. Inside every pricing we look for that exact same pricing in the valid list. */ this.stops = this.stops.map((eachRouteStop: RouteStop) => { eachRouteStop.pricings = eachRouteStop.pricings.filter((eachPricing: TravelStopPricing) => { let index = valid.findIndex((eachValidPricing: TravelStopPricing) => eachValidPricing.id === eachPricing.id); return index !== -1; }); return eachRouteStop; }); } getValidPickupPoints() { return this.stops.filter((each: RouteStop) => each.isPickup()); } getValidDropoffPoints() { return this.stops.filter((each: RouteStop) => each.isDropoff()); } isValid() { return this.invalidFields().length === 0; } invalidFields() { let fields = []; !this.name && fields.push('name'); if (this.stops.length < 2) { fields.push('stops'); } if (this.stops.length >= 2) { this.stops.map((routeStop, routeStopIndex) => { if (!routeStop.isValid()) { fields.push(`route_stop[${routeStopIndex}]__name`); } if (routeStopIndex < this.stops.length - 1) { !routeStop.time_to_reach && fields.push(`route_stop[${routeStopIndex}]__time_to_reach`); !routeStop.distance && fields.push(`route_stop[${routeStopIndex}]__distance`); } }); } return fields; } }