/*
 * Created on 28/09/2004, 17:18:01
 *
*/
package compphys_640364;


/**
 * @author Patrick Donelan
 * 
 */
public class AppletWorker extends Thread {
    public static final int RUNNING = 0;
    public static final int PAUSED = 1;
    public static final int STOPPED = 2;
    public static final int THERMALISING = 3;
    public static final int AUTOMATING = 4;
	
	private int update_interval = 100;
    
    public int algorithm_status = STOPPED;
    public int thread_status = STOPPED;
    private MultiThreadedApplet mta;
	private Lattice l;
	public int sweeps = 0;
	public int thermCounter = 0;
    
    public AppletWorker(MultiThreadedApplet mta){
        this.mta = mta;
        l = new Lattice(mta, this);
        mta.setLatticeReference(l);
    }
    
    public String get_algorithm_status() {
        if (algorithm_status == RUNNING){
            return "RUNNING";
        } else if (algorithm_status == PAUSED){
            return "PAUSED";
        } else if (algorithm_status == STOPPED){
            return "STOPPED";
        } else {
            return "";
        }
    }
    
    // This function is called when the thread starts
    public void run() {
        thread_status = RUNNING; // Record that thread has started
        
        while (thread_status == RUNNING) {    
            // We spend all our time in this loop
            
            if (algorithm_status==RUNNING){
                sweep();
            } else if (algorithm_status==THERMALISING) {
                if (thermCounter>0){
                    sweep();
                    thermCounter--;
                } else {
                    algorithm_status=PAUSED;
                }
            }
        }
    }
    
    public void sweep() {
        l.sweep();
        sweeps++;
        if (thread_status != AUTOMATING || (sweeps % Settings.updateSweepsWhileAutomatingInterval == 0)){
            mta.updateSweepsLabel(sweeps);
        }
        if (Settings.calculateMag) {
            mta.updateMagLabel(l.magnetisation());
        }
    }
    
    public void stop_thread() {
        thread_status = STOPPED;
    }
    
    public void start_algorithm() {
        algorithm_status = RUNNING;
    }
    
    public void pause_algorithm() {
        algorithm_status = PAUSED;
    }
    
    public void stop_algorithm() {
        algorithm_status = STOPPED;
    }
    
    public void thermalise() {
        thermCounter = Settings.thermaliseSweeps;
        algorithm_status = THERMALISING;
    }
    
    public void automate() {
        // Stop the main thread
        thread_status = AUTOMATING;
                
        System.out.println("Beta\tMag\tError");
//        for (double b=0.1; b<=1;) {
        for (double b=1; b>=0.1;) {
            Settings.beta = b;
            mta.updateBetaLabel();
                        
            // Thermalise
            int thermaliseSweeps = Settings.thermaliseSweeps;
            if (Settings.beta > 0.3) {
                thermaliseSweeps *= 5;
            }
            if (Settings.beta > 0.5) {
                thermaliseSweeps *= 3;
            }
            for (int i=0; i<Settings.thermaliseSweeps; i++) {
                sweep();
            }
            
                    
            double[] magResult = new double[Settings.autoSampleSweeps];
            
            // Perform sweeps and obtain M
            for (int i=0; i<Settings.autoSampleSweeps; i++) {
                
                // Perform decorrelation sweeps
                for (int j=0; j<Settings.autoDecorrelationSweeps; j++){
                    sweep();
                }
                
                // Record Magnetisation (absolute value)
                magResult[i] = Math.abs(l.magnetisation());
            }
            
            double magMean = 0;
            for (int i=0; i<Settings.autoSampleSweeps; i++) {
                magMean += magResult[i];
            }
            magMean = magMean / Settings.autoSampleSweeps;
            
            double magVar = 0;
            for (int i=0; i<Settings.autoSampleSweeps; i++) {
                magVar += Math.pow(magResult[i]-magMean, 2.0);
            }
            magVar = magVar / (Settings.autoSampleSweeps - 1.0);
            
            System.out.println(DecimalString.getString(b)
                    +"\t"+DecimalString.getString(magMean)
                    +"\t"+DecimalString.getString(Math.sqrt(magVar)));
            
            if (b < 0.25 || b > 0.55) {
                b -= 0.1;
            } else {
                b -= 0.02;
            }
        }
        System.out.println("Done!");
        thread_status = RUNNING;
        algorithm_status=PAUSED;
    }
    
    public void display() {
        l.displayLattice();
    }
}

