-
-
Notifications
You must be signed in to change notification settings - Fork 686
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bookstore : add to track #310
Changes from 5 commits
9b71eb0
de35a3f
c61580a
6d15792
ab34101
7a9a4b4
19ca6d0
c8dd1ff
812e86e
9252786
8426842
f26f9e7
28c89b0
1142bff
a551793
c823390
94e6ee0
18fd731
b1f4e7f
6e385d1
84e3bb6
a8303ad
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
apply plugin: "java" | ||
apply plugin: "eclipse" | ||
apply plugin: "idea" | ||
|
||
repositories { | ||
mavenCentral() | ||
} | ||
|
||
dependencies { | ||
testCompile "junit:junit:4.12" | ||
} | ||
test { | ||
testLogging { | ||
exceptionFormat = 'full' | ||
events = ["passed", "failed", "skipped"] | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import java.util.ArrayList; | ||
import java.util.stream.Collectors; | ||
|
||
public class BookStore{ | ||
public static double CalculateTotalCost(ArrayList<Integer> books ){ | ||
return CalculateTotalCost(books,0); | ||
} | ||
|
||
public static double CalculateTotalCost (ArrayList<Integer> books,double priceSoFar ){ | ||
double minPrice = Double.MAX_VALUE; | ||
|
||
if(books.size() == 0) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Stylistically we would prefer if you use braces, even for simple cases like this. EG: if (books.size() ==0){
return priceSoFar;
} |
||
return priceSoFar; | ||
|
||
ArrayList<Integer> groups = (ArrayList<Integer>) books.stream().distinct().collect(Collectors.toList()); | ||
|
||
|
||
double price = 0; | ||
|
||
for(int i = 0;i<groups.size();i++){ | ||
books.remove(groups.get(i)); | ||
} | ||
|
||
|
||
try { | ||
price = CalculateTotalCost(books,priceSoFar + CostPerGroup(groups.size())); | ||
} catch (Exception e) { | ||
e.printStackTrace(); | ||
} | ||
minPrice = Math.min(minPrice, price); | ||
return minPrice; | ||
|
||
|
||
} | ||
|
||
private static double CostPerGroup(int groupSize) throws Exception{ | ||
double discountPercentage; | ||
switch (groupSize) | ||
{ | ||
case 1: | ||
discountPercentage = 0; | ||
break; | ||
case 2: | ||
discountPercentage = 5; | ||
break; | ||
case 3: | ||
discountPercentage = 10; | ||
break; | ||
case 4: | ||
discountPercentage = 20; | ||
break; | ||
case 5: | ||
discountPercentage = 25; | ||
break; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see a pretty clear relationship between Also wondering, is this really configuration data rather than business logic? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't the the relationship between Also I didn't understand your second question, can you develop and explain it ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just checked the php exemple of the exercise and saw a different version about the discount percentage :
So in Java, it will be :
It's this kind of relationship you're talking about ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or even simpler. Perhaps take it in two steps:
8 * (groupSize - 1) * 0.05d; Even better, avoid the use of magic numbers. Name the book price and discount increment, EG BOOK_PRICE * (groupSize - 1) * DISCOUNT_INCREMENT; There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As far as my "configuration vs logic" comment, it's not hard to imagine that the price of a book or the discount increment would be a business rule of the bookstore. In a production application, you would want to separate setting those values from the logic. You might even imagine a case in which you would have a class that is responsible for calculating the discount that is separate from the one that applies it to the user's purchase. In this example, I feel like calling these values out by defining them at the class level with clear names is probably enough. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 8 * (groupSize - 1) * 0.05d; Are you sure that this work ? Or maybe I'm missing something ? private double CostPerGroup(int groupSize) throws Exception{
if(groupSize > maxGroupSize || groupSize <= 0 )
throw new Exception("Invalide group size : " + groupSize );
double discountForOneBook = bookPrice * (groupSize - 1) * discountIncrement;
return (bookPrice * groupSize ) - (groupSize * discountForOneBook);
} But by running gradle for the test, I have 13 tests completed, 5 failed :
So, I prefer to upload this modifications and don't push now. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, I made an error! I thought the discount tiers were linear by private static double[] DISCOUNT_TIERS = {0,5,10,20,25}; //declare at class level
private double CostPerGroup(int groupSize) throws Exception{
if (groupSize < 1 || groupSize > 5){
throw new Exception("Invalid group size : " + groupSize );
}
return bookPrice * groupSize * (100 - DISCOUNT_TIERS[groupSize-1])/100;
} |
||
default: | ||
throw new Exception("Invalide group size : " + groupSize ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You'll want to change the spelling to |
||
} | ||
|
||
return 8 * groupSize * (100 - discountPercentage) / 100; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import static org.junit.Assert.assertEquals; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import org.junit.Test; | ||
|
||
public class BookStoreTest{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
@Test | ||
public void Basket_with_single_book(){ | ||
Integer[] p = {1}; | ||
ArrayList<Integer> books = new ArrayList<>(Arrays.asList(p)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
assertEquals(8,BookStore.CalculateTotalCost(books),2); | ||
} | ||
|
||
|
||
@Test | ||
public void Basket_with_two_of_same_book(){ | ||
Integer[] p = {1,1}; | ||
ArrayList<Integer> books = new ArrayList<>(Arrays.asList(p)); | ||
assertEquals(16,BookStore.CalculateTotalCost(books),2); | ||
} | ||
|
||
|
||
@Test | ||
public void Empty_basket(){ | ||
ArrayList<Integer> books = new ArrayList<>(); | ||
assertEquals(0,BookStore.CalculateTotalCost(books),2); | ||
} | ||
|
||
|
||
@Test | ||
public void Basket_with_two_different_books(){ | ||
Integer[] p = {1,2}; | ||
ArrayList<Integer> books = new ArrayList<>(Arrays.asList(p)); | ||
|
||
assertEquals(15.20,BookStore.CalculateTotalCost(books),2); | ||
} | ||
|
||
|
||
@Test | ||
public void Basket_with_three_different_books(){ | ||
Integer[] p = {1,2,3}; | ||
ArrayList<Integer> books = new ArrayList<>(Arrays.asList(p)); | ||
assertEquals(21.6,BookStore.CalculateTotalCost(books),2); | ||
} | ||
|
||
|
||
@Test | ||
public void Basket_with_four_different_books(){ | ||
Integer[] p = {1,2,3,4}; | ||
ArrayList<Integer> books = new ArrayList<>(Arrays.asList(p)); | ||
assertEquals(25.6,BookStore.CalculateTotalCost(books),2); | ||
|
||
} | ||
|
||
|
||
@Test | ||
public void Basket_with_five_different_books(){ | ||
Integer[] p = {1,2,3,4,5}; | ||
ArrayList<Integer> books = new ArrayList<>(Arrays.asList(p)); | ||
assertEquals(30,BookStore.CalculateTotalCost(books),2); | ||
} | ||
|
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like from this point on, the test suite diverges from the canonical test suite for this exercise. Is that intentional? All the remaining tests are extra, and these tests from the canonical spec are missing: {
"description": "Two groups of four is cheaper than group of five plus group of three",
"basket": [1,1,2,2,3,3,4,5],
"targetgrouping": [[1,2,3,4],[1,2,3,5]],
"expected": 51.20
},
{
"description": "Group of four plus group of two is cheaper than two groups of three",
"basket": [1,1,2,2,3,4],
"targetgrouping": [[1,2,3,4],[1,2]],
"expected": 40.8
},
{
"description": "Two each of first 4 books and 1 copy each of rest",
"basket": [1,1,2,2,3,3,4,4,5],
"targetgrouping": [[1,2,3,4,5],[1,2,3,4]],
"expected": 55.60
},
{
"description": "Two copies of each book",
"basket": [1,1,2,2,3,3,4,4,5,5],
"targetgrouping": [[1,2,3,4,5],[1,2,3,4,5]],
"expected": 60.00
},
{
"description": "Three copies of first book and 2 each of remaining",
"basket": [1,1,2,2,3,3,4,4,5,5,1],
"targetgrouping": [[1,2,3,4,5],[1,2,3,4,5],[1]],
"expected": 68.00
},
{
"description": "Three each of first 2 books and 2 each of remaining books",
"basket": [1,1,2,2,3,3,4,4,5,5,1,2],
"targetgrouping": [[1,2,3,4,5],[1,2,3,4,5],[1,2]],
"expected": 75.20
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I followed the test from the C# version, so this test is just a translation from C# to Java. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I see that! Thanks for adding the additional tests. Along the way, before we merge your changes, we'll need you to add the annotation |
||
@Test | ||
public void Basket_with_eight_books(){ | ||
Integer[] p = {1,1,2,2,3,3,4,5}; | ||
ArrayList<Integer> books = new ArrayList<>(Arrays.asList(p)); | ||
assertEquals(51.20,BookStore.CalculateTotalCost(books),2); | ||
} | ||
|
||
|
||
|
||
@Test | ||
public void Basket_with_nine_books(){ | ||
Integer[] p = {1,1,2,2,3,3,4,4,5}; | ||
ArrayList<Integer> books = new ArrayList<>(Arrays.asList(p)); | ||
assertEquals(55.60,BookStore.CalculateTotalCost(books),2); | ||
} | ||
|
||
@Test | ||
public void Basket_with_ten_books(){ | ||
Integer[] p = {1,1,2,2,3,3,4,4,5,5}; | ||
ArrayList<Integer> books = new ArrayList<>(Arrays.asList(p)); | ||
assertEquals(60,BookStore.CalculateTotalCost(books),2); | ||
} | ||
|
||
|
||
@Test | ||
public void Basket_with_eleven_books(){ | ||
Integer[] p = {1,1,2,2,3,3,4,4,5,5,1}; | ||
ArrayList<Integer> books = new ArrayList<>(Arrays.asList(p)); | ||
assertEquals(68,BookStore.CalculateTotalCost(books),2); | ||
} | ||
|
||
|
||
@Test | ||
public void Basket_with_twelve_books(){ | ||
Integer[] p = {1,1,2,2,3,3,4,4,5,5,1,2}; | ||
ArrayList<Integer> books = new ArrayList<>(Arrays.asList(p)); | ||
assertEquals(75.20,BookStore.CalculateTotalCost(books),2); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In English we would say
Bookstore
rather thanBookStore
. Also, the folder name should likewise be one wordbookstore
without the hypen.