//Trans_State.java
//author Umberto Ravaioli, 2005

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.applet.*;
import java.awt.font.*;
import java.net.URL;
import java.text.*;
import java.util.Map;
import java.util.Hashtable;
import java.util.jar.Attributes;

/* For lossy line, not used here (lossless line)
    R : Series resistance per unit length, for both conductors, in Ohms/m
    L : Series inductance per unit length, for both conductors, in H/m
    G : Shunt conductance per unit length, in S/m
    C : Shunt capacitance per unit length, in F/m
    Gamma : Propagation Constant
    Z0 : Characteristic Impedance
*/

public class Trans_State {
    double L, C, G, R;
    public Complex gamma, Gammain, GammaL, Z0; 
    public double GammaL_mag, GammaL_phase;
    public Complex Zin, Yin; //Input Impedance
    public Complex Vin, Iin; //Input Voltage and Currents
    public Complex VPlus, one;
    double alpha, beta;
    protected double frequency, angular_frequency;
    double xpos, lineLength, lineLength_part1, lineLength_part2, VSWR;
    int linecounter1 = 1000, linecounter2 = 0;
    double epsilon_r, mu_r;
    double x[], y1[], y2[]; //cursor position
    Complex ZL, YL; //Load
    public Complex Voltage[], Current[], Power[];
    public Complex Impedance[], Admittance[];
    Generator generator;
    public static final int NPoints=300;
    public int NTime, ctime, dtime;
    boolean IsLowLoss, is_Load_Ztype, use_Zchart;//true for low loss, false for high loss.
    boolean IsLargerThanOne, IsPlots;
    Complex timeFactor;
    public double wavelength;
    public double Power_input;
    public double Power_load;
    public double Power_generator;
    public double Power_Zg;
    public double Power_flow;
    public Complex GammaShort = new Complex(-1.0,0.0);
    public Complex GammaOpen  = new Complex(1.0,0.0);
	    
    // Exact speed of light in vacuum
    //private static final double epsilon0 = 8.8541878176E-12; // Units: F/m
    //private static final double mu0 = 1.25663706144E-6; //      Units H/m
    //private static final double light_velocity = Math.sqrt(1.0/(epsilon0*mu0)); //  Units m/s
    
    // Approximate speed of light in vacuum
    private static final double light_velocity = 3.0E8; //  Units m/s
    
    public int IsPhasorPlot = 1;
    public int IsTimePlot = 1;
    public boolean IsLoadShort, IsLoadOpen, IsLoadImaginary, IsLoadRegular, IsAlphaZero, IWantImpedance;
    
    public boolean LicenseExpired;
    
    public int this_month, today_week, this_year, this_hour, this_minute, today_month, 
	       today_year,this_zone, saving_time;
	       
    GregorianCalendar Greg = new GregorianCalendar();
         
    public Font ttfFont, sanSerifFont, serifFont, symbolFont, italicFont;

    
    public Trans_State(){
    
        IsPlots = false;
	IsLoadShort = false;
	IsLoadOpen = false;
	IsLoadImaginary = false;
	IsLoadRegular = true;
	IsAlphaZero = true;
	IWantImpedance = true;
        use_Zchart = true;
	
	L = 0.3794;
	C = 67.447;
	R = 1.0;
	G = 0.0033;    
	
	IsLowLoss=true;
	IsLargerThanOne = false;
	is_Load_Ztype = true;
	frequency = 1.0E9;
	
	
	lineLength=1.0;
	lineLength_part1 = 1.0;
	lineLength_part2 = 0.0;
	
	xpos = 0.0;
	
	epsilon_r = 1.0;
	mu_r = 1.0;
	
	wavelength = light_velocity/(Math.sqrt(epsilon_r*mu_r)*frequency);
	one = new Complex(1.0,0.0);
	ZL=new Complex(50.0,100.0);
	YL=new Complex(0.004,-0.008);
        Yin = YL;
	Zin = new Complex(50.0,100.0);
	Z0 = new Complex(50.0,0.0);
	alpha = 0.0;
	beta = 2.0*Math.PI;
	GammaL_mag = 0.70710678;
        GammaL_phase = 45;
	generator = new Generator();
	
	//graph arrays
	x=new double[NPoints];
	y1=new double[NPoints];
	y2=new double[NPoints];
        Impedance = new Complex[NPoints];
	Admittance = new Complex[NPoints];
	
	for(int i=0; i<x.length;i++){
	    x[i]=i*lineLength/(NPoints-1);
	}
	MaestroA.randomizer(y1,2.0,-2.0,1);
	MaestroA.randomizer(y2,2.0,-2.0,2);
	
	//Time dependent arrays
	Voltage = new Complex[NPoints];
	Current = new Complex[NPoints];
	Power = new Complex[NPoints];
	
	//Timefactor
	NTime=360;
	ctime=0;
	dtime=10;
	timeFactor = new Complex(Math.cos(2.0*Math.PI*ctime/NTime),
				 Math.sin(2.0*Math.PI*ctime/NTime));
				 
	this_month = Greg.get(Calendar.MONTH);
	today_week = Greg.get(Calendar.DAY_OF_WEEK);
	this_year = Greg.get(Calendar.YEAR);
	this_hour = Greg.get(Calendar.HOUR_OF_DAY);
	this_minute = Greg.get(Calendar.MINUTE);
	today_month = Greg.get(Calendar.DAY_OF_MONTH);
	today_year = Greg.get(Calendar.DAY_OF_YEAR);
	this_zone = Greg.get(Calendar.ZONE_OFFSET);
	saving_time = Greg.get(Calendar.DST_OFFSET);

	ignition();
    }
    
    public void ignition(){
	Complex temp2,temp3,temp4,Zin2,Yin2;
	
	angular_frequency = 2*Math.PI*frequency;
	
	if(IsLowLoss){
		    beta = 2.0*Math.PI;
		    wavelength = light_velocity/(Math.sqrt(epsilon_r*mu_r)*frequency);
	}
	
	//Compute Gamma at Load
	    
	if(is_Load_Ztype)
	{
	    if(IsLoadOpen){
		GammaL = new Complex(1.0,0.0);
		ZL = new Complex(0.0,-1.0E135);
		YL = new Complex(0.0,0.0);
	    }
	    else if(IsLoadShort){
		GammaL = new Complex(-1.0,0.0);
		YL = new Complex(0.0,-1.0E135);
		ZL = new Complex(0.0,0.0);
	    }
	    else{
	        GammaL = EMF.computeGamma(ZL,Z0);
		YL = EMF.Inv(ZL);
	    }
	}
	else{
	    GammaL = EMF.computeGamma(YL,Z0,false);
	    if(GammaL == GammaOpen){//open
		ZL = new Complex(0.0,-1.0E135);
	    }
	    else{
		ZL = Complex.Divide(one,YL);
	    }
	}
	if(IsLoadOpen || IsLoadShort || IsLoadImaginary){
	    VSWR = 1.0E135;
	}
	else{
	    VSWR = (1.0+Complex.Magnitude(GammaL))/(1-Complex.Magnitude(GammaL));
	}
	
        VPlus = new Complex(1.0,0.0); //EMF.computeVPlus(generator,GammaL,Z0,lineLength,alpha,wavelength);    
	//System.out.println("VPlus = "+VPlus);
        
	//Compute Gamma at xpos
	if(alpha == 0.0){
            Gammain = EMF.computeGammaAt(GammaL,xpos);
	}
	else{
	    Gammain = EMF.computeGammaAt(GammaL,alpha,xpos,wavelength);
	}
        
	/*	
	//Compute V+
	VPlus = EMF.computeVPlus(generator,GammaL,Z0,lineLength,alpha,wavelength);
	*/
        
	//Compute Zin
	
	if(alpha == 0.0){
	    Complex tz, ty;
	    tz = EMF.computeZinAt(GammaL,Complex.Real(Z0),xpos,true);
	    ty = EMF.computeYinAt(GammaL,Complex.Real(Z0),xpos,true);
	    if(IsLoadRegular){
		Zin = tz;
		Yin = ty;
	    }
	    else if(IsLoadImaginary){
		Zin = new Complex(0.0, tz.Imaginary());
		Yin = new Complex(0.0, ty.Imaginary());
	    }
	    else if(IsLoadShort){
		if(xpos == 0.0 || xpos == 0.5 || xpos == 1.0){
		    Zin = new Complex(0.0,0.0);
		    Yin = new Complex(0.0, -1.0E135);
		}
		else if(xpos == 0.25 || xpos == 0.75){
		    Yin = new Complex(0.0,0.0);
		    Zin = new Complex(0.0, -1.0E135);
		}
		else{
		    Zin = tz;
		    Yin = ty;
		}
	    }
	    else if(IsLoadOpen){
		if(xpos == 0.0 || xpos == 0.5 || xpos == 1.0){
		    Yin = new Complex(0.0,0.0);
		    Zin = new Complex(0.0, -1.0E135);
		}
		else if(xpos == 0.25 || xpos == 0.75){
		    Zin = new Complex(0.0,0.0);
		    Yin = new Complex(0.0, -1.0E135);
		}
		else{
		    Zin = tz;
		    Yin = ty;
		}
	    }
	}
	else{
	    Zin = EMF.computeZinAt(GammaL,Z0,xpos,alpha,wavelength);
	    Yin = EMF.computeYinAt(GammaL,Z0,xpos,alpha,wavelength);
	}
        /*
	//Compute Vin
	{
	    Complex one = new Complex(1.0,0.0);
	    Complex factor = new Complex(alpha*xpos,2*Math.PI*xpos);
	    Complex Expo = Complex.Exp(factor);
	    Complex Reflecto = Complex.Add(one,Gammain);
	    Complex Reflecto2 = Complex.Subtract(one,Gammain);
	    Complex VoltScal = Complex.Multiply(Expo,Reflecto);
	    Complex CurScal = Complex.Divide(Complex.Multiply(Expo,Reflecto2),Z0);
	    Vin=Complex.Multiply(VPlus,VoltScal);
	    if(Zin.Real()==0.0 && Zin.Imaginary()==0.0){
		Iin=Complex.Multiply(VPlus,CurScal);
	    }
	    else
		//Compute Iin
		Iin=Complex.Divide(Vin,Zin);
	    }
	
	//Compute Power
	    Complex one = new Complex(1.0,0.0);
	    Complex factor_in = new Complex(alpha*lineLength,2*Math.PI*lineLength);
	    Complex Expo_in = Complex.Exp(factor_in);
	    Complex Gamma_in = EMF.computeGammaAt(GammaL,alpha,lineLength,wavelength);
	    Complex Reflecto_in = Complex.Add(one,Gamma_in);
	    Complex VoltScal_in = Complex.Multiply(Expo_in,Reflecto_in);
	    Complex V_input=Complex.Multiply(VPlus,VoltScal_in);
	    Complex V_load = Complex.Multiply(VPlus,Complex.Add(one,GammaL));
	    Complex I_load = Complex.Divide(Complex.Multiply(VPlus,Complex.Subtract(one,GammaL)),Z0);
	    
	    Complex Z_input = EMF.computeZinAt(GammaL,Z0,lineLength,alpha,wavelength);
	    Complex Y_input = EMF.computeYinAt(GammaL,Z0,lineLength,alpha,wavelength);
	    
	    Complex I_input = Complex.Multiply(V_input,Y_input);
	    
	    Power_input = 0.5 * Complex.Real(Complex.Multiply(V_input,Complex.Conjugate(I_input)));
	    //Power_load  = 0.5 * Math.pow(Complex.Magnitude(VPlus),2)/Z0 * (1 - Math.pow(Complex.Magnitude(GammaL),2));
	    Power_load = 0.5 * Complex.Real(Complex.Multiply(V_load,Complex.Conjugate(I_load)));
	    Power_generator = 0.5 * Complex.Real(Complex.Multiply(generator.getVg(),Complex.Conjugate(I_input))); 
	    Power_Zg = 0.5 * Complex.Real(Complex.Multiply(Complex.Subtract(generator.getVg(),V_input),Complex.Conjugate(I_input))); 
	    Power_flow = 0.5 * Complex.Real(Complex.Multiply(Vin,Complex.Conjugate(Iin)));
         */
    }
    
    public void ScanImpedance(){
	double maxBound=20*Complex.Real(Z0);
	double minBound=1.0/maxBound;
	for(int i = 0; i < NPoints; i++){
	    x[i] = i * lineLength/(NPoints-1);
            
            if(Complex.Real(YL)==0.0 && Complex.Imaginary(YL)==0.0){// open circuit
                y1[i] = 0.0;
                y2[i] = -Complex.Real(Z0)*Math.cos(2.0*Math.PI*x[i])/Math.sin(2.0*Math.PI*x[i]);
            }
            else{
                Impedance[i] = EMF.computeZinAt(ZL,Complex.Real(Z0),x[i],false);

                y1[i] = Impedance[i].Real();
                y2[i] = Impedance[i].Imaginary();
            }
	    // FIX to limit the values on plots (7/31/97) - Umberto
	    if(y1[i]<minBound){  y1[i] = 0.0;}
	    if(y1[i]>maxBound){  y1[i] =  maxBound;}
	    if(y2[i]>maxBound){  y2[i] =  maxBound;}
	    if(y2[i]<-maxBound){ y2[i] = -maxBound;}
	//System.out.println(i+"    "+y1[i]+"    "+y2[i]);		     
	}
    } 
    
        
    public void ScanAdmittance(){
	double maxBound = 30.0/Complex.Real(Z0);
	double minBound = maxBound/10000;
	double maximum, minimum;
	for(int i = 0; i < NPoints; i++){
	    x[i ] = i * lineLength/(NPoints-1);
	    
            //if(Complex.Real(ZL)==0.0 && Complex.Imaginary(ZL)==0.0){// short circuit
              //  y1[i] = 0.0;
              //  y2[i] = Math.sin(2.0*Math.PI*x[i])/Math.cos(2.0*Math.PI*x[i])/Complex.Real(Z0);
            //}
            //else{
                Admittance[i] = EMF.computeYinAt(YL,Complex.Real(Z0),x[i],false);
                y1[i] = Admittance[i].Real();
                y2[i] = Admittance[i].Imaginary();
            //}
	    // FIX to limit the values on plots (7/31/97) - Umberto
	    if(y1[i]<minBound){  y1[i] = 0.0;}
	    if(y1[i]>maxBound){  y1[i] = maxBound;}
	    if(y2[i]>maxBound){  y2[i] =  maxBound;}
	    if(y2[i]<-maxBound){ y2[i] = -maxBound;}	     
	}
    }
    
     public void ScanVoltageCurrent(){ 
	        
        //if(IsTotal){
            for(int i = 0; i < NPoints; i++){
                x[i] = i * lineLength/(NPoints-1);
                Voltage[i] = EMF.computeVat(ZL,Z0,VPlus,x[i]);
                Current[i] = EMF.computeIat(ZL,Z0,VPlus,x[i]);
                //System.out.println("I am here");
                if(Complex.Real(YL)==0.0 && Complex.Imaginary(YL)==0.0){
                    // normalized, plot does not have absolute values, anyway
                    y1[i] = 2.0*Math.abs(Math.cos(2.0*Math.PI*x[i]));
                    y2[i] = 2.0*Math.abs(Math.sin(2.0*Math.PI*x[i]))/Complex.Real(Z0);
                }
                else if(Complex.Real(ZL)==Complex.Real(Z0) && Complex.Imaginary(ZL)==0.0){
                    y1[i] = Complex.Magnitude(VPlus);
                    y2[i] = Complex.Magnitude(VPlus)/Complex.Real(Z0);
                }
                else{
                    y1[i] = Voltage[i].Magnitude();
                    y2[i] = Current[i].Magnitude();
                }
                
                //System.out.println(i+"   "+y1[i]+"    "+y2[i]);
            } 
        //}
        /*
        else if(IsIncident){
            
            for(int i = 0; i < NPoints; i++){
                x[i] = i * lineLength/(NPoints-1);
                Voltage[i] = EMF.computeVincidentat(ZL,lineZ0,VPlus,x[i]);
                Current[i] = EMF.computeIincidentat(ZL,lineZ0,VPlus,x[i]);
	    
                if(Complex.Real(ZL)==lineZ0 && Complex.Imaginary(ZL)==0.0){
                    y1[i] = Complex.Magnitude(VPlus);
                    y2[i] = Complex.Magnitude(VPlus)/lineZ0;
                }
                else{
                    y1[i] = Voltage[i].Magnitude();
                    y2[i] = Current[i].Magnitude();
                }
            } 
        }
        else if(IsReflected){
            for(int i = 0; i < NPoints; i++){
                x[i] = i * lineLength/(NPoints-1);
                Voltage[i] = EMF.computeVreflectedat(ZL,lineZ0,VPlus,x[i]);
                Current[i] = EMF.computeIreflectedat(ZL,lineZ0,VPlus,x[i]);
	    
                if(Complex.Real(ZL)==lineZ0 && Complex.Imaginary(ZL)==0.0){
                    y1[i] = Complex.Magnitude(VPlus);
                    y2[i] = Complex.Magnitude(VPlus)/lineZ0;
                }
                else{
                    y1[i] = Voltage[i].Magnitude();
                    y2[i] = Current[i].Magnitude();
                }
            } 
        }
         */
    }
    
}/* End of State */
