Given some incoming some data in JSON format, representing unsorted train, bus, and flight tickets:
[{'from':'A', to:'B',...}, {'from':'C', to:'D',...}, {'from':'B', to:'C',...}];
… I must sort tickets (A-B-B-C-C-D) and generate text (description) with all information about each trip (number of flight, gate, seat - it comes with JSON objects). But with some requirements:
- it must be "API format". extensible code (should provide way to add information about different type of transport).
- clean and easy code.
I want to be honest with you, imagine that I'm junior in your team, and that I write for real project.
Here is my solution.
var tickets = [
{
from: "London",
to: "Paris",
transportType: "train",
transport: {
"number": "54S",
"seat": "23"
}
},
{
from: "Berlin",
to: "Akrich",
transportType: "bus",
transport: {
"number": "SR465",
"seat": "56",
"gate": "2A",
}
},
{
from: "Paris",
to: "Berlin",
transportType: "flight",
transport: {
"number": "SR465",
"seat": "56",
"gate": "2A",
"baggage": "will be automatically transferred from your last leg"
}
},
{
from: "Moscow",
to: "London",
transportType: "flight",
transport: {
"number": "N554",
"seat": "4A",
"gate": "22",
"baggage": "drop at ticket counter 344"
}
}
];
function TripSorter ( tickets ) {
this.from = {};
this.to = {};
this.path = [];
this.tickets = [];
if ( tickets ) {
this.importTickets( tickets );
}
}
// copy data in this.tickets.
// create "from" ( contains only "from" points of route ) and "to" objects (hashMap);
TripSorter.prototype.importTickets = function ( tickets ) {
var self = this;
self.tickets = [];
if ( tickets instanceof Array ) {
self.tickets = tickets;
tickets.forEach( function( e, i ) {
if ( !e.from || e.from === ' ' ) {
console.error('card.from - is missing on ' + JSON.stringify(e, undefined, 2));
} else if ( !e.to || e.to === ' ' ) {
console.error('card.to - is missing on ' + JSON.stringify(e, undefined, 2));
} else {
self.from[e.from] = i;
self.to[e.to] = i;
}
});
}
};
// start of trip - unique key in obj from compared to obj to.
TripSorter.prototype.getStartTrip = function () {
var i = 0,
start;
for ( ; i < this.tickets.length; i++ ) {
if( this.to[this.tickets[i].from] == null ) {
start = this.tickets[i].from;
break;
}
}
return start;
};
// obj "from" and "to" contains equal value for different keys
// ticket {from: A, to: B} => var from = { A : 0 }, to = { B : 0};
TripSorter.prototype.buildTrip = function () {
var start = this.getStartTrip(),
point = this.from[start],
next,
i = 0;
for ( ; i < this.tickets.length; i++ ) {
if ( !this.tickets[point] ) continue;
next = this.tickets[point].to;
this.path.push(this.tickets[this.to[next]]);
point = this.from[next];
}
};
TripSorter.prototype.getTrip = function () {
var text = [];
this.path.forEach( function( card ) {
switch (card.transportType) {
case 'flight':
text.push( new Flight(card).message );
break;
case 'train':
text.push( new Train(card).message );
break;
case 'bus':
text.push( new Bus(card).message);
break;
default: break;
};
});
return text;
};
var trip = new TripSorter(tickets);
trip.buildTrip();
var route = trip.getTrip();
console.log(route);
//Generate trip description.
function Transport (data) {
this.from = data.from;
this.to = data.to;
this.type = data.transportType;
this.place = 'from ' + this.from + ' to ' + this.to; // ?
this.seat = (data.transport.seat) ? ' Seat ' + data.transport.seat + '.' : ' No seat assignment.';
this.gate = (data.transport.gate) ? ' Geat ' + data.transport.gate + '.' : '';
this.number = (data.transport.number) ? ' ' + data.transport.number + ' ' : ' ';
this.baggage = ' Baggage' + data.transport.baggage || '';
}
function Train(data) {
Transport.call(this, data);
this.message = 'Take train' + this.number + this.place + '.' + this.seat;
return this.m;
}
Train.prototype = Object.create(Transport.prototype);
Train.prototype.constructor = Train;
function Flight(data) {
Transport.call(this, data);
this.number = 'take flight' + this.number; // ?
this.place = 'From ' + this.from + ',' + this.number + 'to ' + this.to + '.'; // ?
this.message = this.place + this.gate + this.seat + this.baggage;
return this.m;
}
Flight.prototype = Object.create(Transport.prototype);
Flight.prototype.constructor = Flight;
function Bus(data) {
Transport.call(this, data);
this.message = 'Take the bus' + this.number + this.place + '.' + this.seat;
return this.m;
}
Bus.prototype = Object.create(Transport.prototype);
Bus.prototype.constructor = Bus;
Is it ok that I used:
- function constructor and Prototype instead of usual function ?
- different types of array loop —
for
andforEach
in one constructor?
How I should organize code inside of this file (where to place "transport constructor" and where "TripSorter")?
Is it correct to use Transport
constructor and inherit from it or I must used switch(type of transport) - case (message + )? What way is easy to extend?
I must add some functionality to print generated text to html - is it ok that I put it inside of TripSorter
prototype or its better to use different function?
I used console.error
to handle error of ticket format — is it correct way?
Are the comments normal?