//StateVars.java
/* A Java class for
 * SingleStub.java
 * Electromagnetic Transmission Line Applet
 * Applet without Smith Chart - Prepared by Umberto Ravaioli 
 * for 6th edition of Fundamentals of Applied Electromagnetics Book
 * June 2009 - All Rights Reserved
 */   

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;

public class StateVars{
    public Complex ZL, YL, GammaL;
    public double Z0;
    public Complex Zin, Yin;
    
    //private boolean IsShunt, IsOpen;
    public boolean IsShunt, IsOpen, paintZ, IsTraceOn, IsBig;
    private int stepnumber, MaxSteps;
    public int sleeptime;
    public static final double lineLength=1.0;
    public double xpos, frequency, frequency_minimum, frequency_maximum, delta_frequency, frequency_scan;
    public double F1, F2, G1, G2;
    public int fpos1, fpos2, gpos1, gpos2, scanpoint;
    public boolean BigBand1 = false; 
    public boolean BigBand2 = false;
    
    public double epsilon_r, wavelength;
    
    public double t1, t2;
    public double d1, d2, dd1, dd2, d1_meters, d2_meters; //stub distances
    public double L1, L2, LL1, LL2, L1_meters, L2_meters; //stub lengths
    public double Bs1, Bs2, BBs1, BBs2, BBs1norm, BBs2norm; //stub susceptances
    public double x_freq[], F_array[], G_array[];
    public static final int NPoints = 1001;
    
    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
    private static final double light_velocity = 3.0E8; //  Units m/s
    
    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;
      
    Stub stub1, stub2; //Two possible solutions for the stubs
    StateVars(){
	ZL = new Complex(100.0,80.0);
	Z0 = 50.0;
	YL = EMF.Inv(ZL);
	Zin = (Complex)ZL.clone();
	Yin = (Complex)YL.clone();
	xpos = (0.0);
	
	frequency = 1.0E9; //Hertz
	frequency_minimum = 0.0;
	frequency_maximum = 2.0E9;
	frequency_scan = frequency;
	delta_frequency = (frequency_maximum - frequency_minimum)/(NPoints - 1); 
	
	x_freq = new double[NPoints];
	F_array = new double[NPoints];
	G_array = new double[NPoints];
	
	for(int i=0;i<NPoints;i++){
	    x_freq[i] = frequency_minimum+(double)i*delta_frequency;
	}
	
	for(int i=0;i<NPoints;i++){
	    F_array[i] = 1.0;
	    G_array[i] = 1.0;
	}
	
	epsilon_r = 1.0;
	wavelength = light_velocity/(Math.sqrt(epsilon_r) * frequency);
	IsShunt = true;
	IsOpen  = false;
	IsBig = false;
	
	scanpoint = NPoints/2;
	
	stub1 = new Stub();
	stub2 = new Stub();
	
	stub1.Short();
	stub2.Short();
	//stub1.Open();
	//stub2.Open();
	
	stub1.isEnable(false);
	stub2.isEnable(false);
	
	stub1.setZchar(Z0);
	stub2.setZchar(Z0);
	sleeptime = 101;
	stepnumber = 1;
	MaxSteps = 9;
	paintZ = false;
	IsTraceOn = true;
	
	this_month = Greg.get(Calendar.MONTH);
	//System.out.println("  This is the month = "+this_month);
	today_week = Greg.get(Calendar.DAY_OF_WEEK);
	//System.out.println("  This is the day_week = "+today_week);
	this_year = Greg.get(Calendar.YEAR);
	this_hour = Greg.get(Calendar.HOUR_OF_DAY);
	//System.out.println("  This is the year = "+this_year);
	this_minute = Greg.get(Calendar.MINUTE);
	//System.out.println("  This is the minute = "+this_minute);
	today_month = Greg.get(Calendar.DAY_OF_MONTH);
	//System.out.println("  This is the day_month = "+today_month);
	today_year = Greg.get(Calendar.DAY_OF_YEAR);
	//System.out.println("  This is the day_year = "+today_year);
	this_zone = Greg.get(Calendar.ZONE_OFFSET);
	//System.out.println("  This is the zone_offset = "+this_zone/3600000);
	saving_time = Greg.get(Calendar.DST_OFFSET);
	//System.out.println("  This is the dst_offset = "+saving_time/3600000);
    }
    
    public void ignition2(){
	YL = EMF.Inv(ZL);
	Zin = (Complex)ZL.clone();
	Yin = (Complex)YL.clone();
	GammaL = EMF.computeGamma(ZL,Z0);
	ignition();
	BigBand1 = false; BigBand2 = false;
	scanfrequency();
    }
    
    public void ignition(){
		
	//frequency_minimum = 0.0;
	//frequency_maximum = 2.0*frequency;
	frequency_minimum = frequency - 0.5*frequency;
	frequency_maximum = frequency + 0.5*frequency;
	
	delta_frequency = (frequency_maximum - frequency_minimum)/(NPoints - 1); 
	wavelength = light_velocity/(Math.sqrt(epsilon_r) * frequency);
	
	stub1.setZchar(Z0);
	stub2.setZchar(Z0);
	if(Z0 == ZL.Real()){
	    t1 = Math.tan(Math.PI*0.5);
	    t2 = -0.5 * ZL.Imaginary()/Z0;
	}
	else{
	//Pozar, equation 6.9, page 292
	t1 = ( ZL.Imaginary() + Math.sqrt(ZL.Real()*
				 (
				  Math.pow(Z0-ZL.Real(),2.0)+Math.pow(ZL.Imaginary(),2.0)
				 )/Z0
			      )
	     )/(ZL.Real()-Z0);
	     
	t2 = ( ZL.Imaginary() - Math.sqrt(ZL.Real()*
				 (
				  Math.pow(Z0-ZL.Real(),2.0)+Math.pow(ZL.Imaginary(),2.0)
				 )/Z0
			      )
	     )/(ZL.Real()-Z0);
	}
	
	if(t1 >= 0){
	      d1 = (1.0/(2.0*Math.PI))*Math.atan(t1);
	}
	else{
	      d1 = (1.0/(2.0*Math.PI))*(Math.PI+Math.atan(t1));
	}
	
	if(t2 >=0){
	      d2 = (1.0/(2.0*Math.PI))*Math.atan(t2);
	}
	else{
	      d2 = (1.0/(2.0*Math.PI))*(Math.PI+Math.atan(t2));
	}
	
	
	//Pozar, equation 6.8b, page 292
	Bs1 = -( Math.pow(ZL.Real(),2.0)*t1-(Z0-ZL.Imaginary()*t1)*(ZL.Imaginary()+Z0*t1) )/
	      ( Z0 * (Math.pow(ZL.Real(),2.0)+Math.pow(ZL.Imaginary()+Z0*t1,2) ) );
	if(stub1.isOpen()){
	    L1 = (1.0/(2.0*Math.PI))*Math.atan(Bs1*Z0);
	}
	else {
	    L1 = -(1.0/(2.0*Math.PI))*Math.atan(1.0/(Bs1*Z0));
	}
	if(L1<0.0) L1+=0.5;
	
	Bs2 = -( Math.pow(ZL.Real(),2.0)*t2-(Z0-ZL.Imaginary()*t2)*(ZL.Imaginary()+Z0*t2) )/
	      ( Z0 * (Math.pow(ZL.Real(),2.0)+Math.pow(ZL.Imaginary()+Z0*t2,2) ) );
	if(stub2.isOpen()){
	     L2 = (1.0/(2.0*Math.PI))*Math.atan(Bs2*Z0);
	}
	else {
	     L2 = -(1.0/(2.0*Math.PI))*Math.atan(1.0/(Bs2*Z0));
	}
	if(L2<0.0) L2+=0.5;
	if(d1<d2){
	    stub1.setPosition(d1);
	    stub2.setPosition(d2);
	    stub1.setLength(L1);
	    stub2.setLength(L2);
	    
	    dd1 = d1;
	    dd2 = d2;
	    BBs1 = Bs1;
	    BBs1norm = Bs1*Z0;
	    BBs2 = Bs2;
	    BBs2norm = Bs2*Z0;
	    LL1 = L1;
	    LL2 = L2;
	    
	    d1_meters = d1 * wavelength;
	    d2_meters = d2 * wavelength;
	    L1_meters = L1 * wavelength;
	    L2_meters = L2 * wavelength;
	}
	else{
	    stub1.setPosition(d2);
	    stub2.setPosition(d1);
	    stub1.setLength(L2);
	    stub2.setLength(L1);
	    
	    dd1 = d2;
	    dd2 = d1;
	    BBs1 = Bs2;
	    BBs1norm = Bs2*Z0;
	    BBs2 = Bs1;
	    BBs2norm = Bs1*Z0;
	    LL1 = L2;
	    LL2 = L1;
	    
	    d1_meters = d2 * wavelength;
	    d2_meters = d1 * wavelength;
	    L1_meters = L2 * wavelength;
	    L2_meters = L1 * wavelength;
	}
    }
    
    public void scanfrequency(){
	double wavelen, d1new, d2new, L1new, L2new;
	Complex Z1, Z2, Zs1, Zs2, Yinput1, Yinput2;
	Complex ZL_freq;
	
	ZL_freq = ZL;
	
	F1 = frequency;
	F2 = frequency;
	fpos1 = NPoints/2;
	fpos2 = NPoints/2;
	
	//x_freq = new double[NPoints];
	//F_array = new double[NPoints];
	//G_array = new double[NPoints];
	
	for(int i=0;i<NPoints;i++){
	    x_freq[i] = frequency_minimum+(double)i*delta_frequency;
	}
		
	//for(int i=1;i<NPoints;i++){ // use this if frquency_minimum is zero
	for(int i=0;i<NPoints;i++){   // use this if frequency_minimum is not zero
	  
	    wavelen = light_velocity/(Math.sqrt(epsilon_r) * x_freq[i]);
	    
	    // Rescale imaginary part of load impedance with frequency
	    if(Complex.Imaginary(ZL) > 0.0){
		// Assume Im(ZL) = jwL
		ZL_freq = new Complex(Complex.Real(ZL),Complex.Imaginary(ZL)*x_freq[i]/frequency);
	    }
	    else if(Complex.Imaginary(ZL) < 0.0){
		//Assume Im(ZL) = -j/(wC)
		ZL_freq = new Complex(Complex.Real(ZL),Complex.Imaginary(ZL)*frequency/x_freq[i]);
	    }
	    else{
	
	    }
	    
	    d1new = d1_meters/wavelen;
	    d2new = d2_meters/wavelen;
	    L1new = L1_meters/wavelen;
	    L2new = L2_meters/wavelen;
	    
	    Z1 = EMF.computeZinAt(ZL_freq,Z0,d1new,false);
	    Z2 = EMF.computeZinAt(ZL_freq,Z0,d2new,false);
	    
	    if(stub1.isOpen()){
		Zs1 = EMF.computeZinAt(new Complex(1.0,0.0),Z0, L1new,true);
	    }
	    else{
		Zs1 = EMF.computeZinAt(new Complex(-1.0,0.0),Z0, L1new,true);
	    }
	    
	    
	    if(stub2.isOpen()){
		Zs2 = EMF.computeZinAt(new Complex(1.0,0.0),Z0, L2new,true);
	    }
	    else{
		Zs2 = EMF.computeZinAt(new Complex(-1.0,0.0),Z0, L2new,true);
	    }
	    
	    Yinput1 = Complex.Add(Complex.Divide(new Complex(1.0,0.0),Z1),Complex.Divide(new Complex(1.0,0.0),Zs1));
	    Yinput2 = Complex.Add(Complex.Divide(new Complex(1.0,0.0),Z2),Complex.Divide(new Complex(1.0,0.0),Zs2));
	    
	    F_array[i] = Complex.Magnitude(EMF.computeGamma(Yinput1,Z0,false));
	    G_array[i] = Complex.Magnitude(EMF.computeGamma(Yinput2,Z0,false));
	}
	
	/* use these lines if frequency_minimum is zero
	if(stub1.isOpen()){
	    F_array[0] = Complex.Magnitude(GammaL);//F_array[1];
	}
	else{
	    F_array[0] = 1.0;
	}
	if(stub2.isOpen()){
	    G_array[0] = Complex.Magnitude(GammaL);//G_array[1];
	}
	else{
	    G_array[0] = 1.0;
	}
	*/
	// Find Bandwidth for |Gamma| = 0.2 or VSWR = 1.5
	
	int Nlim = NPoints/2;
	for(int i=1;i<Nlim;i++){
	    F1 = x_freq[Nlim-i];
	    fpos1 = Nlim - i;
	    if(F_array[Nlim-i] >= 0.2){
		break;
	    }
	}
	for(int i=1;i<Nlim;i++){
	    F2 = x_freq[Nlim+i];
	    fpos2 = Nlim + i;
	    if(F_array[Nlim+i] >= 0.2){
		break;
	    }
	}
	for(int i=1;i<Nlim;i++){
	    G1 = x_freq[Nlim-i];
	    gpos1 = Nlim - i;
	    if(G_array[Nlim-i] >= 0.2){
		break;
	    }
	}
	for(int i=1;i<Nlim;i++){
	    G2 = x_freq[Nlim+i];
	    gpos2 = Nlim + i;
	    if(G_array[Nlim+i] >= 0.2){
		break;
	    }
	}
	if(F_array[NPoints-1] < 0.2){BigBand1 = true;}
	if(G_array[NPoints-1] < 0.2){BigBand2 = true;}
    }
    
    public synchronized void setxpos(double xpos){
	this.xpos = xpos;
    }
    
    public synchronized void setZL(Complex ZL){
	this.ZL = ZL;
    }
    
    public synchronized void setZL(double Zreal, double Zimag){
	ZL.setReal(Zreal);
	ZL.setImaginary(Zimag);
    }
    
    public synchronized void setZin(Complex Zin){
	this.Zin = Zin;
    }
    
    public Complex getZin(){
	 return Zin;
    }
    
    public synchronized void setYin(Complex Yin){
	this.Yin = Yin;
    }
    
    public Complex getYin(){
	return Yin;
    }
    
    public Complex getZL(){
	return ZL;
    }	
    
    public Complex getYL(){
	return YL;
    }
    
    public synchronized void setZ0(double Z0){
	this.Z0 = Z0;
    }
    
    public synchronized void setSleep(int x){
	this.sleeptime = x;
    }
    
    public int getSleep(){
	return sleeptime;
    }
    
    public double getZ0(){
	return Z0;
    }
    
    public boolean getPaintZ(){
	return paintZ;
    }
    
    public boolean getTrace(){
	return IsTraceOn;
    }
    
    public synchronized void setPaintZ(boolean x){
	this.paintZ = x;
    }
    
    public synchronized void setTrace(boolean x){
	this.IsTraceOn = x;
    }
    
    public boolean getShunt(){
	return IsShunt;
    }
    
    public synchronized void setShunt(boolean IsShunt){
	this.IsShunt = IsShunt;
    }
    
    public boolean getOpen(){
	return IsOpen;
    }
    
    public synchronized void setOpen(boolean IsOpen){
	this.IsOpen = IsOpen;
	if(IsOpen){
	    stub1.Open();
	    stub2.Open();
	}
	else{
	    stub1.Short();
	    stub2.Short();
	}
    }
    
    public int getStepNumber(){
	return stepnumber;
    }
    
    public synchronized void setStepNumber(int stepnumber){
	this.stepnumber = stepnumber;
    }
    
    public synchronized void StepIncrement(){
	stepnumber ++;
	if(stepnumber>MaxSteps) stepnumber=MaxSteps;
    }
    
    public synchronized void StepDecrement(){
	stepnumber --;
	if(stepnumber<1) stepnumber = 1;
    }
}
