// Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.geocities.com/kpdus/jad.html
// Decompiler options: packimports(3) fieldsfirst 
// Source File Name:   FlowShop.java

package lt.ktu.gmj.tasks;

import java.io.*;
import java.net.URL;
import java.util.Random;
import java.util.StringTokenizer;
import lt.ktu.HostNameRetriever;
import lt.ktu.gmj.*;
import lt.ktu.gmj.propertySheet.PropertyManager;
import lt.ktu.gmj.propertySheet.UrlProperty;

// Referenced classes of package lt.ktu.gmj.tasks:
//			FlowShopDomain, Job, FlowShopDataUrlProvider, Step

public class FlowShop
	implements Task
{

	private FlowShopDomain domain;
	private Random rnd;
	private final int DIM = 3;
	private final int NUMBER_OF_MACHINES = 40;
	private final int NUMBER_OF_JOBS = 7;
	private Job job[];
	private boolean initialized;
	public String data_url;

	public FlowShop()
	{
		domain = new FlowShopDomain();
		rnd = new Random(System.currentTimeMillis());
		job = new Job[7];
		initialized = false;
		for(int i = 0; i < 7; i++)
			job[i] = new Job();

		data_url = new String(HostNameRetriever.getCodeBase() + "jobtimes.txt");
	}

	private void calc_heuristics(double h[])
	{
		for(int jj = 0; jj < 7; jj++)
			if(!job[jj].IsFinished())
			{
				double ej = job[jj].getStep(0).getTime() < job[jj].getStep(39).getTime() ? 1.0D : -1D;
				double minj = (1.0D / 0.0D);
				for(int k = 0; k < 39; k++)
					if(minj > job[jj].getStep(k).getTime() + job[jj].getStep(k + 1).getTime())
						minj = job[jj].getStep(k).getTime() + job[jj].getStep(k + 1).getTime();

				h[jj] = ej / minj;
			}

		double minA = (1.0D / 0.0D);
		double maxA = (-1.0D / 0.0D);
		for(int jj = 0; jj < 7; jj++)
			if(!job[jj].IsFinished())
			{
				minA = Math.min(minA, h[jj]);
				maxA = Math.max(maxA, h[jj]);
			}

		if(minA == maxA)
		{
			for(int jj = 0; jj < 7; jj++)
				h[jj] = 1.0D;

		} else
		{
			for(int jj = 0; jj < 7; jj++)
				if(!job[jj].IsFinished())
					h[jj] = (h[jj] - minA) / (maxA - minA);

		}
	}

	public void customize(PropertyManager manager)
	{
		manager.add(new UrlProperty("URL of data file", new FlowShopDataUrlProvider(this)));
	}

	private void do_selection(int selection, double machine_time[], double job_time[])
	{
		job_time[selection] = 0.0D;
		for(int i = 0; i < 40; i++)
		{
			machine_time[i] = Math.max(job_time[selection], machine_time[i]) + job[selection].getStep(i).getTime();
			job_time[selection] = Math.max(machine_time[i], job_time[selection]);
		}

		job[selection].Use();
	}

	public Domain domain()
	{
		return domain;
	}

	public IResult f(Point pt)
	{
		double x[] = new double[3];
		double fmin = 1.7976931348623157E+308D;
		double sum = pt.x[0] + pt.x[1] + pt.x[2];
		x[0] = pt.x[0] / sum;
		x[1] = pt.x[1] / sum;
		x[2] = pt.x[2] / sum;
		if(!initialized)
		{
			try
			{
				input();
			}
			catch(Exception e)
			{
				System.out.println("Error!!! Bad data: " + e);
			}
			initialized = true;
		}
		return new SimpleResult(fif(x));
	}

	private double fif(double x[])
	{
		double machine_time[] = new double[40];
		double job_time[] = new double[7];
		for(int i = 0; i < 7; i++)
		{
			job[i].Init();
			job_time[i] = 0.0D;
		}

		for(int i = 0; i < 40; i++)
			machine_time[i] = 0.0D;

		boolean testi = true;
		double h[] = new double[7];
		while(testi) 
		{
			int n = 0;
			int selection = 0;
			double a2 = 0.0D;
			int a3 = 0;
			calc_heuristics(h);
			double maxh = (-1.0D / 0.0D);
			for(int i = 0; i < 7; i++)
				if(!job[i].IsFinished())
				{
					a2 += h[i];
					if(maxh < h[i])
					{
						maxh = h[i];
						a3 = i;
					}
				}

			a2 = 1.0D / a2;
			double eps = rnd.nextDouble();
			double r = 0.0D;
			for(int i = 0; i < 7; i++)
				if(job[i].IsFinished())
				{
					n++;
				} else
				{
					selection = i;
					r += (1.0D / (double)(7 - n)) * x[0] + a2 * x[1] * h[i] + x[2] * (double)(i == a3 ? 1 : 0);
					if(r > eps)
					{
						do_selection(i, machine_time, job_time);
						i = 7;
					}
				}

			if(n == 7)
				testi = false;
			if(n == 6)
			{
				do_selection(selection, machine_time, job_time);
				testi = false;
			}
		}
		double max = 0.0D;
		for(int i = 0; i < 7; i++)
			max = Math.max(max, job_time[i]);

		return max;
	}

	private void input()
		throws IOException
	{
		String row = new String();
		BufferedReader file = new BufferedReader(new InputStreamReader((new URL(data_url)).openStream()));
		for(int k = 0; k < 7; k++)
		{
			row = file.readLine();
			StringTokenizer st = new StringTokenizer(row);
			for(int i = 0; i < 40; i++)
				job[k].Add(Double.valueOf(st.nextToken()).doubleValue());

		}

	}
}
