using System;
using System.Drawing;
using System.Drawing.Printing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.IO;
using Microsoft.DirectX;
using Microsoft.DirectX.DirectDraw;
using WaveLib;
//using DotNetMatrix;


namespace HearingAidLab
{
   



	/// <summary>
	/// Summary description for CategoricalLoudness.
	/// </summary>
	public class CategoricalLoudness : System.Windows.Forms.Form
	{

		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		private System.Windows.Forms.TextBox txtLevel;
		private System.Windows.Forms.TextBox txtPrimary;
		private System.Windows.Forms.Label label3;
		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.Panel panel1;
		private System.Windows.Forms.StatusBar statusBar1;
		private System.Windows.Forms.StatusBarPanel sbLeftCal;
		private System.Windows.Forms.StatusBarPanel sbRightCal;
		private System.Windows.Forms.TextBox txtMin;
		private System.Windows.Forms.Label label2;
		private System.Windows.Forms.TextBox txtMax;
		private System.Windows.Forms.Label label4;
		private System.Windows.Forms.Button btnSkip;
		private System.Windows.Forms.Label label5;
		private System.Windows.Forms.TextBox txtFunction;
		

		public Form1 mainmenu;
		public HearingAidLab.Definitions def;
		public System.Windows.Forms.Timer ResponseTimer;		    //time before a 'no response'
		public System.Windows.Forms.Timer InterStimDelay;		    //time between stims
		public FileInfo outfile;								    //output file
		public StreamWriter output;								    //output writer
		private ArrayList Stims = new ArrayList();				    //list of CLDatas
		private int nCurrentStim = -1;							    //number of the current stim
		private CLData CurrentStim = null;						    //the current Stim
		private float fCurrentLevel = 70;						    //current level
		private float nMin;										    //Used when determining the min/max in phase 1
		private float nMax;										    //Used when determining the min/max in phase 1
		private Random r;										    //a randomizer
		private CatLoudUser dlg ;			                        //the buttons dlg
		public WaveLib.WavePlayer player = new WaveLib.WavePlayer();//audio
		private int nButtons = 11;								    //the number of buttons
		private bool bInaudible = false;						    //phase 1, to determine if the min has gone inaudible yet
		private bool bTooLoud = false;							    //limit of the system
		private bool bButtons = true;
		private int nCount = 0;
        
		private enum CLPhase
		{
			GetPositiveResponse,//get a positive response so I know they heard the tone
			FindingMin,
			FindingMax,
			Phase1,//initial 4 points
			Phase2, //additional Points
			Phase3, //check data, see if more needed
			Complete,
			AnchoredTrials
		};
		private CLPhase Phase;
		private Color[] colors = new Color[10];
		
		private SortedList RandomSet;
		private System.Windows.Forms.TextBox txtNumLevel;
		private System.Windows.Forms.Label label6;
		private System.Windows.Forms.Button btnSaveGraph;
		private System.Windows.Forms.Button btnPrintGraph;
		private System.Windows.Forms.Button btnLoadGraph;
        private StatusBarPanel sbCardInfo;
		private bool bDone = false;
		//private bool bDrawCurrentL = false;
		//private bool bDrawL = false;
		//private bool bDrawNextL = false;
		//private int Llow = 1;
		//private int Lhi = 4;
		//private double[,] curve = new double[50,2];
		//private double[] tempL = new double[50];
		//private int CurveCount = 0;
	
		public CategoricalLoudness()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();
           	if(player.Open()==false)
			{
				MessageBox.Show(this,"Unable to open sound card!","Audio Error",MessageBoxButtons.OK,MessageBoxIcon.Stop);
				return;
			}
			player.Init();
			this.Closing += new CancelEventHandler(CategoricalLoudness_Closing);
			StreamWriter sw = new StreamWriter(@"C:\curve.txt",false);
			sw.Close();
            
			
#if !DEBUG
			btnSkip.Visible = false;
#endif
			
				colors[0] = Color.Blue;
				colors[1] = Color.LightSeaGreen;
				colors[2] = Color.White;
				colors[3] = Color.Violet;
				colors[4] = Color.LightBlue;
				colors[5] = Color.Pink;
				colors[6] = Color.White;
				colors[7] = Color.LightYellow;
				colors[8] = Color.Brown;
				colors[9] = Color.Wheat;
			
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(output!=null)
				{
					if(output.BaseStream!=null)
					{
						try
						{
							output.Flush();
							output.Close();
						}
						catch(Exception){}
					}
				}
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CategoricalLoudness));
            this.txtLevel = new System.Windows.Forms.TextBox();
            this.txtPrimary = new System.Windows.Forms.TextBox();
            this.label3 = new System.Windows.Forms.Label();
            this.label1 = new System.Windows.Forms.Label();
            this.panel1 = new System.Windows.Forms.Panel();
            this.statusBar1 = new System.Windows.Forms.StatusBar();
            this.sbLeftCal = new System.Windows.Forms.StatusBarPanel();
            this.sbRightCal = new System.Windows.Forms.StatusBarPanel();
            this.sbCardInfo = new System.Windows.Forms.StatusBarPanel();
            this.txtMin = new System.Windows.Forms.TextBox();
            this.label2 = new System.Windows.Forms.Label();
            this.txtMax = new System.Windows.Forms.TextBox();
            this.label4 = new System.Windows.Forms.Label();
            this.btnSkip = new System.Windows.Forms.Button();
            this.txtFunction = new System.Windows.Forms.TextBox();
            this.label5 = new System.Windows.Forms.Label();
            this.txtNumLevel = new System.Windows.Forms.TextBox();
            this.label6 = new System.Windows.Forms.Label();
            this.btnSaveGraph = new System.Windows.Forms.Button();
            this.btnPrintGraph = new System.Windows.Forms.Button();
            this.btnLoadGraph = new System.Windows.Forms.Button();
            ((System.ComponentModel.ISupportInitialize)(this.sbLeftCal)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.sbRightCal)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.sbCardInfo)).BeginInit();
            this.SuspendLayout();
            // 
            // txtLevel
            // 
            this.txtLevel.Location = new System.Drawing.Point(168, 56);
            this.txtLevel.Name = "txtLevel";
            this.txtLevel.ReadOnly = true;
            this.txtLevel.Size = new System.Drawing.Size(240, 20);
            this.txtLevel.TabIndex = 16;
            // 
            // txtPrimary
            // 
            this.txtPrimary.Location = new System.Drawing.Point(168, 32);
            this.txtPrimary.Name = "txtPrimary";
            this.txtPrimary.ReadOnly = true;
            this.txtPrimary.Size = new System.Drawing.Size(240, 20);
            this.txtPrimary.TabIndex = 15;
            // 
            // label3
            // 
            this.label3.Location = new System.Drawing.Point(8, 56);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(160, 23);
            this.label3.TabIndex = 14;
            this.label3.Text = "Primary Stimulus Pres. Level:";
            this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
            // 
            // label1
            // 
            this.label1.Location = new System.Drawing.Point(8, 32);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(160, 23);
            this.label1.TabIndex = 13;
            this.label1.Text = "Current Primary Stimulus:";
            this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
            // 
            // panel1
            // 
            this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
            this.panel1.Location = new System.Drawing.Point(280, 136);
            this.panel1.Name = "panel1";
            this.panel1.Size = new System.Drawing.Size(504, 400);
            this.panel1.TabIndex = 17;
            // 
            // statusBar1
            // 
            this.statusBar1.Location = new System.Drawing.Point(0, 544);
            this.statusBar1.Name = "statusBar1";
            this.statusBar1.Panels.AddRange(new System.Windows.Forms.StatusBarPanel[] {
            this.sbLeftCal,
            this.sbRightCal,
            this.sbCardInfo});
            this.statusBar1.ShowPanels = true;
            this.statusBar1.Size = new System.Drawing.Size(792, 22);
            this.statusBar1.TabIndex = 18;
            this.statusBar1.Text = "statusBar1";
            // 
            // sbLeftCal
            // 
            this.sbLeftCal.AutoSize = System.Windows.Forms.StatusBarPanelAutoSize.Contents;
            this.sbLeftCal.Name = "sbLeftCal";
            this.sbLeftCal.Text = "statusBarPanel1";
            this.sbLeftCal.Width = 97;
            // 
            // sbRightCal
            // 
            this.sbRightCal.AutoSize = System.Windows.Forms.StatusBarPanelAutoSize.Contents;
            this.sbRightCal.Name = "sbRightCal";
            this.sbRightCal.Text = "statusBarPanel1";
            this.sbRightCal.Width = 97;
            // 
            // sbCardInfo
            // 
            this.sbCardInfo.Name = "sbCardInfo";
            this.sbCardInfo.Text = "Current Card information";
            this.sbCardInfo.Width = 500;
            // 
            // txtMin
            // 
            this.txtMin.Location = new System.Drawing.Point(168, 80);
            this.txtMin.Name = "txtMin";
            this.txtMin.ReadOnly = true;
            this.txtMin.Size = new System.Drawing.Size(240, 20);
            this.txtMin.TabIndex = 20;
            // 
            // label2
            // 
            this.label2.Location = new System.Drawing.Point(8, 80);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(160, 23);
            this.label2.TabIndex = 19;
            this.label2.Text = "Min Level:";
            this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
            // 
            // txtMax
            // 
            this.txtMax.Location = new System.Drawing.Point(168, 104);
            this.txtMax.Name = "txtMax";
            this.txtMax.ReadOnly = true;
            this.txtMax.Size = new System.Drawing.Size(240, 20);
            this.txtMax.TabIndex = 22;
            // 
            // label4
            // 
            this.label4.Location = new System.Drawing.Point(8, 104);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(160, 23);
            this.label4.TabIndex = 21;
            this.label4.Text = "Max Level:";
            this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
            // 
            // btnSkip
            // 
            this.btnSkip.Location = new System.Drawing.Point(8, 136);
            this.btnSkip.Name = "btnSkip";
            this.btnSkip.Size = new System.Drawing.Size(75, 23);
            this.btnSkip.TabIndex = 23;
            this.btnSkip.Text = "Skip to 2";
            this.btnSkip.Click += new System.EventHandler(this.btnSkip_Click);
            // 
            // txtFunction
            // 
            this.txtFunction.Location = new System.Drawing.Point(168, 8);
            this.txtFunction.Name = "txtFunction";
            this.txtFunction.ReadOnly = true;
            this.txtFunction.Size = new System.Drawing.Size(240, 20);
            this.txtFunction.TabIndex = 37;
            // 
            // label5
            // 
            this.label5.Location = new System.Drawing.Point(8, 8);
            this.label5.Name = "label5";
            this.label5.Size = new System.Drawing.Size(160, 23);
            this.label5.TabIndex = 36;
            this.label5.Text = "Current Function:";
            this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
            // 
            // txtNumLevel
            // 
            this.txtNumLevel.Location = new System.Drawing.Point(528, 80);
            this.txtNumLevel.Name = "txtNumLevel";
            this.txtNumLevel.Size = new System.Drawing.Size(32, 20);
            this.txtNumLevel.TabIndex = 38;
            // 
            // label6
            // 
            this.label6.Location = new System.Drawing.Point(432, 80);
            this.label6.Name = "label6";
            this.label6.Size = new System.Drawing.Size(96, 16);
            this.label6.TabIndex = 39;
            this.label6.Text = "Number of levels:";
            // 
            // btnSaveGraph
            // 
            this.btnSaveGraph.Location = new System.Drawing.Point(8, 216);
            this.btnSaveGraph.Name = "btnSaveGraph";
            this.btnSaveGraph.Size = new System.Drawing.Size(72, 24);
            this.btnSaveGraph.TabIndex = 40;
            this.btnSaveGraph.Text = "Save Graph";
            this.btnSaveGraph.Click += new System.EventHandler(this.btnSaveGraph_Click);
            // 
            // btnPrintGraph
            // 
            this.btnPrintGraph.Location = new System.Drawing.Point(8, 248);
            this.btnPrintGraph.Name = "btnPrintGraph";
            this.btnPrintGraph.Size = new System.Drawing.Size(72, 24);
            this.btnPrintGraph.TabIndex = 41;
            this.btnPrintGraph.Text = "Print Graph";
            this.btnPrintGraph.Click += new System.EventHandler(this.btnPrintGraph_Click);
            // 
            // btnLoadGraph
            // 
            this.btnLoadGraph.Location = new System.Drawing.Point(8, 184);
            this.btnLoadGraph.Name = "btnLoadGraph";
            this.btnLoadGraph.Size = new System.Drawing.Size(72, 24);
            this.btnLoadGraph.TabIndex = 42;
            this.btnLoadGraph.Text = "Load Graph";
            this.btnLoadGraph.Click += new System.EventHandler(this.btnLoadGraph_Click);
            // 
            // CategoricalLoudness
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(792, 566);
            this.Controls.Add(this.btnLoadGraph);
            this.Controls.Add(this.btnPrintGraph);
            this.Controls.Add(this.btnSaveGraph);
            this.Controls.Add(this.label6);
            this.Controls.Add(this.txtNumLevel);
            this.Controls.Add(this.txtFunction);
            this.Controls.Add(this.txtMax);
            this.Controls.Add(this.txtMin);
            this.Controls.Add(this.statusBar1);
            this.Controls.Add(this.txtLevel);
            this.Controls.Add(this.txtPrimary);
            this.Controls.Add(this.label5);
            this.Controls.Add(this.btnSkip);
            this.Controls.Add(this.label4);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.panel1);
            this.Controls.Add(this.label3);
            this.Controls.Add(this.label1);
            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
            this.Name = "CategoricalLoudness";
            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            this.Text = "Categorical Loudness";
            this.Load += new System.EventHandler(this.CategoricalLoudness_Load);
            ((System.ComponentModel.ISupportInitialize)(this.sbLeftCal)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.sbRightCal)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.sbCardInfo)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();

		}
		#endregion
//initialization functions
		public void Init()
		{
            dlg = new CatLoudUser(mainmenu.def.CLButtonsLayout);
		    r = new Random(DateTime.Now.Millisecond);

			ResponseTimer = new Timer();
			ResponseTimer.Interval = mainmenu.def.nTimer;
			ResponseTimer.Tick += new EventHandler(ResponseTimer_Tick);
			
			InterStimDelay = new Timer();
			InterStimDelay.Interval = (int) (mainmenu.def.nDelay+r.NextDouble()*mainmenu.def.nJitter);
			InterStimDelay.Tick += new EventHandler(InterStimDelay_Tick);

			sbLeftCal.Text = mainmenu.GetLCal();
			sbRightCal.Text = mainmenu.GetRCal();
            sbCardInfo.Text += " :" + player.deviceName;
            nButtons = mainmenu.def.nCLButtons;
			if(InitStims()==false)
				return;
			InitOutput();
			InitUser();
			this.Show();
			
			DialogResult res = MessageBox.Show(this,"Click 'OK' when you are ready to begin, or 'Cancel' to abort!","Ready?",MessageBoxButtons.OKCancel,MessageBoxIcon.Information);
			if(res == DialogResult.OK)
				Start();
			else
				this.Close();
		}
		private bool InitStims()
		{
			try
			{
				CLData dat;
				foreach(Stim a in mainmenu.def.PrimaryStims)
				{
					dat = new CLData();
					dat.s = new Stim();
					if(mainmenu.def.bFrequencyShaping==false)
					{
						dat.s = a.Clone();
						dat.s.strEar = a.strEar;
						dat.s.nFreq = a.nFreq;
						dat.s.buffer = new WaveBuffer();
						mainmenu.CreateStim(ref dat.s);
					}
					else
					{
						FileInfo f = new FileInfo(dat.s.strStimDirectory+"\\"+dat.s.strFile);//new FileInfo(mainmenu.def.strStimDirectory+dat.s.strFile);
						int V2 = mainmenu.GetV2(a.nOrigin,1000,"both");
						WaveBuffer bt = SigPro.FreqShape(f,mainmenu.def.LAtten,mainmenu.def.LFreqs,mainmenu.def.RAtten,mainmenu.def.RFreqs,V2);
						dat.s.buffer.SetMS(bt.ms, "both");
					}
					dat.s.buffer.AmplificationType = dat.s.AmpType;
					Stims.Add(dat);
				}
				if(mainmenu.def.bRandom==true)
				{
					//randomize Stims
					SortedList temp = new SortedList();
					foreach(CLData d in Stims)
					{
						for(int x = 0;x<def.nReps;x++)
						{
							int z = r.Next(10000);
							while(temp.ContainsKey(z)==true)
							{
								z = r.Next(10000);
							}
							temp.Add(z,d);
						}
					}
					Stims.Clear();
					foreach(DictionaryEntry de in temp)
					{
						Stims.Add(de.Value);
					}
				}
				else
				{
					if(def.nReps>1)
					{
						ArrayList temp = new ArrayList();
						foreach(CLData d in Stims)
						{
							for(int x=0;x<def.nReps;x++)
							{
								temp.Add(d);
							}
						}
						Stims.Clear();
						foreach(CLData d in temp)
						{
							Stims.Add(d);
						}
					}
				}
			}
			catch(Exception err)
			{
				Form1.ErrorMsg(err.Message);
				return false;
			}
			return true;
		}

		private void InitOutput()
		{
			output = new StreamWriter(outfile.ToString(), true);
			output.WriteLine("%CATEGORICAL LOUDNESS RESULTS");
			output.WriteLine(string.Empty);
			output.WriteLine("%SUBJECT DATA");
			output.WriteLine("%"+mainmenu.txtName.Text);
			output.WriteLine("%"+mainmenu.txtBirth.Text);
			output.WriteLine("%"+mainmenu.cmbGender.Text);
			output.WriteLine("%"+mainmenu.txtGroup.Text);
			output.WriteLine("%"+mainmenu.txtId.Text);
			output.WriteLine(string.Empty);
			output.WriteLine("%Definition File: "+mainmenu.def.strInitFile);
			output.WriteLine("%StimuliDirectory: "+mainmenu.def.strStimDirectory);
			output.WriteLine("%"+DateTime.Now.ToShortDateString());
			output.WriteLine("%"+DateTime.Now.ToShortTimeString());
			output.WriteLine(string.Empty);
			output.WriteLine("Calibration: "+mainmenu.GetCal());
			output.WriteLine(string.Empty);
			if(mainmenu.txtBirth.Text.Length>0)
			{
				try
				{
					DateTime dtBirth = DateTime.Parse(mainmenu.txtBirth.Text);
					
					TimeSpan sp = DateTime.Now.Subtract(dtBirth);
					double age = sp.Days/365.25;
					int yrs = (int) age;
					int mos = (int) ((age-yrs)*12);
					output.WriteLine("%"+yrs.ToString() + ";" + mos.ToString());
				}
				catch(Exception){}
			}
			output.WriteLine(string.Empty);

			output.WriteLine("%"+"STIMULI");
			
			foreach(Stim s in mainmenu.def.PrimaryStims)
			{
				output.WriteLine("%"+s.strText);
			}
			output.WriteLine(string.Empty);
			output.WriteLine("---------------------------------------------------------");
			output.WriteLine(string.Empty);
		}
		private void InitUser()
		{
           // MessageBox.Show("Size" + SystemInformation.PrimaryMonitorMaximizedWindowSize);
           
            int DisplayIndex = 0;
            
            Screen[] screens = Screen.AllScreens;
            Screen currentscreen = Screen.FromControl(this);
           int upperBound = screens.GetUpperBound(0);
            for (DisplayIndex = 0; DisplayIndex < upperBound; DisplayIndex++)
            {
               if (screens[DisplayIndex].DeviceName != currentscreen.DeviceName)
                {
                    break;
                }

            }
            if (mainmenu.OptSingleScreen.Checked == false )
            {
                
                dlg.Location = new Point(Screen.AllScreens[DisplayIndex].Bounds.Left, Screen.AllScreens[DisplayIndex].Bounds.Top);
            }
            

			dlg.CreateButtons(nButtons,mainmenu.def.CLButtonsLayout);
			dlg.ButtonEvt += new HearingAidLab.CatLoudUser.ButtonEventHandler(dlg_ButtonEvt);
            dlg.Show();
		}

//gui functions
		private void CategoricalLoudness_Closing(object sender, CancelEventArgs e)
		{
			player.Close();
			if(dlg!=null)
				dlg.Close();
			GC.Collect();
			mainmenu.Show();
		}

		private void btnSkip_Click(object sender, System.EventArgs e)
		{
			Draw();

		}
		
//drawing functions
		private void Draw()
		{
			this.Invalidate(true);
			this.Update();
		}
		protected override void OnPaint( PaintEventArgs e)
		{
			base.OnPaint(e);
			Graphics dc = e.Graphics;
			PlotGraph (dc);
			panel1.Hide();
		}
		private void DrawGraph(Graphics g)
		{
			int x = panel1.Location.X;
			int y = panel1.Location.Y+panel1.Height-10;
			int width = panel1.Width;
			int height = panel1.Height;

			System.Drawing.SolidBrush brush = new SolidBrush(Color.Blue);
			Pen pen = new Pen(brush,2);
			Pen penDotted = new Pen(brush,1);
			penDotted.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
			
			Font font = new Font("Arial",8);
			//draw a graph frame
			g.DrawLine(pen,x+10,y-10,x+width,y-10);
			g.DrawLine(pen,x+10,y-10,x+10,y-height); 
			g.DrawString(mainmenu.txtName.Text,font,brush,x+50,y-panel1.Height);
            g.DrawString("Frequency:- " + txtPrimary.Text, font, brush, x + 200 , y - panel1.Height);
			g.DrawString(mainmenu.txtBirth.Text,font,brush,x+200,y-panel1.Height+20);

			//x scale is 0 to CalDb
			int nXRange = (int) mainmenu.CalDb/10+1;
			int nXStep = panel1.Width/nXRange;
			double nYStep = panel1.Height/10;
			int nLabel = 0;
			for(int i=0;i<nXRange;i++)
			{
				g.DrawString(nLabel.ToString(),font,brush,x+nXStep*i+5,y-10);
			//	g.DrawLine(penDotted,x+nXStep*i+5,y-10,x+nXStep*i+5,(float) (y-nYStep*11));
				nLabel+=10;
			}
			//y scale is 0 to 50 in nButton steps
			//float yrange = (float) (50.0/nButtons);
			//int nYRange = (int) yrange;
			nLabel = 5;
			for(int i = 1;i<11;i++)
			{
				g.DrawString(nLabel.ToString(),font,brush,x-10,(int) (y-nYStep*i));
				//g.DrawLine(penDotted,x,(float)(y-nYStep*i),x+nXStep*nXRange+5,(float)( y-nYStep*i));
				nLabel+=5;
			}

		}

		private void DrawLine(Graphics g, Color c, SortedList sl)
		{
			try
			{
				int x = panel1.Location.X;
				int y = panel1.Location.Y+panel1.Height;
				int width = panel1.Width;
				int height = panel1.Height;
				System.Drawing.SolidBrush brush = new SolidBrush(c);
				Pen pen = new Pen(brush,2);
				Font font = new Font("Arial",8);
			
				double yScale = panel1.Height/50.0;
				double nXRange = (int) mainmenu.CalDb/10+1;
				double nXScale = panel1.Width/(nXRange*10);
				Point[] pt = new Point[sl.Count];
				for(int i=0;i<sl.Count;i++)
				{
					float X = (float) sl.GetKey(i);
					int Y = (int)sl.GetByIndex(i);
					pt[i].X = (int) (x+nXScale*X);
					pt[i].Y = (int) (y-yScale*Y);
				}
				if(pt.Length>0)
				{
					try
					{
						g.DrawLines(pen,pt);
					}
					catch(Exception err)
					{
						Form1.ErrorMsg("Drawing Line: "+err.Message);
					}
				}
			}
			catch(Exception err)
			{
				Form1.ErrorMsg("Calculating Line: "+err.Message);
			}
		}
		private void DrawLine(Graphics g, float[] X,Color c)
		{
			int x = panel1.Location.X;
			int y = panel1.Location.Y+panel1.Height;
			int width = panel1.Width;
			int height = panel1.Height;
			System.Drawing.SolidBrush brush = new SolidBrush(c);
			Pen pen = new Pen(brush,2);
			Font font = new Font("Arial",8);
			//X should be 50 in length, each one relating to a point on the Y Axis
			double yScale = panel1.Height/50.0;
            double nXRange = (int) mainmenu.CalDb/10+1;
			double nXScale = panel1.Width/(nXRange*10);
			Point[] pt = new Point[45];
			for(int i=0;i<45;i++)
			{
				pt[i].X = (int) (x+nXScale*X[i+5]);
				pt[i].Y = (int) (y-yScale*(i+5));
			}
			try
			{
				g.DrawLines(pen,pt);
				//g.DrawCurve(pen,pt,0,49,1);
			}
			catch(Exception err)
			{
				return;
			}
		}

		private void DrawLine(Graphics g, float m, float b, Color c)
		{
			//y = mx+b
			int x = panel1.Location.X;
			int y = panel1.Location.Y+panel1.Height;
			int width = panel1.Width;
			int height = panel1.Height;
			System.Drawing.SolidBrush brush = new SolidBrush(c);
			Pen pen = new Pen(brush,1);
			Font font = new Font("Arial",8);
			//X should be 50 in length, each one relating to a point on the Y Axis
			double yScale = panel1.Height/50.0;
			//double nXRange = (int) mainmenu.CalDb/10+1;
			double nXRange = (int) mainmenu.CalDb/10+1;
			double nXScale = panel1.Width/(nXRange*10);
			Point[] pt = new Point[(int) mainmenu.CalDb];
			int z = 0;
			for(int i=0;i<mainmenu.CalDb;i++)
			{
				float Y = m*i+b;
				if(Y<0||Y>50)
					continue;
				pt[z].X = (int) (x+nXScale*i+10);
				pt[z].Y = (int) (y-yScale*Y-10);
				z++;
				
			}
			try
			{
				Point[] pts = new Point[z];
				for(int i=0;i<z;i++)
				{
					pts[i] = pt[i];
				}
				g.DrawLines(pen,pts);
				//g.DrawCurve(pen,pt,0,z-1,1);
			}
			catch(Exception err)
			{
				return;
			}
		}
		private void DrawCircles(Graphics g, Color c, SortedList sl, int nOffset)
		{
			try
			{
				int x = panel1.Location.X;
				int y = panel1.Location.Y+panel1.Height;
				int width = panel1.Width;
				int height = panel1.Height;
				System.Drawing.SolidBrush brush = new SolidBrush(c);
				Pen pen = new Pen(brush,2);
				Font font = new Font("Arial",8);
				//X should be 50 in length, each one relating to a point on the Y Axis
				double yScale = panel1.Height/50.0;
				double nXRange = (int) mainmenu.CalDb/10+1;
				double nXScale = panel1.Width/(nXRange*10);
				for(int i=0;i<sl.Count;i++)
				{
					float X = (float) sl.GetKey(i);
					int Y = (int) sl.GetByIndex(i);
					g.FillEllipse(brush, (float ) (x+nXScale*X-4+nOffset), 
						(float) (y-yScale*Y),
						8,8);
				}
			}
			catch(Exception err)
			{
				Form1.ErrorMsg("Drawing Circles: " + err.Message);
				return;
			}

		}
		
		/*private void DrawCurve(Graphics g)
		{
			if(CurveCount<=0)
				return;
			int x = panel1.Location.X;
			int y = panel1.Location.Y+panel1.Height;
			int width = panel1.Width;
			int height = panel1.Height;
			System.Drawing.SolidBrush brush = new SolidBrush(Color.Blue);
			Pen pen = new Pen(brush,1);
			Font font = new Font("Arial",8);
			//X should be 50 in length, each one relating to a point on the Y Axis
			double yScale = panel1.Height/50.0;
			//double nXRange = (int) mainmenu.CalDb/10+1;
			double nXRange = (int) mainmenu.CalDb/10+1;
			double nXScale = panel1.Width/(nXRange*10);
			Point[] pt = new Point[CurveCount];
			int z = 0;
			for(int i=0;i<CurveCount;i++)
			{
				pt[z].X = (int) (x+nXScale*curve[i,0]+10);
				pt[z].Y = (int) (y-yScale*curve[i,1]-10);
				z++;
			}
			try
			{
				g.DrawCurve(pen,pt,0,CurveCount-1,1);
			}
			catch(Exception err)
			{
				return;
			}

		}*/
		/*private void DrawTempL(Graphics g)
		{
			if(CurveCount<=0)
				return;
			int x = panel1.Location.X;
			int y = panel1.Location.Y+panel1.Height;
			int width = panel1.Width;
			int height = panel1.Height;
			System.Drawing.SolidBrush brush = new SolidBrush(Color.Red);
			Pen pen = new Pen(brush,2);
			Font font = new Font("Arial",8);
			//X should be 50 in length, each one relating to a point on the Y Axis
			double yScale = panel1.Height/50.0;
			//double nXRange = (int) mainmenu.CalDb/10+1;
			double nXRange = (int) mainmenu.CalDb/10+1;
			double nXScale = panel1.Width/(nXRange*10);
			Point[] pt = new Point[50];
			int z = 0;
			for(int i=0;i<50;i++)
			{
				pt[z].X = (int) (x+nXScale*tempL[i]+10);
				pt[z].Y = (int) (y-yScale*i-10);
				z++;
			}
			try
			{
				g.DrawCurve(pen,pt,0,49,1);
			}
			catch(Exception err)
			{
				return;
			}

		}  */
//bridge functions (Start this, start that)
		private bool Start()
		{
			Phase = CLPhase.GetPositiveResponse;
			//Play signal at
			if(GetNextStim()==true)
			{
#if DEBUG
				
			/*	CurrentStim.Min = 40;
				CurrentStim.Max = 90;
				CurrentStim.MaxLoudness = 45;
				CurrentStim.TestedLevels.Add(CurrentStim.Min, 5);
				CurrentStim.TestedLevels.Add(CurrentStim.Max, CurrentStim.MaxLoudness);
				CurrentStim.TestedLevels.Add(45.0f,10);
				CurrentStim.TestedLevels.Add(50.0f,15);
				CurrentStim.TestedLevels.Add(55.0f,20);
				CurrentStim.TestedLevels.Add(60.0f,25);
				CurrentStim.TestedLevels.Add(65.0f,30);
				CurrentStim.TestedLevels.Add(70.0f,35);
				CurrentStim.TestedLevels.Add(75.0f,40);
				CurrentStim.TestedLevels.Add(80.0f,40);
				CurrentStim.TestedLevels.Add(85.0f,45);
				CurrentStim.PastLevels.Add(CurrentStim.TestedLevels);
				CurrentStim.PastLevels.Add(CurrentStim.TestedLevels);
				Draw();
				/*Phase = CLPhase.Phase2;
				Draw();
				StartPhase3();*/
#endif
				//If we are finding Min Max every time
				if(def.bAnchoredTrials==false||CurrentStim.Max<0)
				{
					if(CurrentStim.TestedLevels.Count>0)
					{
						CurrentStim.PastLevels.Add(CurrentStim.TestedLevels);
						CurrentStim.TestedLevels = new SortedList();
					}
					output.WriteLine("%PHASE 0 - DETERMINE MIN/MAX");
					output.WriteLine("Stimulus: {0}",this.txtPrimary.Text);
					output.WriteLine(string.Empty);
					output.WriteLine("Stimulus, Level(dB), Loudness Assigned");
					PresentStim();
				}
				else
				{
					nMin = CurrentStim.Min;
					nMax = CurrentStim.Max;
					output.WriteLine("%ANCHORED TRIAL");
					output.WriteLine("Stimulus: {0}",this.txtPrimary.Text);
					string str = string.Format("Min: {0}, Max: {1}",
						CurrentStim.Min,CurrentStim.Max);
					StartAnchoredTrials();
					PresentStim();
					//StartPhase1();
				}
				ResponseTimer.Start();
			}
			else//GetStim returned false
				return false;
			return true;
		}
		private void StartPhase1()
		{
			CurrentStim.TestedLevels.Add(CurrentStim.Min, 5);
			CurrentStim.TestedLevels.Add(CurrentStim.Max, CurrentStim.MaxLoudness);
			//write current results
			string str = string.Format("Min: {0}, Max: {1}",
				CurrentStim.Min,CurrentStim.Max);
			output.WriteLine(str);
			output.WriteLine(string.Empty);
			output.WriteLine("%PHASE 1 - TEST DATA POINTS");
			output.WriteLine(string.Empty);
			output.WriteLine("Stimulus, Level(dB), Loudness Assigned");
			txtMin.Text = CurrentStim.Min.ToString();
			txtMax.Text = CurrentStim.Max.ToString();
			txtFunction.Text = "Phase 1 - Find 4 main points";
			if(RandomSet!=null)
				RandomSet.Clear();
			else
				RandomSet = new SortedList();
			Phase = CLPhase.Phase1;
			//have min and max, find some data points1
			float f = CurrentStim.Max - CurrentStim.Min;//that's how much space we have to cover
			//get 4 equidistant points along that line
			f/=5;
			RandomSet.Clear();
			for(int x=1;x<5;x++)
			{
				int z = r.Next(10000);
				while(RandomSet.ContainsKey(z)==true)
				{
					z = r.Next(10000);
				}
				RandomSet.Add(z,Round(CurrentStim.Min+(f*x)));//put them into RandomSet in Random order
			}
			//set current level
			fCurrentLevel = (float) RandomSet.GetByIndex(0);
			RandomSet.RemoveAt(0);
		}
		private void StartPhase2()
		{
			txtMin.Text = CurrentStim.Min.ToString();
			txtMax.Text = CurrentStim.Max.ToString();
			txtFunction.Text = "Phase 2 - Midpoints";
			if(RandomSet!=null)
				RandomSet.Clear();
			else
				RandomSet = new SortedList();
			Phase = CLPhase.Phase2;
			//do the interp, find midpoints between each of the tested points, and test them
			for(int z=1;z<CurrentStim.TestedLevels.Count;z++)
			{
				float a = (float) CurrentStim.TestedLevels.GetKey(z-1);
				a += (float) CurrentStim.TestedLevels.GetKey(z);
				int k = r.Next(12345);
				while(RandomSet.ContainsKey(k)==true)
				{
					k = r.Next(12345);
				}
				RandomSet.Add(z,Round(a/2.0f));
			}
			fCurrentLevel = (float) RandomSet.GetByIndex(0);
			RandomSet.RemoveAt(0);
		}
		private void StartPhase3()
		{
			txtFunction.Text = "Phase 3 - Additional";
			if(RandomSet!=null)
				RandomSet.Clear();
			else
				RandomSet = new SortedList();
			Phase = CLPhase.Phase3;
			for(int z = 1;z<CurrentStim.TestedLevels.Count;z++)
			{
				int a = (int) CurrentStim.TestedLevels.GetByIndex(z-1);
				int b = (int) CurrentStim.TestedLevels.GetByIndex(z);
				if(Math.Abs(a-b)>=10)//>=15 Loudness units between them, 
				{
					float db1 = (float) CurrentStim.TestedLevels.GetKey(z-1);
					float db2 = (float) CurrentStim.TestedLevels.GetKey(z);
					db1+=2.5f;
					int q;
					while(db1<db2)
					{
						q = r.Next(12345);
						while(RandomSet.ContainsKey(q)==true)
						{
							q = r.Next(12345);
						}
						RandomSet.Add(q,db1);
						output.WriteLine("Testing additional Level {0} dB",db1);
						db1+=2.5f;
					}
				}
			}
			if(RandomSet.Count>0)
			{
				fCurrentLevel = (float) RandomSet.GetByIndex(0);
				RandomSet.RemoveAt(0);
			}
			else
				bDone = true;
		}
		private void StartAnchoredTrials()
		{
			output.WriteLine("%ANCHORED TRIALS - RETEST DATA POINTS");
			output.WriteLine("Stimulus: {0}",this.txtPrimary.Text);
			output.WriteLine(string.Empty);
			output.WriteLine("Stimulus, Level(dB), Loudness Assigned");
			//randomly test all values in CurrentStim.TestedLevels
			Phase = CLPhase.AnchoredTrials;
			txtFunction.Text = "Anchored Trials";
			if(RandomSet!=null)
				RandomSet.Clear();
			else
				RandomSet = new SortedList();
			int k;
			for(int z=0;z<CurrentStim.TestedLevels.Count;z++)
			{
				//do the low ones first, as a group, then do the high ones
				if(z<6)
				{
					k = r.Next(1000);
					while(RandomSet.ContainsKey(k)==true)
					{
						k = r.Next(1000);
					}
					RandomSet.Add(k,(float)CurrentStim.TestedLevels.GetKey(z));
				}
				else
				{
					k = 1000+r.Next(1000);
					while(RandomSet.ContainsKey(k)==true)
					{
						k = 1000+r.Next(1000);
					}
					RandomSet.Add(k,(float)CurrentStim.TestedLevels.GetKey(z));
				}
			}
			if(RandomSet.Count>0)
			{
				fCurrentLevel = (float) RandomSet.GetByIndex(0);
				RandomSet.RemoveAt(0);
			}
			else
			{
				CurrentStim.Max=-1;
				Start();
			}
			CurrentStim.PastLevels.Add(CurrentStim.TestedLevels);
			CurrentStim.TestedLevels = new SortedList();
			//do the interstim delay here, otherwise it skips it
			System.Threading.Thread.Sleep(mainmenu.def.nDelay);
		}
		private bool GetNextStim()
		{
			try
			{
				txtFunction.Text = "Get Initial Response";
//				bDrawNextL = false;
				//bDrawCurrentL = false;
				if(CurrentStim!=null)
					WriteResults();
				nCurrentStim++;
				if(nCurrentStim>=Stims.Count)
					return false;
				CurrentStim = (CLData) Stims[nCurrentStim];
				fCurrentLevel = CurrentStim.s.nOrigin;
				if(CurrentStim.s.strType=="wave")
					txtPrimary.Text = CurrentStim.s.strFile;
				else
					txtPrimary.Text = CurrentStim.s.nFreq.ToString() + "  " + CurrentStim.s.strType;
				
			}
			catch(Exception err)
			{
				Form1.ErrorMsg(err.Message);
				return false;
			}
			
			bDone = false;
			return true;
		}
		/*private bool GetNextL()
		{
			if(RandomSet.Count>0)
			{
				nCurrentL = (int) RandomSet.GetByIndex(0);
				fCurrentLevel =  L[nCurrentL];
				RandomSet.RemoveAt(0);
				return true;
			}
			else
				return false;
		}*///presentation functions
		private void PresentStim()
		{
			dlg.LightListen();
			if(bDone==true)
				return;
			//Set Level
			txtLevel.Text = fCurrentLevel.ToString();
			int V2 = GetPrimaryLevel();
			player.Signals[0] = CurrentStim.s.buffer;
			player.Signals[0].SetLevel((int) V2);

			player.Signals[0].Play();
            player.Signals[0].AmplificationType = mainmenu.def.PrimaryStims[0].AmpType;
			//dlg.Show();
			player.Play();
			//Play it
			bButtons = true;
			dlg.LightRespond();
		}
		private int GetPrimaryLevel()
		{
            // The Primary Level has to be attuenated to
			int V2 = 0;
			if(CurrentStim.s.strType=="wave")
			{
				//set level
				double d = mainmenu.CalDb;
				if(fCurrentLevel>mainmenu.def.nMaxLevel)
					fCurrentLevel = mainmenu.def.nMaxLevel;
				double fLevel = fCurrentLevel - d;
				V2 = (int) (mainmenu.MaxAmplitude*(Math.Pow(10,fLevel/20)) );
				if(V2>mainmenu.MaxAmplitude)
					V2 = mainmenu.MaxAmplitude;
			}
			else if(CurrentStim.s.strType!="wave")
			{
				//only if it is not a wave
                if (V2 > mainmenu.MaxAmplitude)
                {
                    MessageBox.Show("Volume requested("+ V2.ToString()+ ") to play is greator than Maximum allowed ( " + mainmenu.MaxAmplitude.ToString() + " )");
                    return 0;
                }
				V2 = mainmenu.GetV2(fCurrentLevel- mainmenu.def.PrimaryStims[0].attenuation ,CurrentStim.s.nFreq,CurrentStim.s.strEar);
			}
			return V2;
		}
		
//timer functions
		private void ResponseTimer_Tick(object sender, EventArgs e)
		{

		}

		private void InterStimDelay_Tick(object sender, EventArgs e)
		{
			InterStimDelay.Stop();
			InterStimDelay.Enabled = false;
			PresentStim();
		}

//button functions
		private void dlg_ButtonEvt(object sender, EventArgs e)
		{
			if(bButtons==false)
				return;
			bButtons = false;
			nCount++;
			//txtMax.Text = nCount.ToString();
			//dlg.Hide();
            dlg.LightNone(); 
			ResponseTimer.Stop();
			ResponseTimer.Enabled = false;
			InterStimDelay.Stop();
			InterStimDelay.Enabled = false;
			

			Button b = (Button) sender;
			int x = (int) b.Tag;
			WriteResponse(x);
			if(Phase==CLPhase.GetPositiveResponse||Phase==CLPhase.FindingMin||Phase==CLPhase.FindingMax)
				Phase0Button(x);
			else if(Phase==CLPhase.Phase1)//if we're finding min/max
				Phase1Button(x);
			else if(Phase==CLPhase.Phase2)//we're doing the 2nd phase
				Phase2Button(x);
			else if(Phase==CLPhase.Phase3||Phase==CLPhase.AnchoredTrials)
				Phase3Button(x);
			if(bDone==true)
			{
				if(Start()==false)
					Complete();
			}
			else
			{
				Draw();
				InterStimDelay.Enabled = true;
				InterStimDelay.Start();
			}
			//bButtons = true;
		}
		private void Phase0Button(int x)
		{
			if(Phase==CLPhase.GetPositiveResponse)
			{
				if(x==nButtons-1)
					fCurrentLevel+=5;//increase signal level
				else
				{
					Phase = CLPhase.FindingMin;//start right in on finding the min
					txtFunction.Text = "Finding Min";
				}
			}
			if(Phase==CLPhase.FindingMin)
			{
				#region FindingMin
				if(bInaudible==true)//they didn't hear the last one
				{
					if(x!=nButtons-1)
					{
						CurrentStim.arrMin[CurrentStim.index++] = fCurrentLevel;
						bInaudible = false;
						//fCurrentLevel = CurrentStim.s.nOrigin;
						fCurrentLevel += 10;
						if(CurrentStim.index==2)//if there are two
						{
							if(CurrentStim.arrMin[0]==CurrentStim.arrMin[1])//if they are the same
							{
								//set min, and move on
								CurrentStim.SetMin();
								fCurrentLevel = CurrentStim.s.nOrigin > 70 ? CurrentStim.s.nOrigin : 70;
								txtMin.Text = CurrentStim.Min.ToString();
								Phase = CLPhase.FindingMax;
								txtFunction.Text = "Finding Max";
							}
						}
						else if(CurrentStim.index==3)//we've found the three, set the min and move to max
						{
							CurrentStim.SetMin();
							fCurrentLevel = CurrentStim.s.nOrigin > 70 ? CurrentStim.s.nOrigin : 70;
							txtMin.Text = CurrentStim.Min.ToString();
							Phase = CLPhase.FindingMax;
							txtFunction.Text = "Finding Max";
						}
					}
					else//the didn't hear this one, either
						fCurrentLevel += 2.5f;
				}
				else//they did hear the last one
				{
					if(x==nButtons-1)//they did not hear this on
					{
						bInaudible = true;
						fCurrentLevel += 2.5f;
					}
					else//they did hear it, decrease level
						fCurrentLevel -= 10;
				}
#endregion
			}
			else if(Phase==CLPhase.FindingMax)
			{
				#region FindingMax
				if(this.bTooLoud==true)//the last one was too loud
				{
					if(x!=0)
					{
						//was too loud, but now it's not
						CurrentStim.arrMax[CurrentStim.index++] = fCurrentLevel;
						fCurrentLevel -= 10;
						bTooLoud = false;
						if(CurrentStim.index==2)//if there are two
						{
							if(CurrentStim.arrMax[0]==CurrentStim.arrMax[1])//if they are the same
							{
								//set max, and move on
								CurrentStim.SetMax();
								txtMax.Text = CurrentStim.Max.ToString();
								Phase = CLPhase.Phase1;
								StartPhase1();
							}
						}
						else if(CurrentStim.index==3)//we've found the three, set the min and move to max
						{
							CurrentStim.SetMax();
							txtMax.Text = CurrentStim.Max.ToString();
							Phase = CLPhase.Phase1;
							StartPhase1();
						}
					}
					if(x==0)//too loud button
					{
						//is still too loud
						fCurrentLevel-=2.5f;
					}
				}
				else//the last one was not too loud
				{
					if(x!=0)
					{
						//if we are at max, and they didn't say it was too loud, pretend it is
						ChirpCal cal = mainmenu.LeftCal;
						if(CurrentStim.s.strEar.ToLower()=="right")
							cal = mainmenu.LeftCal;
						if( (cal==null && mainmenu.CalDb <= fCurrentLevel) ||
							(cal!=null && cal.GetMax(CurrentStim.s.nFreq) < fCurrentLevel) ||
							(mainmenu.def.nMaxLevel <= fCurrentLevel) )
						{
							CurrentStim.MaxLoudness = GetLoudnessFromButton(x);
							//was too loud, but now it's not
							CurrentStim.arrMax[CurrentStim.index++] = fCurrentLevel;
							fCurrentLevel -= 10;
							bTooLoud = false;
							if(CurrentStim.index==2)//if there are two
							{
								if(CurrentStim.arrMax[0]==CurrentStim.arrMax[1])//if they are the same
								{
									//set max, and move on
									CurrentStim.SetMax();
									txtMax.Text = CurrentStim.Max.ToString();
									Phase = CLPhase.Phase1;
									StartPhase1();
								}
							}
							else if(CurrentStim.index==3)//we've found the three, set the min and move to max
							{
								CurrentStim.SetMax();
								txtMax.Text = CurrentStim.Max.ToString();
								Phase = CLPhase.Phase1;
								StartPhase1();
							}
						}
						else
						{
							fCurrentLevel += 5;
							if(mainmenu.def.nMaxLevel < fCurrentLevel)
								fCurrentLevel = mainmenu.def.nMaxLevel;
							//if we are over .def file max
							//if we are over max, reduce to max
							if((cal==null && mainmenu.CalDb < fCurrentLevel) ||
								(cal!=null && cal.GetMax(CurrentStim.s.nFreq) < fCurrentLevel)  )
							{
								fCurrentLevel = (float) (mainmenu.CalDb);
								if(mainmenu.cal!=null)
									fCurrentLevel = (float) (mainmenu.cal.GetMax(CurrentStim.s.nFreq));
							}
						}
					}
					if(x==0)
					{
						//they did say it was too loud
						bTooLoud = true;
						fCurrentLevel-=2.5f;//reduce level until they say it isn't too loud
					}
				}
				#endregion
			}
			//InterstimDelay gets started in ButtonEvent
		}
		private void Phase1Button(int x)
		{
			//store response, get next level from RandomSet
			if(CurrentStim.TestedLevels.ContainsKey(fCurrentLevel)==false)
				CurrentStim.TestedLevels.Add(fCurrentLevel, GetLoudnessFromButton(x));
			else
				CurrentStim.TestedLevels[fCurrentLevel] = GetLoudnessFromButton(x);
			if(RandomSet.Count>0)
			{
				fCurrentLevel = (float) RandomSet.GetByIndex(0);
				RandomSet.RemoveAt(0);
			}
			else
				StartPhase2();
			//InterstimDelay gets started in ButtonEvent
		}
		private void Phase2Button(int x)
		{
			//store response, get next level from RandomSet
			if(CurrentStim.TestedLevels.ContainsKey(fCurrentLevel)==false)
				CurrentStim.TestedLevels.Add(fCurrentLevel, GetLoudnessFromButton(x));
			else
				CurrentStim.TestedLevels[fCurrentLevel] = GetLoudnessFromButton(x);
			if(RandomSet.Count>0)
			{
				fCurrentLevel = (float) RandomSet.GetByIndex(0);
				RandomSet.RemoveAt(0);
			}
			else
				StartPhase3();
			//InterstimDelay gets started in ButtonEvent
		}
		private void Phase3Button(int x)
		{
			//store response, get next level from RandomSet
			if(CurrentStim.TestedLevels.ContainsKey(fCurrentLevel)==false)
				CurrentStim.TestedLevels.Add(fCurrentLevel, GetLoudnessFromButton(x));
			else
				CurrentStim.TestedLevels[fCurrentLevel] = GetLoudnessFromButton(x);
			if(RandomSet.Count>0)
			{
				fCurrentLevel = (float) RandomSet.GetByIndex(0);
				RandomSet.RemoveAt(0);
			}
			else
				bDone = true;
		}
		private int GetLoudnessFromButton(int x)
		{
			int nB = nButtons-1;
			double f = 50.0/nB;
			int z = (int) ((nB-x)*f);
			return z;
		}
		private void Complete()
		{
			ResponseTimer.Enabled = false;
			InterStimDelay.Enabled = false;
			ResponseTimer.Stop();
			InterStimDelay.Stop();
			dlg.LightNone();
			MessageBox.Show(this,"Complete");
			bDone = true;
			output.Flush();
			output.Close();
		}

//helper functions
		private int GetRandom()
		{
			int z = r.Next(100);
			while(RandomSet.Contains(z)==true)
			{
				z = r.Next(100);
			}
			return z;
		}
		
		
		/*private void GetCurve()
		{
			double[] r = new double[6];
			double[] l = new double[6];
			for(int i=0;i<6;i++)
			{
				r[i] = R[i+1];
				l[i] = L[i+1];
			}
			double[] p = polyfit(r,l);
			double[] f = new double[45];
			for(int i=0;i<45;i++)
			{
				f[i] = i+5;
			}
			double[] newR = polyval(p,f);
			this.CurveCount = 45;
			for(int i=0;i<45;i++)
			{
				curve[i,0] = newR[i];
				curve[i,1] = f[i];
			}
		}*/
		private float Round(float f)
		{
			int x = (int) (f/ 2.5);
			if(f%2.5>0.5)
				x++;
			return x*2.5f;
		}
		//output functions
		private void WriteResponse(int x)
		{
			int nB = nButtons-1;
			double f = 50.0/nB;
			//int f = 50/nB;
			double Response = (nB-x)*f;
			
			string str = string.Format("{0},{1},{2}",
				this.txtPrimary.Text,this.txtLevel.Text,Response);
			output.WriteLine(str);
			output.Flush();
		}
		private void WriteResults()
		{
			output.WriteLine(string.Empty);
			output.WriteLine("%Stim complete: {0}", this.txtPrimary.Text);
			output.WriteLine("Signal Level (dB),Loudness Assigned (1-50)");
			for(int i=0;i<CurrentStim.TestedLevels.Count;i++)
			{
				string str = string.Format("{0},{1}",
					CurrentStim.TestedLevels.GetKey(i),CurrentStim.TestedLevels.GetByIndex(i));
				output.WriteLine(str);
			}
			/*double[,] d = InterpdB();
			output.WriteLine(string.Empty);
			output.WriteLine("%DATA INTERP");
			output.WriteLine("Level (dB), Loudness");
			int z = 4;
			if(nMin!=0||nMin!=1)
			{
				int kk = (int) nMin/5;
				kk-=1;
				z+=kk*5;
			}
			if(z<4)
				z = 4;
			for(int i=z;i<nMax;)
			{
				output.WriteLine("{0},{1}",
					d[i,0].ToString("##0"),d[i,1].ToString("##0"));
				if(d[i,1]<25)
					i+=5;
				else
					i+=2;
			}*/
			output.WriteLine(string.Empty);
			output.WriteLine("---------------------------------------------------------");
			output.WriteLine(string.Empty);
		}

		private void CategoricalLoudness_Load(object sender, System.EventArgs e)
		{
		
		}

		private void btnSaveGraph_Click(object sender, System.EventArgs e)
		{ 
			// save as dialog
			SaveFileDialog dlg = new SaveFileDialog();
			dlg.Filter="Graph points (*.grp)|*.grp";
			dlg.Filter += "|All files|*.*";
			if(dlg.ShowDialog()== DialogResult.OK)
            {
                string str;
				StreamWriter sw  = new StreamWriter(dlg.FileName, false);

                foreach (SortedList itemList in CurrentStim.PastLevels)
                {
                    sw.Write("\n");
                    for (int i = 0; i < itemList.Count; i++)
                    {
                        str = string.Format("{0},{1}",
                           itemList.GetKey(i), itemList.GetByIndex(i));
                        sw.WriteLine(str);
                    }
                }
                sw.Write("\n");
				for(int i =0;i<CurrentStim.TestedLevels.Count;i++)
				{
                    
					str = string.Format("{0},{1}",
						CurrentStim.TestedLevels.GetKey(i),CurrentStim.TestedLevels.GetByIndex(i));
					sw.WriteLine(str);
				}
               	sw.Close();
			}
		}

		private void btnLoadGraph_Click(object sender, System.EventArgs e)
		{
			OpenFileDialog dlg = new OpenFileDialog();
			dlg.Filter = "Graph points (*.grp)|*.grp";
			dlg.Filter += "|All files|*.*";
			dlg.Multiselect = false;
			String strLine;
			SortedList slGraph = new SortedList();
            
			if(dlg.ShowDialog()==DialogResult.OK)
			{
				StreamReader s = new StreamReader(dlg.FileName);
                while ((strLine = s.ReadLine()) != null)
				{
					try
					{
                        if (strLine == "")
                        {
                            if (slGraph.Count > 0)
                            {
                                CurrentStim.PastLevels.Add(slGraph);
                                slGraph = new SortedList();
                            }

                        }
                        else
                        {


                            String[] sTemp;
                            sTemp = strLine.Split(',');
                            float fKey = (float)Convert.ToDouble(sTemp[0]);
                            int iVal = Convert.ToInt32(sTemp[1]);
                            slGraph.Add(fKey, iVal);
                        }
                        
					}
					catch(Exception ex){continue;}
					
				}
                CurrentStim.TestedLevels = slGraph;
                

                
				this.Refresh();
			}
		}

		private void btnPrintGraph_Click(object sender, System.EventArgs e)
		{
			PrintDialog dlg = new PrintDialog();
		 
			dlg.AllowSelection = false;
			dlg.AllowSomePages = false;
			dlg.ShowHelp = false;
			dlg.ShowNetwork = false;
			dlg.Document = new System.Drawing.Printing.PrintDocument();
			if (dlg.ShowDialog() == DialogResult.OK)
			{
				PrintDocument pd = new PrintDocument();
				pd.PrinterSettings = dlg.PrinterSettings;
				pd.PrintPage += new PrintPageEventHandler(DoPrint);
				pd.Print();
			}

		}
		private void DoPrint(Object O,System.Drawing.Printing.PrintPageEventArgs e)
		{
			PlotGraph(e.Graphics);
			e.HasMorePages=false;

		}
		private void PlotGraph(Graphics dc)
		{
			DrawGraph(dc);
			
			if(CurrentStim!=null)
			{
				for(int x=0;x<CurrentStim.PastLevels.Count;x++)
				{
					DrawCircles(dc,colors[x],(SortedList)CurrentStim.PastLevels[x],(x+1)*4);
				}
				if(CurrentStim.TestedLevels.Count>1)
					DrawLine(dc,Color.Red,CurrentStim.TestedLevels);
				 DrawCircles(dc, Color.Red, CurrentStim.TestedLevels, 0);
			}
			
		}
	

	}
}
