/*
 *  $Id: CDNAgent_GSchenato.java,v 1.3 2008/07/07 02:08:41 nemo Exp $
 * 
 * Copyright (c) 2008, Nemo Semret.
 * 
 * Your agent must implement this interface. All the constants of the
 * game are set here as well. Do not hardcode the constants in your
 * agent. You should refer to them as these static variables. Some of
 * these values may change in the final run so you must design your
 * algorithm for the general case.
 */

package edu.columbia.ee.e6773;

/* To use random generator */
import java.util.Random;

/**
 * Interface for player agent representing Information Provider in Content Delivery Game.
 * http://www.ee.columbia.edu/~nemo/teaching/Content_Delivery_Game.html
 * @author Nemo Semret
 */
public class CDNAgent_GSchenato implements CDNAgent {
    /* set day counter to zero */
    public int daycount = 0;
    /* set the guess of the number of players to zero */
    public double N_guess = 0;
    /* array b */
    public long b_i[];
    /* array c */
    public long c_i[];
    Random generator = new Random(System.currentTimeMillis());
    /**
     * At the beginning of each day, the system generates today's
     * value of X and gives it to each of the players. X is random iid
     * with distribution F(x) = 1 - P (X >x) = 1- (x_min/x)^2, for x
     * >= xmin, and 0 otherwise, with x__min = 0.5 Gbytes = 536870912 bytes.
     *
     * @param the value of X in bytes
     * @return a boolean action vector representing his decisions to
     * cache (k-th element is true iff this provider decided to cache
     * in network k)
     */
    
    public boolean[] startDay(long X)
    {
        boolean [] a;
        int index = 0;
        int cache_net = K;
        double N_guess_old = 0;
        double N_guess_new = 0;
        
        a = new boolean [K];
        for (int i=0; i<K; i++)
            {
		a[i] = false;
		/* Set all the values to false */
            }
        daycount += 1;
        
        /** for day 1, cache a random network to try to guess the total number of players.
	 *  Being sure that the network that we cached has (1-q)D_k users downloading data
         *  from network and not from cache, and using the expected value 1/lambda as average
         *  number of users D_k (10,000 users; b_ik is (1-q)D_k/N hence we can guess N
	 */
        if (daycount == 1)
	    {
		int rnd = generator.nextInt(K);
		a[rnd] = true;
		return a;
	    }
        else
	    {
		for(int i=0; i<K; i++)
		    { /* Find the cached network*/
			if (c_i[i] > 0)
			    {
				cache_net = i;
			    }
		    }
		if (cache_net != K) /* It means one network has been cached, I can guess N */
		    {
			if (N_guess == 0) /* No previous guessing */
			    {
				N_guess = (1-q)*10000/b_i[cache_net];
			    }
			else /* Already previously guessed; average with new guess*/
			    {
				if(b_i[cache_net] > 0) { // FIXED to avoid div by zero
				    N_guess_old = N_guess;
				    N_guess_new = (1-q)*10000/b_i[cache_net];
				    N_guess = (N_guess_old+N_guess_new)/2;
				}
			    }
		    }
		if (cache_net != K)
		    {
			if (c_i[cache_net]*V > (Pc*(X/(1024^3))+Sc)) /* Caching has been profitable */
			    {
				a[cache_net] = true; /* keep on caching that net */
				return a;
			    }
			else /* caching that network has not been profitable */
			    /* try to see if we can cache another one       */
			    {
				for(int i=1; i<K; i++)
				    {
					if(b_i[i] > b_i[index])
					    /** Find the index corresponding to the maximum value for b_i.
					     *  If there exists a network that has not been cached, this is most likely the one.
					     *  Indeed, if a network does not have any cached version of the data all the
					     *  users will try to download the data directly, b_i should be higher.
					     *  Network that has the least probability of having been cached by another
					     *  player. Hence, try to cache this network.
					     */
					    {
						index=i;
					    }
				    }
				/* Cache the network indexed by 'index' only if there is a reasonable probability
				   of getting some reward. We can guess the reward using the mean value of D_k
				   =10000 and assuming that every player caches at most one network since caching
				   very very expensive. With this assumption we can assume that each network is
				   cached by N/K people (if N>10). The reward is (c_ik*V)-(Pc*(X/1024^3) + Sc). c_ik
				   guessed with the idea just mentioned is given by c_ik=(q*D_k)/(N/K). If N<K we
				   can think that the network has not been cached.
				*/
				if (N_guess < K)
				    {
					if (((q*10000)*V) > (Pc*X/(1024^3)+Sc))
					    {
						a[index] = true;
					    } 
				    }   
				else
				    {
					if ((((K*q*10000)/N_guess)*V) > (Pc*X/(1024^3)+Sc))
					    {
						a[index] = true;
					    }     
				    }
				return a;
			    }
		    }
	    }
	return a;
    }
    
    
    public void endDay(long[] b, long[] c)
    {
        /* Copying vectors b and c to vectors b_i and c_i to have them ready */
        /* for the next day */
        b_i = b;
        c_i = c;        
    }
}
