<file_sep>package com.woolfer.varteq.tasks.horseTrack.objectTypes;

import sun.invoke.empty.Empty;

import java.util.Currency;
import java.util.Iterator;
import java.util.Map;

/**
 * Created by pavlenko on 3/14/2015.
 */
public class MoneyOT {

    protected Map<Integer, Integer> cash;
    protected Currency currency;

    public MoneyOT(Currency currency) {
        this.currency = currency;
    }

    public Map<Integer, Integer> getCash() {
        return cash;
    }

    public void setCash(Map<Integer, Integer> cash) {
        this.cash = cash;
    }

    public Currency getCurrency() {
        return currency;
    }

    public void setCurrency(Currency currency) {
        this.currency = currency;
    }

    @Override
    public String toString() {
        StringBuilder str = new StringBuilder();
        Iterator iter = cash.entrySet().iterator();
        String symbol = currency.getSymbol();

        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next();
            str.append(symbol);
            str.append(entry.getKey() + ", ");
            str.append(entry.getValue() + "\n");
        }
        return str.toString();
    }
}
<file_sep>package com.woolfer.varteq.tasks.horseTrack.impl;

import com.woolfer.varteq.tasks.horseTrack.events.Payouts;
import com.woolfer.varteq.tasks.horseTrack.objectTypes.HorseOT;
import com.woolfer.varteq.tasks.horseTrack.commons.Horses;
import com.woolfer.varteq.tasks.horseTrack.objectTypes.MoneyOT;
import com.woolfer.varteq.tasks.horseTrack.services.MachineService;

import java.util.*;

/**
 * Created by pavlenko on 3/14/2015.
 */
public class MachineServiceImpl implements MachineService {

    private final Map<Integer, HorseOT> horsesList;
    private DollarTellerMachine tellerMachine;
    private int winHorseId;
    private int amount;
    private int winningAmount;
    private MoneyOT gainings;

    public MachineServiceImpl(DollarTellerMachine tellerMachine, Map<Integer, HorseOT> horsesList) {
        this.tellerMachine = tellerMachine;
        this.horsesList = horsesList;
    }

    @Override
    public void setBet(int horseId, int amount) {
        this.winHorseId = horseId;
        this.amount = amount;
    }

    @Override
    public String checkResult() {
        HorseOT horse = horsesList.get(winHorseId);
        if (horse.getLastResult() == Horses.WON) {
            winningAmount = getWinningAmount(amount, horse.getOdds());
            if (dispensing(winningAmount)) {
                Payouts.payoutWin(horse.getName() + "," + tellerMachine.getCurrency().getSymbol() + winningAmount);
                Payouts.dispensing(gainings.toString());
            }
        } else {
            Payouts.noPayout(horse.getName());
        }
        return null;
    }

    private boolean dispensing(int winningAmount) {
        Map<Integer, Integer> cash = new TreeMap<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2.compareTo(o1);
            }
        });
        Map<Integer, Integer> cashTellerMachine = tellerMachine.getMoney().getCash();
        cash.putAll(cashTellerMachine);

        Map<Integer, Integer> dispensingList = new TreeMap();
        for (Map.Entry entry : cashTellerMachine.entrySet()) {
            dispensingList.put((Integer) entry.getKey(), 0);
        }

        int payoutResult = 0;
        int remainderPayment = winningAmount;
        for (Map.Entry entry : cash.entrySet()) {

            Integer denominationInt = (Integer) entry.getKey();
            int denomination = denominationInt.intValue();
            Integer inventoryInt = (Integer) entry.getValue();
            int inventory = inventoryInt.intValue();

            int count = remainderPayment / denomination;
            if (inventory > 0) {
                if (count > inventory) count = inventory;
                payoutResult += count * denomination;
                inventory -= count;
                entry.setValue(Integer.valueOf(inventory));
                dispensingList.put(denominationInt, count);
                remainderPayment = remainderPayment - count * denomination;
            }
            if (payoutResult == winningAmount) {
                gainings = new MoneyOT(tellerMachine.getCurrency());
                gainings.setCash(dispensingList);
                tellerMachine.getMoney().setCash(new TreeMap<>(cash));
                return true;
            }
        }
        if (payoutResult != winningAmount) {
            Payouts.insufficientFunds(String.valueOf(winningAmount));
            return false;
        }
        return false;
    }

    private int getWinningAmount(int amount, int odds) {
        return amount * odds;
    }
}
<file_sep>package com.woolfer.varteq.tasks.horseTrack.services;

/**
 * Created by pavlenko on 3/14/2015.
 */
public interface MachineService {
    public void setBet(int horseId, int amount);
    public String checkResult();
}
<file_sep>package com.woolfer.varteq.tasks.horseTrack.services;

import java.util.Collections;

/**
 * Created by pavlenko on 3/14/2015.
 */
public interface HorseService {
    public void declareHorses();
    public void setWinner(int horseId);
    public String showHorsesList();
}
<file_sep>package com.woolfer.varteq.tasks.horseTrack.impl;

import com.woolfer.varteq.tasks.horseTrack.commons.Denominations;
import com.woolfer.varteq.tasks.horseTrack.objectTypes.MoneyOT;
import com.woolfer.varteq.tasks.horseTrack.objectTypes.TellerMachine;

import java.util.*;

/**
 * Created by pavlenko on 3/15/2015.
 */
public class DollarTellerMachine implements TellerMachine {

    private MoneyOT money;
    private String currencyCode = "USD";
    private Currency currency = Currency.getInstance(currencyCode);

    public DollarTellerMachine() {
        money = new MoneyOT(currency);
        money.setCash(new TreeMap<Integer, Integer>());
        generateCashInventory(money.getCash());
    }

    @Override
    public MoneyOT getMoney() {
        return money;
    }

    @Override
    public void setMoney(MoneyOT money) {
        this.money = money;
    }

    @Override
    public void generateCashInventory(Map<Integer, Integer> cashInventory){

        cashInventory.put(Denominations.ONE.getDenomination(), 10);
        cashInventory.put(Denominations.FIVE.getDenomination(), 10);
        cashInventory.put(Denominations.TEN.getDenomination(), 10);
        cashInventory.put(Denominations.TWENTY.getDenomination(), 10);
        cashInventory.put(Denominations.ONE_HUNDRED.getDenomination(), 10);
    }

    @Override
    public void restockCashInventory(){
        Map cashInventory = money.getCash();
        if(cashInventory != null) {
            cashInventory.clear();
            generateCashInventory(cashInventory);
        }
    }

    public String getCurrencyCode() {
        return currencyCode;
    }

    public Currency getCurrency() {
        return currency;
    }
}
<file_sep>package com.woolfer.varteq.tasks.horseTrack.commons;

/**
 * Created by pavlenko on 3/14/2015.
 */
public enum Commands {
    RESTOCK("R"), QUIT("Q"), WIN("W");

    private String command;
    Commands(String command) {
        this.command = command;
    }
    public String getCommand(){
        return command;
    }
}
