package tekoalyhaaste.goodvsevil.humans;

import tekoalyhaaste.goodvsevil.util.Random;

/** Analyzes the way others changes sides and attempts to stay at the losing side
 * to gain a streak.
 * 
 * <br>As of version 2, ReversePsychologist only analyzes the last 20 rounds and
 * frequently creeps back to the top spot 1 once held.
 * 
 * @author Mikko*/
public final class ReversePsychologist2 extends Human {

	@Override
	public String takeSides(String history) throws Exception {
		// Always start with good
		if(history.equals("")) { return "good"; }
		
		// Initializes variables
		int commaInd = history.indexOf(',');
		Player[] players = new Player[commaInd == -1 ? history.length() : history.substring(0, commaInd).length()];
		int playersLen = players.length;
		int turns = commas(history)+1;
		
		// Initializes players' histories
		int good = 0, evil = 0;
		int actions = playersLen * turns;
		int switches = 0;
		for(int i = 0; i < players.length; i++) {
			StringBuilder sb = new StringBuilder();
			for(int turn = 0; turn < turns; turn++) {
				// players * turn + playerInd + turn
				sb.append(history.charAt(playersLen * turn + i + turn));
			}
			Player player = players[i] = new Player(sb.toString());
			
			// Measures popularity of good and evil last round
			char prev = player.history.charAt(0);
			for(int hisInd = 1; hisInd < player.history.length(); hisInd++) {
				char chr = player.history.charAt(hisInd);
				if(chr != prev) { prev = chr; player.switches++; }
			}
			if(prev=='1') { good++; } else { evil++; }
			
			switches += player.switches;
		}
		
		double sperc = ((double) switches / (double) actions);
		sperc = sperc > 0.25 ? sperc * 4.0 : sperc / 4.0;
		boolean shouldSwitch = new Random().nextDouble() < sperc;
		
		boolean choice = good > evil ? true : false;
		if(shouldSwitch) { choice = !choice; }
		
		return !choice ? "good" : "evil";
	}
	
	private static class Player {
		
		private int switches = 0;
		private String history = "";
		
		private Player(String str) { 
			history = str;
			// Only analyzes last 20 rounds
			if(history.length() > 20) {
				history = history.substring(history.length() - 20);
			}
		}
	}
	
	private static int commas(String s) {
		return (int) s.chars().filter(c -> c==',').count();
	}
	
}