Skip to content
This repository was archived by the owner on Sep 10, 2025. It is now read-only.

Commit 93cb399

Browse files
authored
Merge pull request #53 from jaebradley/symbol-service
Symbol service - Adds support for OSes that don't support emojis
2 parents 6be9b75 + fad75ff commit 93cb399

16 files changed

+616
-68
lines changed

src/executables/uber-price.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
/* eslint-disable no-console */
44

55
import program from 'commander';
6-
import emoji from 'node-emoji';
76

87
import CommandExecutionService from '../services/CommandExecutionService';
8+
import SymbolService from '../services/symbols/SymbolService';
99

1010
const isUberError = error =>
1111
error.name === 'Uber Error' &&
@@ -20,6 +20,8 @@ const isDistanceExceededError = error =>
2020

2121
const service = new CommandExecutionService();
2222

23+
const symbolService = new SymbolService();
24+
2325
program
2426
.option('-s, --start <start>', 'specify start address')
2527
.option('-e, --end <end>', 'specify end address')
@@ -31,7 +33,7 @@ try {
3133
.then(table => console.log(table))
3234
.catch((e) => {
3335
if (isDistanceExceededError(e)) {
34-
console.log(`Maximum distance of ${emoji.get('100')} miles exceeded between start address: ${program.start} and end address: ${program.end}`);
36+
console.log(`Maximum distance of ${symbolService.getMaximumDistanceSymbol()} miles exceeded between start address: ${program.start} and end address: ${program.end}`);
3537
} else {
3638
console.error('Could not get price estimates');
3739
}

src/services/CommandExecutionService.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,19 @@ import TripPriceEstimateRowFormatter from './tables/TripPriceEstimateRowFormatte
88
import TripPriceEstimatesTableBuilder from './tables/builders/TripPriceEstimatesTableBuilder';
99
import PickupTimeEstimatesTableRowsBuilder from './tables/PickupTimeEstimatesTableRowsBuilder';
1010
import PickupTimeEstimatesTableBuilder from './tables/builders/PickupTimeEstimatesTableBuilder';
11+
import SymbolService from './symbols/SymbolService';
1112

1213
export default class CommandExecutionService {
1314
constructor() {
1415
this.uberService = new UberService();
1516
this.distanceConverter = new DistanceConverter();
1617
this.durationConverter = new DurationConverter();
18+
this.symbolService = new SymbolService();
1719
this.durationFormatter = new DurationFormatter(this.durationConverter);
18-
this.tripPriceEstimateRowFormatter = new TripPriceEstimateRowFormatter(this.distanceConverter, this.durationFormatter); // eslint-disable-line max-len
19-
this.tripPriceEstimatesTableBuilder = new TripPriceEstimatesTableBuilder(this.tripPriceEstimateRowFormatter); // eslint-disable-line max-len
20-
this.pickupTimeEstimatesTableRowsBuilder = new PickupTimeEstimatesTableRowsBuilder(this.durationFormatter); // eslint-disable-line max-len
21-
this.pickupTimeEstimatesTableBuilder = new PickupTimeEstimatesTableBuilder(this.pickupTimeEstimatesTableRowsBuilder); // eslint-disable-line max-len
20+
this.tripPriceEstimateRowFormatter = new TripPriceEstimateRowFormatter(this.distanceConverter, this.durationFormatter, this.symbolService); // eslint-disable-line max-len
21+
this.tripPriceEstimatesTableBuilder = new TripPriceEstimatesTableBuilder(this.tripPriceEstimateRowFormatter, this.symbolService); // eslint-disable-line max-len
22+
this.pickupTimeEstimatesTableRowsBuilder = new PickupTimeEstimatesTableRowsBuilder(this.durationFormatter, this.symbolService); // eslint-disable-line max-len
23+
this.pickupTimeEstimatesTableBuilder = new PickupTimeEstimatesTableBuilder(this.pickupTimeEstimatesTableRowsBuilder, this.symbolService); // eslint-disable-line max-len
2224
}
2325

2426
executePriceEstimates(startAddress, endAddress, distanceUnitName) {
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
export default class BaseSymbolService {
2+
getVehicleSymbol() {
3+
throw new Error('Not implemented');
4+
}
5+
6+
getPriceSymbol() {
7+
throw new Error('Not implemented');
8+
}
9+
10+
getTripDistanceSymbol() {
11+
throw new Error('Not implemented');
12+
}
13+
14+
getDurationSymbol() {
15+
throw new Error('Not implemented');
16+
}
17+
18+
getSurgeSymbol() {
19+
throw new Error('Not implemented');
20+
}
21+
22+
getNotApplicableSymbol() {
23+
throw new Error('Not implemented');
24+
}
25+
26+
getSurgePresentSymbol() {
27+
throw new Error('Not implemented');
28+
}
29+
30+
getDestinationSymbol() {
31+
throw new Error('Not implemented');
32+
}
33+
34+
getOriginSymbol() {
35+
throw new Error('Not implemented');
36+
}
37+
38+
getMaximumDistanceSymbol() {
39+
throw new Error('Not implemented');
40+
}
41+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import emoji from 'node-emoji';
2+
3+
import BaseSymbolService from './BaseSymbolService';
4+
5+
6+
export default class EmojiService extends BaseSymbolService {
7+
getVehicleSymbol() {
8+
return emoji.get('oncoming_automobile');
9+
}
10+
11+
getPriceSymbol() {
12+
return emoji.get('money_with_wings');
13+
}
14+
15+
getTripDistanceSymbol() {
16+
return emoji.get('arrows_clockwise');
17+
}
18+
19+
getDurationSymbol() {
20+
return emoji.get('hourglass_flowing_sand');
21+
}
22+
23+
getSurgeSymbol() {
24+
return emoji.get('boom');
25+
}
26+
27+
getNotApplicableSymbol() {
28+
return emoji.get('no_entry_sign');
29+
}
30+
31+
getSurgePresentSymbol() {
32+
return emoji.get('grimacing');
33+
}
34+
35+
getDestinationSymbol() {
36+
return emoji.get('end');
37+
}
38+
39+
getOriginSymbol() {
40+
return emoji.get('round_pushpin');
41+
}
42+
43+
getMaximumDistanceSymbol() {
44+
return emoji.get('100');
45+
}
46+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { List } from 'immutable';
2+
3+
import BaseSymbolService from './BaseSymbolService';
4+
import EmojiService from './EmojiService';
5+
import TextSymbolService from './TextSymbolService';
6+
7+
export default class SymbolService extends BaseSymbolService {
8+
constructor() {
9+
super();
10+
this.client = SymbolService.areEmojisSupported() ?
11+
new EmojiService() :
12+
new TextSymbolService();
13+
}
14+
15+
static areEmojisSupported() {
16+
return SymbolService.getEmojiSupportedOperatingSystems().contains(process.platform);
17+
}
18+
19+
static getEmojiSupportedOperatingSystems() {
20+
return List.of('darwin');
21+
}
22+
23+
getVehicleSymbol() {
24+
return this.client.getVehicleSymbol();
25+
}
26+
27+
getPriceSymbol() {
28+
return this.client.getPriceSymbol();
29+
}
30+
31+
getTripDistanceSymbol() {
32+
return this.client.getTripDistanceSymbol();
33+
}
34+
35+
getDurationSymbol() {
36+
return this.client.getDurationSymbol();
37+
}
38+
39+
getSurgeSymbol() {
40+
return this.client.getSurgeSymbol();
41+
}
42+
43+
getNotApplicableSymbol() {
44+
return this.client.getNotApplicableSymbol();
45+
}
46+
47+
getSurgePresentSymbol() {
48+
return this.client.getSurgePresentSymbol();
49+
}
50+
51+
getDestinationSymbol() {
52+
return this.client.getDestinationSymbol();
53+
}
54+
55+
getOriginSymbol() {
56+
return this.client.getOriginSymbol();
57+
}
58+
59+
getMaximumDistanceSymbol() {
60+
return this.client.getMaximumDistanceSymbol();
61+
}
62+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import BaseSymbolService from './BaseSymbolService';
2+
3+
export default class TextSymbolService extends BaseSymbolService {
4+
getVehicleSymbol() {
5+
return 'Vehicle';
6+
}
7+
8+
getPriceSymbol() {
9+
return 'Price';
10+
}
11+
12+
getTripDistanceSymbol() {
13+
return 'Distance';
14+
}
15+
16+
getDurationSymbol() {
17+
return 'Duration';
18+
}
19+
20+
getSurgeSymbol() {
21+
return ' *';
22+
}
23+
24+
getNotApplicableSymbol() {
25+
return 'N/A';
26+
}
27+
28+
getSurgePresentSymbol() {
29+
return ':-(';
30+
}
31+
32+
getDestinationSymbol() {
33+
return 'Destination';
34+
}
35+
36+
getOriginSymbol() {
37+
return 'Origin';
38+
}
39+
40+
getMaximumDistanceSymbol() {
41+
return '100';
42+
}
43+
}

src/services/tables/TripPriceEstimateRowFormatter.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1-
import emoji from 'node-emoji';
1+
import CurrencySymbol from 'currency-symbol-map';
2+
23
import { List, Map } from 'immutable';
34

45
import DistanceUnit from '../../data/DistanceUnit';
56

67
export default class TripPriceEstimateRowFormatter {
7-
constructor(distanceConverter, durationFormatter) {
8+
constructor(distanceConverter, durationFormatter, symbolService) {
89
const distanceUnitAbbreviations = {};
910
distanceUnitAbbreviations[DistanceUnit.MILE.name] = 'mi';
1011
distanceUnitAbbreviations[DistanceUnit.KILOMETER.name] = 'km';
1112

1213
this.distanceUnitAbbreviations = Map(distanceUnitAbbreviations);
1314
this.distanceConverter = distanceConverter;
1415
this.durationFormatter = durationFormatter;
16+
this.symbolService = symbolService;
1517
}
1618

1719
format(estimate, rowDistanceUnit) {
@@ -44,11 +46,9 @@ export default class TripPriceEstimateRowFormatter {
4446
}
4547

4648
formatSurgeMultiplier(surgeMultiplier) {
47-
if (surgeMultiplier > 1) {
48-
return `${surgeMultiplier}x ${emoji.get('grimacing')}`;
49-
}
50-
51-
return emoji.get('no_entry_sign');
49+
return surgeMultiplier > 1 ?
50+
`${surgeMultiplier}x ${this.symbolService.getSurgePresentSymbol()}` :
51+
this.symbolService.getNotApplicableSymbol();
5252
}
5353

5454
getDistanceUnitAbbreviation(unit) {

src/services/tables/builders/PickupTimeEstimatesTableBuilder.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import Table from 'cli-table2';
22
import { List, Map } from 'immutable';
3-
import emoji from 'node-emoji';
43

54
export default class PickupTimeEstimatesTableBuilder {
6-
constructor(rowsBuilder) {
5+
constructor(rowsBuilder, symbolService) {
76
this.rowsBuilder = rowsBuilder;
7+
this.symbolService = symbolService;
88
}
99

1010
build(estimates) {
@@ -15,16 +15,16 @@ export default class PickupTimeEstimatesTableBuilder {
1515

1616
getTableHeaders() {
1717
return List.of(
18-
emoji.get('hourglass_flowing_sand'),
19-
emoji.get('oncoming_automobile'),
18+
this.symbolService.getDurationSymbol(),
19+
this.symbolService.getVehicleSymbol(),
2020
);
2121
}
2222

2323
getFormattedLocation(locationName) {
2424
return List.of(
2525
Map({
2626
colSpan: 2,
27-
content: `${emoji.get('round_pushpin')} ${locationName}`,
27+
content: `${this.symbolService.getOriginSymbol()} ${locationName}`,
2828
hAlign: 'center',
2929
}),
3030
);

src/services/tables/builders/TripPriceEstimatesTableBuilder.js

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import Table from 'cli-table2';
22
import { List, Map } from 'immutable';
3-
import emoji from 'node-emoji';
43

54
export default class TripPriceEstimatesTableBuilder {
6-
constructor(rowFormatter) {
5+
constructor(rowFormatter, symbolService) {
76
this.rowFormatter = rowFormatter;
7+
this.symbolService = symbolService;
88
}
99

1010
build(estimates, presentationDistanceUnit) {
@@ -21,11 +21,11 @@ export default class TripPriceEstimatesTableBuilder {
2121

2222
getTableHeaders() {
2323
return List.of(
24-
emoji.get('oncoming_automobile'),
25-
emoji.get('money_with_wings'),
26-
emoji.get('arrows_clockwise'),
27-
emoji.get('hourglass_flowing_sand'),
28-
`${emoji.get('boom')} Surge${emoji.get('boom')}`,
24+
this.symbolService.getVehicleSymbol(),
25+
this.symbolService.getPriceSymbol(),
26+
this.symbolService.getTripDistanceSymbol(),
27+
this.symbolService.getDurationSymbol(),
28+
`${this.symbolService.getSurgeSymbol()} Surge${this.symbolService.getSurgeSymbol()}`,
2929
);
3030
}
3131

@@ -37,15 +37,10 @@ export default class TripPriceEstimatesTableBuilder {
3737
}
3838

3939
buildLocationRow(name, isEnd) {
40-
let symbol = emoji.get('round_pushpin');
41-
if (isEnd) {
42-
symbol = emoji.get('end');
43-
}
44-
4540
return List.of(
4641
Map({
4742
colSpan: 1,
48-
content: symbol,
43+
content: this.getEndSymbol(isEnd),
4944
hAlign: 'center',
5045
}),
5146
Map({
@@ -54,4 +49,10 @@ export default class TripPriceEstimatesTableBuilder {
5449
}),
5550
);
5651
}
52+
53+
getEndSymbol(isEnd) {
54+
return isEnd ?
55+
this.symbolService.getDestinationSymbol() :
56+
this.symbolService.getOriginSymbol();
57+
}
5758
}

0 commit comments

Comments
 (0)