package apostov;

import static apostov.Suit.CLUBS;
import static apostov.Suit.DIAMONDS;
import static apostov.Suit.HEARTS;
import static apostov.Suit.SPADES;
import static apostov.Value.ACE;
import static apostov.Value.KING;
import static apostov.Value.QUEEN;
import static apostov.Value.SEVEN;
import static apostov.Value.TEN;
import static apostov.Value.TWO;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.Map;

import org.apache.commons.math3.fraction.Fraction;
import org.junit.Test;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;

public class HandResultEnumeratorTest {

	@Test
	public void test01() {
		final HolecardHand aces = new HolecardHand(new Card(ACE, CLUBS), new Card(ACE, SPADES));
		final HolecardHand trash = new HolecardHand(new Card(TWO, CLUBS), new Card(SEVEN, SPADES));
		
		final Map<HolecardHand, Fraction> percentages = computePercentages(aces, trash);
		assertTrue(percentages.get(aces).doubleValue() > 0.8);
		assertTrue(percentages.get(trash).doubleValue() < 0.2);
	}

	@Test
	public void test02() {
		final HolecardHand aceTen = new HolecardHand(new Card(ACE, CLUBS), new Card(TEN, SPADES));
		final HolecardHand queenTen = new HolecardHand(new Card(QUEEN, DIAMONDS), new Card(TEN, HEARTS));
		
		final Map<HolecardHand, Fraction> percentages = computePercentages(aceTen, queenTen);
		assertTrue(percentages.get(aceTen).doubleValue() > 0.7);
		assertTrue(percentages.get(queenTen).doubleValue() < 0.3);
	}
	
	@Test
	public void test03() {
		final HolecardHand aces = new HolecardHand(new Card(ACE, CLUBS), new Card(ACE, SPADES));
		final HolecardHand trash = new HolecardHand(new Card(TWO, CLUBS), new Card(SEVEN, SPADES));
		
		final ImmutableList<Card> board = ImmutableList.of(new Card(TWO, DIAMONDS), new Card(TWO, SPADES), new Card(TEN, HEARTS));
		
		final Map<HolecardHand, Fraction> percentages = new HandResultEnumerator().enumerateBoardsAndMeasureWins(
				ImmutableList.of(aces, trash),
				board);
		System.out.println("Board: " + board);
		displayResults(percentages);
		assertTrue(percentages.get(aces).doubleValue() < percentages.get(trash).doubleValue());
	}
	
	@Test
	public void test04() {
		final HolecardHand aces = new HolecardHand(new Card(ACE, CLUBS), new Card(ACE, SPADES));
		final HolecardHand trash = new HolecardHand(new Card(TWO, CLUBS), new Card(SEVEN, SPADES));
		
		final ImmutableList<Card> board = ImmutableList.of(new Card(TWO, DIAMONDS), new Card(TWO, SPADES), new Card(TWO, HEARTS));
		
		final Map<HolecardHand, Fraction> percentages = new HandResultEnumerator().enumerateBoardsAndMeasureWins(
				ImmutableList.of(aces, trash),
				board);
		System.out.println("Board: " + board);
		displayResults(percentages);
		assertTrue(percentages.get(aces).doubleValue() < percentages.get(trash).doubleValue());
	}
	
	@Test
	public void test05() {
		final HolecardHand aces = new HolecardHand(new Card(ACE, CLUBS), new Card(ACE, SPADES));
		final HolecardHand trash = new HolecardHand(new Card(TWO, CLUBS), new Card(SEVEN, SPADES));
		
		final ImmutableList<Card> board = ImmutableList.of(
				new Card(TWO, DIAMONDS),
				new Card(TWO, SPADES),
				new Card(TWO, HEARTS),
				new Card(ACE, DIAMONDS),
				new Card(ACE, HEARTS)
		);
		
		final Map<HolecardHand, Fraction> percentages = new HandResultEnumerator().enumerateBoardsAndMeasureWins(
				ImmutableList.of(aces, trash),
				board);
		System.out.println("Board: " + board);
		displayResults(percentages);
		assertTrue(percentages.get(aces).equals(Fraction.ONE));
		assertTrue(percentages.get(trash).equals(Fraction.ZERO));
	}
	
	@Test
	public void test06() {
		final HolecardHand aces = new HolecardHand(new Card(ACE, CLUBS), new Card(ACE, SPADES));
		final HolecardHand trash = new HolecardHand(new Card(TWO, CLUBS), new Card(SEVEN, SPADES));
		
		final ImmutableList<Card> board = ImmutableList.of(
				new Card(TWO, DIAMONDS),
				new Card(TWO, SPADES),
				new Card(TWO, HEARTS),
				new Card(ACE, DIAMONDS),
				new Card(KING, HEARTS)
		);
		
		final Map<HolecardHand, Fraction> percentages = new HandResultEnumerator().enumerateBoardsAndMeasureWins(
				ImmutableList.of(aces, trash),
				board);
		System.out.println("Board: " + board);
		displayResults(percentages);
		assertTrue(percentages.get(aces).equals(Fraction.ZERO));
		assertTrue(percentages.get(trash).equals(Fraction.ONE));
	}

	private Map<HolecardHand, Fraction> computePercentages(final HolecardHand h1, final HolecardHand h2) {
		final Map<HolecardHand, Fraction> result = new HandResultEnumerator().enumerateBoardsAndMeasureWins(ImmutableList.of(h1, h2));
		final Fraction sum = result.values().stream().reduce((x,y) -> x.add(y)).get();
		assertEquals(1, sum.intValue());
		displayResults(result);
		return result;
	}

	private void displayResults(final Map<HolecardHand, Fraction> result) {
		System.out.println(Maps.transformValues(result, f -> String.format("%.02f%%", 100 * f.doubleValue())));
	}
	
}

@@ -721,14 +721,30 @@
 oid 
-test01
+acesVersusTrashPreflop
 () %7B
@@ -1168,14 +1168,35 @@
 oid 
-test02
+aceTenVersusQueenTenPreflop
 () %7B
@@ -1639,14 +1639,38 @@
 oid 
-test03
+acesVersusTrashOnLuckySetBoard
 () %7B
@@ -2347,14 +2347,39 @@
 oid 
-test04
+acesVersusTrashOnLuckyQuadBoard
 () %7B
@@ -3056,14 +3056,31 @@
 oid 
-test05
+acesVersusTrashShowdown
 () %7B
@@ -3864,14 +3864,38 @@
 oid 
-test06
+acesVersusTrashBadBeatShowdown
 () %7B

Make a few test method names more explicit