-
Notifications
You must be signed in to change notification settings - Fork 0
/
ChipDistributionCalculatorForBonusTwo.java
executable file
·196 lines (184 loc) · 7.14 KB
/
ChipDistributionCalculatorForBonusTwo.java
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
/*
* @(#)ChipDistributionCalculatorBonusTwo.java 2010/06/03
*
* Copyright (c) 2010 XXXXXX
* All rights reserved.
*
* This software is the confidential and proprietary information of XXXXXXXX
* ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with XXXXXX.
*/
package com.company.application.bo.calculator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.company.application.comparator.ChipColorAndQuantityComparator;
import com.company.application.domain.ChipColorAndQuantity;
import com.company.application.domain.PokerChipDistributionForBonusTwo;
import com.company.application.domain.PokerChipDistributionResult;
import com.company.application.domain.PokerChipDistributionResultList;
import com.company.application.domain.ResponseType;
/**
* Class calculates the optimum distribution of poker chips that maximizes the
* amount of chips that each player receives.
*
* @author Desmond O'Leary
*
*/
public class ChipDistributionCalculatorForBonusTwo extends
ChipDistributionCalculatorBase implements
IChipDistributionCalculator<PokerChipDistributionForBonusTwo> {
/** normal currency values */
public static final double[] availableCurrencies = { 0.01, 0.05, 0.10,
0.25, 0.50, 1.00, 2.00, 5.00, 10.00, 20.00, 50.00, 100.00, 1000.00 };
public final PokerChipDistributionResultList calculate(
final PokerChipDistributionForBonusTwo input) {
double buyInAmount = input.getBuyInAmount();
List<Integer> maximumAvailableQuantities = extractQuantitiesFrom(input
.getChipDetailsList(), input.getPlayerCount());
Map<Double, Integer> optimalCurrencyAndQuantityRangeMap = findOptimalCurrencyAndQuantityRangeFrom(
availableCurrencies, maximumAvailableQuantities, buyInAmount);
Map<Double, Integer> currencyAndQuantityMatchingBuyInAmountMap = getCurrencyAndQuantitiesMatchingBuyInAmountForBonusTwo(
optimalCurrencyAndQuantityRangeMap, buyInAmount);
List<String> colors = fetchColorByQuantityInDescendingOrder(input
.getChipDetailsList());
return new PokerChipDistributionResultList(merge(
currencyAndQuantityMatchingBuyInAmountMap, colors),
ResponseType.BONUS_TWO);
}
/**
* Extracts all quantity amounts from input
*
* @param chipDetailsList
* collection of chip details with color and associated quantity.
* @return
*/
private List<Integer> extractQuantitiesFrom(
final List<ChipColorAndQuantity> chipDetailsList,
final int participantCount) {
List<Integer> result = new ArrayList<Integer>();
for (ChipColorAndQuantity chipDetails : chipDetailsList) {
result.add(chipDetails.getQuantity() / participantCount);
}
return result;
}
/**
* Come up with a range of currencies and associated quantities that totaled
* together amount to greater than the buy in amount. This range will
* include currency and maximum quantities available. Note that the highest
* quantity will start with the lowest currency to ensure that the maximum
* amount of chips can be returned.
*
* @param availableCurrencies
* available currency values
* @param maximumAvailableQuantities
* maximum available quantities
* @param buyInAmount
* buy in amount
* @return map with key as the currency/denomination and value as associated
* quantity
*/
private Map<Double, Integer> findOptimalCurrencyAndQuantityRangeFrom(
final double[] availableCurrencies,
final List<Integer> maximumAvailableQuantities,
final double buyInAmount) {
Map<Double, Integer> result = new HashMap<Double, Integer>();
for (int index = 0; index <= availableCurrencies.length
- maximumAvailableQuantities.size(); index++) {
List<Double> currencyRange = getCurrencyRangeFrom(
availableCurrencies, availableCurrencies[index],
maximumAvailableQuantities.size());
double maximumAmount = maximumAmountForBonusTwoFrom(currencyRange,
maximumAvailableQuantities);
if (maximumAmount >= buyInAmount) {
for (int index2 = 0; index2 < currencyRange.size(); index2++) {
result.put(currencyRange.get(index2),
maximumAvailableQuantities.get(index2));
}
return result;
}
}
throw new IllegalArgumentException(String.format(
"Unable to find currency range to match buy in amount '$%.2f'",
buyInAmount));
}
/**
* fetch currency collection in the range of given input.
*
* @param availableCurrencies
* available currency values
* @param minimumAmount
* currency amount that will act as the starting index
* @param quantity
* denotes the range amount from the starting index (minimum
* amount)
* @return list of currencies
*/
private List<Double> getCurrencyRangeFrom(
final double[] availableCurrencies, final double minimumCurrency,
final int quantity) {
List<Double> result = new ArrayList<Double>();
for (double currency : availableCurrencies) {
if (currency >= minimumCurrency && result.size() != quantity) {
result.add(currency);
}
}
if (result.size() != quantity) {
throw new IllegalArgumentException();
}
return result;
}
/**
* sorts colors by associated quantity in descending order and returns as
* list of colors.
*
* @param chipDetailsList
* list of chip details that includes color and quantity
* @return list of colors
*/
private List<String> fetchColorByQuantityInDescendingOrder(
final List<ChipColorAndQuantity> chipDetailsList) {
List<String> result = new ArrayList<String>();
Collections.sort(chipDetailsList, new ChipColorAndQuantityComparator());
for (ChipColorAndQuantity chipColorAndQuantity : chipDetailsList) {
result.add(chipColorAndQuantity.getColor());
}
return result;
}
/**
* Merges denomination and quantity collection with colors list
*
* @param matchingCurrencyAndQuantityMap
* map with key as the currency/denomination and value as
* associated quantity that matches buy in amount
* @param colors
* list of colors
* @return result collection with each poker chip items with color,
* denomination and quantity
*/
private List<PokerChipDistributionResult> merge(
final Map<Double, Integer> matchingCurrencyAndQuantityMap,
final List<String> colors) {
List<PokerChipDistributionResult> result = new ArrayList<PokerChipDistributionResult>();
Iterator<Double> keys = fetchSortedKeysInDescendingOrderUsing(matchingCurrencyAndQuantityMap);
for (int index = 0; keys.hasNext(); index++) {
String color = colors.get(index);
double denomination = (Double) keys.next();
int quantity = matchingCurrencyAndQuantityMap.get(denomination);
result.add(new PokerChipDistributionResult(color, String.format(
"$%.2f", denomination), quantity));
}
return result;
}
// TODO: will need to be removed going forward as error handling will be
// done in a separate class.
private boolean isSatisfiedBy(final PokerChipDistributionForBonusTwo input) {
// TODO Add proper error handling here
return true;
}
}