This repository was archived by the owner on Jul 21, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBike.java
More file actions
223 lines (181 loc) · 6.97 KB
/
Copy pathBike.java
File metadata and controls
223 lines (181 loc) · 6.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
import java.io.File;
import java.io.FileNotFoundException;
import java.text.NumberFormat;
import java.util.Collections;
import java.util.Scanner;
import java.util.Vector;
/**
* A model of bike, made up of versions of the model.
* For example, a model is "Specialized Diverge" and a version is "Elite A1".
*/
public class Bike implements Comparable<Bike> {
// region statics
static int priceMinGlobal = 888888, priceMaxGlobal; // min and max price of ALL bikes
/**
* Opens an input file and reads all of it into a vector of Bikes.
*
* @param filename name of text file with bike info
* @return a vector of bikes built from the input file
*/
static Vector<Bike> readBikes(String filename) {
Scanner fileScan = null;
try {
fileScan = new Scanner(new File(filename));
} catch (FileNotFoundException e) {
System.err.println("File " + filename + " not found.");
System.exit(1);
}
Vector<Bike> allBikes = new Vector<>();
// go through file and add bikes to the vector
Bike tempBike;
while (true) {
tempBike = readBikeModel(fileScan);
if (tempBike == null) break; // readBikeModel() stops when it reads "end"
allBikes.add(tempBike);
fileScan.nextLine(); //skip a blank line
}
Collections.sort(allBikes);
return allBikes;
}
//@formatter:off (formatter kills indentation in this doc comment)
/**
* Reads and returns a single bike model.
* Steps:
*
* (1) Reads the header, which contains the model name and the number of versions.
* Example: "Trek Domane: 19"
*
* (2) Does four for loops to read:
* (a) version names
* (b) version prices
* (c) version materials
* (d) version groupsets
*
* @param sc scanner on the input text file
* @return a Bike object containing all of the version names, prices, and materials
*/
//@formatter:on
private static Bike readBikeModel(Scanner sc) {
sc.useDelimiter(": |\r?\n|\r"); // use newline and ":" as delimiter
//read model name
String name = sc.next();
if (name.equals("end")) return null;
Bike newBike = new Bike(name);
// read number of versions
int numModels = sc.nextInt();
newBike.numModels = numModels;
sc.useDelimiter(", |\r?\n|\r"); // only use newline as delimiter
// read version names
for (int i = 0; i < numModels; i++) {
newBike.names.add(sc.next());
}
// read version prices
for (int i = 0; i < numModels; i++) {
newBike.addPrice(sc.nextInt());
}
// read version materials
for (int i = 0; i < numModels; i++) {
newBike.carbons.add(Carbon.parseString(sc.next()));
}
// read version groupsets
for (int i = 0; i < numModels; i++) {
newBike.groupsets.add(Groupset.parseString(sc.next()));
}
return newBike;
}
// endregion statics
// region instance stuff
// I have decided everything can be default privacy
String modelName;
int numModels;
Vector<String> names = new Vector<>();
Vector<Integer> prices = new Vector<>();
Vector<Carbon> carbons = new Vector<>();
Vector<Groupset> groupsets = new Vector<>();
int minPriceModel = 999999, maxPriceModel; // price of most and least expensive version of the model
public int compareTo(Bike other) {
return Integer.compare(minPriceModel, other.minPriceModel);
}
/**
* Constructs new Bike given the name of the model.
*
* @param name the name of the model to construct.
*/
public Bike(String name) {
this.modelName = name;
}
/**
* Gives human-readable representation of a bike with all the versions.
*
* @return a human-readable representation of the bike model.
*/
public String toString() {
NumberFormat numFmt = NumberFormat.getInstance();
String out = modelName + "\n-----------------------\n";
for (int i = 0; i < names.size(); i++) {
out += String.format("%s: $%s\n", names.get(i), numFmt.format(prices.get(i)));
}
return out;
}
/**
* Used to add a price to the vector of prices.
* prices isn't private but you should still use this.
*
* @param p the price of the version to add.
*/
private void addPrice(int p) {
prices.add(p);
if (p < priceMinGlobal) priceMinGlobal = p;
if (p > priceMaxGlobal) priceMaxGlobal = p;
if (p < minPriceModel) minPriceModel = p;
if (p > maxPriceModel) maxPriceModel = p;
}
/**
* Prints the header for the CSV populated by CSV_printRow().
*/
static void CSV_printHeader() {
System.out.println("\"Model\", \"Absolute price range\", \"Relative price range\", \"" +
"Least expensive version\", \"Least expensive version price\", \"" +
"Most expensive version\", \"Most expensive version price\"");
}
/**
* Prints a CSV row of: model name, absolute price range, relative price range, name of least expensive version,
* price of least expensive version, name of most expensive version, price of most expensive version.
*
* When writing CSV files, use CSV_printHeader() first.
*/
void CSV_printRow() {
NumberFormat numFmt = NumberFormat.getNumberInstance();
System.out.printf("\"%s\", \"$%s\", \"%.2fx\", \"%s\", \"$%s\", \"%s\", \"$%s\"\n",
modelName,
numFmt.format(maxPriceModel - minPriceModel),
(double) (maxPriceModel) / minPriceModel,
names.firstElement(),
numFmt.format(prices.firstElement()),
names.lastElement(),
numFmt.format(prices.lastElement()));
}
/**
* Returns data for input to a histogram.
* Partitions the bikes by price into numBins bins. Each element of the vector
* is the number of versions in that price range.
*/
Vector<Integer> getHistogramData(int numBins) {
Vector<Integer> bins = new Vector<>(numBins);
for (int i = 0; i < numBins; i++) bins.add(i, 0);
double binWidth = (double) (maxPriceModel - minPriceModel) / numBins; // width in dollars of each bin
double priceCutoff; // max price for a version to be in a bin
for (int currentPrice : prices) {
for (int currentBin = 1; currentBin <= numBins; currentBin++) {
priceCutoff = minPriceModel + (binWidth * currentBin);
if (currentPrice <= priceCutoff) {
// this is gross, mixing zero-based and one-based
bins.set(currentBin - 1, bins.get(currentBin - 1) + 1);
break;
}
}
}
return bins;
}
// endregion instance stuff
}