Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
re-implemented using more idiomatic Xtend, added gradle build config
- Loading branch information
1 parent
fed8e77
commit 89ca00e
Showing
5 changed files
with
155 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<classpath> | ||
<classpathentry kind="src" path="xtend-gen"/> | ||
<classpathentry kind="con" path="org.eclipse.xtend.XTEND_CONTAINER"/> | ||
<classpathentry kind="src" path="src"/> | ||
<classpathentry kind="src" path="xtend-gen"/> | ||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> | ||
<classpathentry kind="output" path="bin"/> | ||
</classpath> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
bin | ||
pricefile.txt | ||
xtend-gen | ||
build | ||
.gradle |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
apply plugin: 'application' | ||
|
||
// Allows generating an Eclipse project via 'gradle eclipse' | ||
apply plugin: 'eclipse' | ||
apply plugin: "org.xtext.xtend" | ||
|
||
mainClassName = "HollingBerries" | ||
|
||
repositories { | ||
mavenCentral() | ||
maven { | ||
url "https://plugins.gradle.org/m2/" | ||
} | ||
} | ||
|
||
dependencies { | ||
compile 'org.eclipse.xtend:org.eclipse.xtend.lib:2.9.0' | ||
} | ||
|
||
eclipse { | ||
project { | ||
natures 'org.eclipse.xtext.ui.shared.xtextNature' | ||
buildCommand 'org.eclipse.xtext.ui.shared.xtextBuilder' | ||
} | ||
} | ||
|
||
sourceSets { | ||
main { | ||
java { | ||
srcDir 'src/' | ||
} | ||
resources { | ||
srcDir 'src/resources' | ||
} | ||
} | ||
} | ||
|
||
buildscript { | ||
repositories { | ||
mavenCentral() | ||
maven { | ||
url "https://plugins.gradle.org/m2/" | ||
} | ||
} | ||
|
||
dependencies { | ||
classpath "org.xtext:xtext-gradle-plugin:1.0.2" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,102 +1,105 @@ | ||
import java.io.FileReader | ||
import java.io.FileWriter | ||
import java.text.SimpleDateFormat | ||
import java.util.Date | ||
import org.eclipse.xtend.lib.Data | ||
import static HollingBerries.* | ||
import org.eclipse.xtend.lib.annotations.Data | ||
|
||
import static extension com.google.common.io.CharStreams.* | ||
import java.io.FileWriter | ||
import java.util.Calendar | ||
|
||
// Class to hold product data | ||
@Data class Product { | ||
int supplierId | ||
int productCode | ||
String description | ||
Date deliveryDate | ||
int price | ||
int quantity | ||
int supplierId | ||
int productCode | ||
String description | ||
Date deliveryDate | ||
int price | ||
int quantity | ||
} | ||
|
||
@Data class ProduceData { | ||
IntegerRange codes | ||
double markup | ||
int shelfLifeDays | ||
} | ||
|
||
// Main class | ||
class HollingBerries { | ||
// supplier ratings | ||
val troubleSuppliers = newArrayList(32, 101) | ||
val premiumSuppliers = newArrayList(219, 204) | ||
// Data for each type of produce: code range, markup, shelf life in days | ||
val produceData = #{ | ||
"Apples" -> new ProduceData((1100 .. 1199), 1.40, 14), | ||
"Bananas" -> new ProduceData((1200 .. 1299), 1.35, 5), | ||
"Berries" -> new ProduceData((1300 .. 1399), 1.55, 7), | ||
"Other" -> new ProduceData(null, 1.5, 7) | ||
} | ||
|
||
// compute the selling price based on product type and supplier | ||
def getSellPrice(Product p) { | ||
var markup = switch p { | ||
case (1100..1199).contains(p.productCode): 40 | ||
case (1200..1299).contains(p.productCode): 35 | ||
case (1300..1399).contains(p.productCode): 55 | ||
default: 50 | ||
} | ||
|
||
// adjust for suppliers | ||
sanePrice(switch p { | ||
case troubleSuppliers.contains(p.supplierId): | ||
(p.price * (1 + markup/100.0) - 200) / 100.0 | ||
case premiumSuppliers.contains(p.supplierId): | ||
Math::ceil(p.price * (1 + (markup+10)/100.0) / 100.0) | ||
default: | ||
p.price * (1 + markup/100.0) / 100.0 | ||
}) | ||
} | ||
// supplier ratings | ||
val troubleSuppliers = #[32, 101] | ||
val premiumSuppliers = #[219, 204] | ||
|
||
// compute sell by date based on product type and supplier | ||
def getSellBy(Product p) { | ||
var adj = switch p { | ||
case (1100..1199).contains(p.productCode): 14 | ||
case (1200..1299).contains(p.productCode): 5 | ||
default: 7 | ||
} | ||
|
||
// adjust for suppliers | ||
if (troubleSuppliers.contains(p.supplierId)) { | ||
val inDateFormat = new SimpleDateFormat("\"yyyy/MM/dd\"") | ||
val outdateFormat = new SimpleDateFormat("yyyy/MM/dd") | ||
|
||
def getProduceData(Product p) { | ||
produceData.values.findFirst[ codes == null || codes.contains(p.productCode) ] | ||
} | ||
|
||
// compute the selling price based on product type and supplier | ||
def getSellPrice(Product p) { | ||
var markup = p.produceData.markup | ||
|
||
// adjust for suppliers | ||
switch p { | ||
case troubleSuppliers.contains(p.supplierId): | ||
(p.price * markup - 200.0) / 100.0 | ||
case premiumSuppliers.contains(p.supplierId): | ||
Math::ceil(p.price * (markup + 0.1) / 100.0) | ||
default: | ||
p.price * markup / 100.0 | ||
} | ||
} | ||
|
||
// compute sell by date based on product type and supplier | ||
def getSellBy(Product p) { | ||
var adj = p.produceData.shelfLifeDays | ||
|
||
// adjust for suppliers | ||
if (troubleSuppliers.contains(p.supplierId)) { | ||
adj = adj - 3 | ||
} | ||
|
||
new Date(p.deliveryDate.time + adj*1000*60*60*24) | ||
} | ||
} | ||
|
||
new Date(p.deliveryDate.time + adj * 1000 * 60 * 60 * 24) | ||
} | ||
|
||
// generate the label printer lines for each product | ||
def String processProduct(Product p) { | ||
if (p.quantity <= 0) return "" | ||
(0 .. p.quantity - 1).join("", [ | ||
var sellPrice = Math.max(p.getSellPrice, 0.0) | ||
var sellBy = p.getSellBy | ||
var desc = p.description.substring(1, 32) | ||
'''R«String::format("% 8.2f", sellPrice)»«outdateFormat.format(sellBy)»«desc» | ||
'''.toString | ||
]) | ||
} | ||
|
||
// make sure prices are sane | ||
def sanePrice(double price) { | ||
if (price < 0) 0 else price | ||
} | ||
// processing loop to read CSV and write label printer file | ||
def process(String sourceCsv, String outputCsv) { | ||
val out = new FileWriter(outputCsv) | ||
new FileReader(sourceCsv).readLines.drop(1).forEach [ | ||
val cols = it.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)", -1).iterator | ||
val product = new Product( | ||
Integer::parseInt(cols.next), | ||
Integer::parseInt(cols.next), | ||
cols.next, | ||
inDateFormat.parse(cols.next), | ||
Integer::parseInt(cols.next), | ||
Integer::parseInt(cols.next) | ||
) | ||
out.write(processProduct(product)) | ||
] | ||
out.close | ||
} | ||
|
||
// generate the label printer lines for each product | ||
def String processProduct(Product p) { | ||
if (p.quantity == 0) return "" | ||
(0..p.quantity-1).join("", [ | ||
var sellPrice = p.getSellPrice | ||
var sellBy = p.getSellBy | ||
var desc = p.description.substring(1,32) | ||
|
||
var sdf = new SimpleDateFormat("yyyy/MM/dd") | ||
'''R«String::format("% 8.2f", sellPrice)»«sdf.format(sellBy)»«desc» | ||
'''.toString | ||
]) | ||
} | ||
|
||
// processing loop to read CSV and write label printer file | ||
def process(String sourceCsv, String outputCsv) { | ||
val out = new FileWriter(outputCsv) | ||
new FileReader(sourceCsv).readLines.drop(1).forEach[ | ||
val cols = it.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)", -1).iterator | ||
val product = new Product( | ||
Integer::parseInt(cols.next), | ||
Integer::parseInt(cols.next), | ||
cols.next, | ||
new SimpleDateFormat("\"yyyy/MM/dd\"").parse(cols.next), | ||
Integer::parseInt(cols.next), | ||
Integer::parseInt(cols.next) | ||
) | ||
out.write(processProduct(product)) | ||
] | ||
out.close | ||
} | ||
|
||
def static void main(String[] args) { | ||
new HollingBerries().process("../../produce.csv", "pricefile.txt") | ||
} | ||
def static void main(String[] args) { | ||
new HollingBerries().process("../../produce.csv", "pricefile.txt") | ||
} | ||
} |