class SubtractiveMixingStrategy implements MixingStrategy {

    public Liquid mixLiquids(LinkedList<Liquid> inflow) {
        if (inflow == null || inflow.isEmpty()) {
            throw new IllegalArgumentException("Must at least mix one liquid");
        }

        // Count full amount first...
        float fullAmount = 0;
        for (Liquid liquid : inflow) {
            fullAmount += liquid.getAmount();
        }

        if (Math.abs(fullAmount) < 0.000001) {
            return new Liquid(0, inflow.peekFirst().getTemperature(), inflow.peekFirst().getColor());
        }

        // Real calculations...
        double c = 0;
        double m = 0;
        double y = 0;
        float temperature = 0;

        for (Liquid liquid : inflow) {
            c += (liquid.getAmount() / fullAmount) * liquid.getColor().getCyan();
            m += (liquid.getAmount() / fullAmount) * liquid.getColor().getMagenta();
            y += (liquid.getAmount() / fullAmount) * liquid.getColor().getYellow();

            temperature += (liquid.getAmount() / fullAmount) * liquid.getTemperature();
        }

        // Fix floating point inaccuracies
        c = Math.min(1, c);
        m = Math.min(1, m);
        y = Math.min(1, y);
        temperature = Math.min(SimulationConstants.MAX_TEMPERATURE,
                Math.max(SimulationConstants.MIN_TEMPERATURE, temperature));

        return new Liquid(fullAmount, temperature, new Color(c, m, y));
    }

}

class SubtractiveMixingStrategyTest {

    @Test
    public void testMixingTwoLiquidsDifferentAmounts() {

        LinkedList<Liquid> liquids = new LinkedList<>();
        liquids.add(new Liquid(300, 340, new Color(0x880000)));
        liquids.add(new Liquid(100, 300, new Color(0x440000)));

        Liquid result = new SubtractiveMixingStrategy().mixLiquids(liquids);
        assertEquals(new Liquid(400, 330, new Color(0x770000)), result);
    }

}