
// Deklarace tríd koponet

using System;
using System.Drawing;
using System.Text;
using System.Threading;

namespace KomponentyCIP
{	
	// Deklarace delegatu pouzivanych pro komponenty CIP
	public delegate double ClickNaKomponentuHandler(double OldZadanaHodnota);
	
	/*******************************************************************************************************************
	 *                 				Třídy definujici graficke rozhrani jednotlivych komponent						   *
	 * *****************************************************************************************************************/

	/*
	 * Abstraktni zakladni trida pro vsechny komponety cisticic stanice
	 * Ventily, cerpadla, klapky, ... 
	 * Definuje zakladni prvky pro graficke rozhrani, prazdny konstruktor
	 */
	
	public abstract class Komponenta
	{
		// Promena urcujici stav inicializace tridy
		protected bool INIT = false;
		
		// Stavove promenne
		protected double Stav;
		public double ZadanaHodnota;
		
		// Promenne pro graficke prostredi
		protected int X_size;
		protected int Y_size;
		protected int X_position;
		protected int Y_position;
		public string Text1;
		public string Text2;
		protected bool MysNadKomponentou;
		
		// Udalost pro kliknuti na komponentu
		public event ClickNaKomponentuHandler Click;
		
		// Funkce Spoustejici udalost click
		// Tato funkce bude spoustena pri stisku tlacitka mysi v hlavnim formulari
		public void SpustPriKliknutiMysi(){
			
			if(this.MysNadKomponentou)
				if(this.Click != null)
					this.ZadanaHodnota = this.Click(this.ZadanaHodnota);
		}
			
		// Deklarace spolecnych vlastnosti
		public Point Position{
			set{
				this.X_position = value.X;
				this.Y_position = value.Y;
			}
			get{
				return new Point(this.X_position, this.Y_position);
			}
		}
		
		public System.Drawing.Size size{
			set{
				this.Y_size = value.Height;
				this.X_size = value.Width;
			}
			get{
				return new Size(this.X_size, this.Y_size);
			}
		}
		
		public Point GetConnectionPoint1{
			get{
				return ConnectionPoint1();
			}
		}
		
		public Point GetConnectionPoint2{
			get{
				return ConnectionPoint2();
			}
		}
		
		// vlastnost pro nastaveni stavove velicicny
		public double stav{
			set{ this.Stav = value;}
			get{ return this.Stav;}
		}
		
		// Deklarace abstrakrnich metod komponent
		protected abstract Point ConnectionPoint1();
		protected abstract Point ConnectionPoint2();
		
		// Zaklad metody pro vykreslovani komponenty na obrazovku
		// Tato bazova metoda zajistuje pouze vykreslovani ctverce okolo komponenty, je-li nad ni kurzor mysi
		public virtual void DrawToScreen(Graphics gfx){
			if(MysNadKomponentou){
				Rectangle ctverec = new Rectangle(new Point(this.X_position - 4, this.Y_position  - 4), new Size(this.X_size + 8, this.Y_size + 8));
				gfx.DrawRectangle(Pens.Black, ctverec);
			}
				
		}
		
		// virtualni funkce pro event zmeny velikosti
		public virtual void ReSizeComponet(double Pomer_X, double Pomer_Y){
			
			if ( Pomer_X != 1){
				this.X_position = System.Convert.ToInt32(this.X_position * Pomer_X);
				this.X_size = System.Convert.ToInt32(this.X_size * Pomer_X);
			}
			
				if ( Pomer_Y != 1){
				this.Y_position = System.Convert.ToInt32(this.Y_position * Pomer_Y);
				this.Y_size = System.Convert.ToInt32(this.Y_size * Pomer_Y);
			}
		}	
			
		// Funkce detekujici ukazatel mysi nad komponentou
		public void JeMysNadKomponentou(int X, int Y){
			
			if( X > this.X_position && (X <= (this.X_position + this.X_size)) )
			   if( Y > this.Y_position && (Y <= (this.Y_position + this.Y_size)) )
					MysNadKomponentou = true;
				else
					MysNadKomponentou = false;
			else
				MysNadKomponentou = false;
		}
		
		// Prazdny konstruktor
		public Komponenta(){
			
			INIT = true;
			this.Stav = 0.0;
			this.MysNadKomponentou = false;
			this.ZadanaHodnota = 0.0;
			
		}
		
	}// END class Komponenta
	
	
	/* Komponenta klapka 
	 * Odvozena od tridy komponenta
	 */
	public class Klapka : Komponenta
	{
		// Promenne graficke visulaizace
		private Point[] P = new Point[6];		
		private Pen BlackPen2;
		private Rectangle RectangleText2;
		private Rectangle RectangleText1;
		private Rectangle RectangleKolecko;
		private StringFormat FormatRetezce;
		private Font pismo;
		
		
		// Funkce pro vykresleni na obrazovku
		public override void DrawToScreen(Graphics gfx){
			
			if(!this.INIT)
				throw new Exception("Pokus o vykresleni neinicializovaneho objektu");
			
			if(gfx == null)
				throw new ArgumentNullException(" GFX = NULL, nelze vykreslovat");
			
			// Zavolani bazove funkce
			base.DrawToScreen(gfx);
			
			// Vyber stetce podle stavu
			System.Drawing.Brush Barva = Brushes.Black;
				
			if( Stav == 0 ){
					Barva = Brushes.Gold;
					Text2 = "Zavírá se";
			}
			
			if( Stav == 1 ){
					Barva = Brushes.Gold;
					Text2 = "Otevírá se";
			}
			
			if( Stav == 2 ){
					Barva = Brushes.Red;
					Text2 = "Zavřeno";
			}
			
			if( Stav == 3 ){
					Barva = Brushes.Green;
					Text2 = "Otevřeno";
			}
		
			// Vyplneni oblasti
			gfx.FillPolygon(Barva, new Point[3]{P[0],P[1],P[4]});
			gfx.FillPolygon(Barva, new Point[3]{P[2],P[3],P[4]});
			
			// Vykresleni Okraju
			gfx.DrawLines(BlackPen2, P);
			gfx.DrawLine(BlackPen2, P[0], P[4]);
			gfx.DrawEllipse(BlackPen2, RectangleKolecko);
			
			// Vypsani textu			
			gfx.DrawString(Text2, pismo, Brushes.Black, RectangleText2, FormatRetezce);
			gfx.DrawString(Text1, pismo, Brushes.Black, RectangleText1, FormatRetezce);

		
		}
			
		// Prepis virtualni metody pro zmenu velikosti komponenty
		public override void  ReSizeComponet(double Pomer_X, double Pomer_Y)
		{		
				base. ReSizeComponet(Pomer_X, Pomer_Y);   // Volani metody bazove tridy (zmena X_size, Y_size, Y_position, X_position)
			
				// Prepocet bodu a ctvercu graficke vizulizace
				int Petina_Y = Y_size/5;		// Pomocna promenna

				P[0] = new Point(X_position, Y_position + 2*Petina_Y);
				P[1] = new Point(X_position, Y_position + 4*Petina_Y);
				P[2] = new Point(X_position + X_size, Y_position + 2*Petina_Y);
				P[3] = new Point(X_position + X_size, Y_position + 4*Petina_Y);
				P[4] = new Point(X_position + X_size/2, Y_position + 3*Petina_Y);
				P[5] = new Point(X_position + X_size/2, Y_position + 2*Petina_Y);
			
				// Definice dulezitych ctevercu pro vykresleni
				RectangleText2 = new Rectangle(X_position, Y_position, X_size, Petina_Y);
				RectangleText1 = new Rectangle(X_position, Y_position + 4*Petina_Y, X_size, Petina_Y);
				RectangleKolecko = new Rectangle(X_position + X_size/2 - Petina_Y/2, Y_position + Petina_Y, Petina_Y, Petina_Y);
				
				if(X_size/7 != 0)
					pismo =  new System.Drawing.Font("",X_size/7, System.Drawing.FontStyle.Regular);
		}
		
		// Abstaktni metody bazove tridy pro urceni pripojnych bodu;
		protected override Point ConnectionPoint1()
		{
				return new Point(X_position, Y_position + 3*Y_size/5);
		}
		
		protected override Point ConnectionPoint2()
		{
				return new Point(X_position + X_size, Y_position + 3*Y_size/5);
		}
		
		
		// Konstruktor
		public Klapka(){
					
			// Inicializace grafickych promennych
			pismo =  new System.Drawing.Font("",8, System.Drawing.FontStyle.Regular);
			FormatRetezce = new StringFormat();
			FormatRetezce.Alignment = StringAlignment.Center;
			FormatRetezce.LineAlignment = StringAlignment.Center;
			BlackPen2 = new Pen(Color.Black,2);
			
			// Pridani metod pro vykreslovani, zmenu velikosti atd do delegatu 
			DelgateMetod.InstanceDelegatDrawToScren += new DelgateMetod.DelegatDrawToScren(this.DrawToScreen);
			DelgateMetod.InstanceDelegatResize += new DelgateMetod.DelegatResize(this.ReSizeComponet);
			DelgateMetod.InstanceDelegatMove += new DelgateMetod.DelegatMove(this.JeMysNadKomponentou);
			DelgateMetod.InstanceDelegatClic += new DelgateMetod.DelegatClic(this.SpustPriKliknutiMysi);
		}
		
		
	}//END class Klapka

	
	/* Komponenta čepadlo
	 * Odvozena od tridy komponenta
	 */	
	public class Cerpadlo : Komponenta
	{

		// Promenne graficke visualizace
		protected Point[] P = new Point[4];
		protected Rectangle RectangleText2;
		protected Rectangle RectangleKolecko;
		protected Rectangle RectangleText1;
		protected Font pismo;
		protected StringFormat FormatRetezce;
		
		// Funkce pro vykresleni na obrazovku
		public override void DrawToScreen(Graphics gfx){
		
			if(gfx == null)
				throw new ArgumentNullException("Pokus o vykresleni do nulovho grafickeho zarizeni");
			
			if(!INIT)
				throw new Exception("Pokus o vykresleni neinicializovaneho objektu cerpadla");
			
			// Volani bazove funkce pro vykresleni obrysu je-li kurzor nad komponentou
			base.DrawToScreen(gfx);
			
			// Definice pera pro vykreslovani
			Pen BlackPen2 = new Pen(Color.Black,2);
						
			// Vyber stetce podle stavu
			Brush Barva = Brushes.Black;
			
			if(this.Stav < 0.05){
				Text2 = "Vypnuto";
		    	Barva = Brushes.Red;
			}
			
			if(this.Stav >= 0.05 && this.Stav <= 1.0){
				Text2 = Convert.ToString(Convert.ToInt32(this.Stav*100)) + " %";
		    	Barva = Brushes.Green;
			}
				
			// Vybarveni oblasti
			gfx.FillEllipse(Barva, RectangleKolecko);
			
			// Vykresleni obrysu
			gfx.FillPolygon(Brushes.Black, P);
			gfx.DrawEllipse(BlackPen2, RectangleKolecko);
			
			// Vypsani textu
			gfx.DrawString(Text2, pismo, Brushes.Black, RectangleText2, FormatRetezce);
			gfx.DrawString(Text1, pismo, Brushes.Black, RectangleText1, FormatRetezce);
			
			
		}
		
		// Prepsani bazove funkce pro zmenu velikosti komponenty
		public override void  ReSizeComponet(double Pomer_X, double Pomer_Y)
		{
			base. ReSizeComponet(Pomer_X,Pomer_Y); // Volani puvodni bazove tridy
			
			// Vypocet dulezitych bodu
			int Sedmina_Y = Y_size/7; 	// Pomocna promenna
			
			P[0] = new Point(X_position + X_size/2 - X_size/10, Y_position + 4*Sedmina_Y);
			P[1] = new Point(X_position, Y_position + 5*Sedmina_Y);
			P[2] = new Point(X_position + X_size, Y_position + 5*Sedmina_Y);
			P[3] = new Point(X_position + X_size/2 + X_size/10, Y_position + 4*Sedmina_Y);
			
			// Definice ctevecu
			RectangleText2 = new Rectangle(X_position, Y_position, X_size, Sedmina_Y);
			RectangleKolecko = new Rectangle(X_position, Y_position + Sedmina_Y, X_size, 3*Sedmina_Y);
			RectangleText1 = new Rectangle(X_position, Y_position + 5*Sedmina_Y, X_size, 2*Sedmina_Y);
			
			if(X_size != 0)
				pismo =  new System.Drawing.Font("",X_size/6, System.Drawing.FontStyle.Regular);
		}
		
		protected override Point ConnectionPoint1()
		{
			return new Point(X_position+X_size/2, Y_position + (5*Y_size)/14);
		}
		
		protected override Point ConnectionPoint2()
		{
				return new Point(X_position + X_size, Y_position + (5*Y_size)/14);
		}
		
		// Konstruktor s parametry
		public Cerpadlo()
		{	
			FormatRetezce = new StringFormat();
			FormatRetezce.LineAlignment = StringAlignment.Center;
			FormatRetezce.Alignment = StringAlignment.Center;
			pismo =  new System.Drawing.Font("",8, System.Drawing.FontStyle.Regular);
			
			// Pridani metod pro vykreslovani, zmenu velikosti atd do delegatu 
			DelgateMetod.InstanceDelegatDrawToScren += new DelgateMetod.DelegatDrawToScren(this.DrawToScreen);
			DelgateMetod.InstanceDelegatResize += new DelgateMetod.DelegatResize(this.ReSizeComponet);
			DelgateMetod.InstanceDelegatMove += new DelgateMetod.DelegatMove(this.JeMysNadKomponentou);
			DelgateMetod.InstanceDelegatClic += new DelgateMetod.DelegatClic(this.SpustPriKliknutiMysi);
		}
		
	} // End class Cerpadlo
	
	/* Komponenta snimac
	 * Odvozena od tridy komponenta
	 * slozi pro zobrazovani měřene veliciny snimace
	 */	
	public class Snimac : Komponenta
	{
		// Graficke promenne
		public string Jednotka;
		private Rectangle RectangleText1;
		private Rectangle RectangleText2;
		private Point[] P = new Point[2];
		private Pen BlackPen1;
		private Pen BlackPen3;
		private Font pismo;
		private StringFormat FormatRetezce;
			
		
		// Funkce pro vykresleni na obrazovku
		public override void DrawToScreen(Graphics gfx)
		{
		
			if(gfx == null)
				throw new ArgumentNullException("Pokus o vykresleni do nulovho grafickeho zarizeni");
			
			if(!INIT)
				throw new Exception("Pokus o vykresleni neinicializovaneho objektu cerpadla");
						  		
			// Vyplneni oblasti
			gfx.FillRectangle(Brushes.AliceBlue, new Rectangle(X_position, Y_position,X_size, Y_size));
			
			// Vykresleni okraju
			gfx.DrawRectangle(BlackPen3, new Rectangle(X_position, Y_position,X_size, Y_size));
			gfx.DrawLine(BlackPen1, P[0], P[1]);
			
			// Vyvoreni retezece Text 2 {HODNOTA + JEDNOTKA}
			
			StringBuilder Retezec;
			if(this.Stav > 0.01)
				Retezec = new StringBuilder(Convert.ToString(this.Stav));
			else
			 	Retezec = new StringBuilder("0.0");
			 	
			if(Retezec.Length > 5)
				Retezec.Length = 5;
			Retezec.Append(" ");
			Retezec.Append(Jednotka);
			Text2 = Retezec.ToString();
			
			gfx.DrawString(Text1, pismo, Brushes.Black, RectangleText1, FormatRetezce);
			gfx.DrawString(Text2, pismo, Brushes.Black, RectangleText2, FormatRetezce);
		}
		
		// Prepsani bazove funkce pro zmenu velikosti
		public override void  ReSizeComponet(double Pomer_X, double Pomer_Y)
		{
			base. ReSizeComponet(Pomer_X, Pomer_Y); // Volani puvodni bazove funkce;
			
			// Definice dulezitych ctvercu
			int Pul_Y = Y_size/2;
			
			RectangleText1 = new Rectangle(X_position, Y_position, X_size,Pul_Y);
			RectangleText2 = new Rectangle(X_position, Y_position + Pul_Y, X_size,Pul_Y);
			
			// Definice dulezitych bodu
			P[0] = new Point(X_position, Y_position + Pul_Y);
			P[1] = new Point(X_position + X_size, Y_position + Pul_Y);
			if(X_size/7 != 0)
				pismo =  new System.Drawing.Font("",(X_size)/7, System.Drawing.FontStyle.Regular);
			
		}
		
		protected override Point ConnectionPoint1()
		{
			return new Point(X_position, Y_position + Y_size/2);
		}
		
		protected override Point ConnectionPoint2()
		{
			return new Point(X_position + X_size/2, Y_position + Y_size);
		}
		
		// Vlastnos definující třetí připojný bod
		public Point GetConnectionPoint3{
			get{
				return new Point(X_position + X_size, Y_position + Y_size/2);
			}
		}
			// Konstruktor s parametry
		public Snimac()
		{

			// Pera 
			BlackPen1 = new Pen(Color.Black,1);
			BlackPen3 = new Pen(Color.Black,3);
		
			pismo =  new System.Drawing.Font("",7, System.Drawing.FontStyle.Regular);
			FormatRetezce = new StringFormat();
			FormatRetezce.LineAlignment = StringAlignment.Center;
			FormatRetezce.Alignment = StringAlignment.Center;
			
			// Pridani metod pro vykreslovani, zmenu velikosti atd do delegatu 
			DelgateMetod.InstanceDelegatDrawToScren += new DelgateMetod.DelegatDrawToScren(this.DrawToScreen);
			DelgateMetod.InstanceDelegatResize += new DelgateMetod.DelegatResize(this.ReSizeComponet);
		}
		
	}
	
	/* Komponenta tank
	 * Odvozena od tridy Komponenta
	 */
	public class Tank : Komponenta
	{
		
		// Promenne grafickeho prostredi
		public string Text3;
		public Brush BarvaTekutiny;
		private Pen BlackPen2;
		private Point[] P = new Point[10];
		private Rectangle VnejsiRectangle;
		private Rectangle VnitrniRectangle;
		private Rectangle RectangleNozicka1;
		private Rectangle RectangleNozicka2;
		private Rectangle RectangleText2;
		private Rectangle RectangleText1;
		private Rectangle RectangleText3;
		private Font pismo;
		private StringFormat FormatRetezce;
			
		
		//Funkce pro vykresleni na obrazovku
		public override void DrawToScreen(Graphics gfx)
		{
		
			if(!this.INIT)
				throw new Exception("Pokus o vykresleni neinicializovaneho objektu");
			
			if(gfx == null)
				throw new ArgumentNullException(" GFX = NULL, nelze vykreslovat");
			
			// Pomocne promenne
			int Y_desetina = Y_size/10;							
			int X_tricetina = Convert.ToInt32(X_size/30.0);
		
			// Definice čtverce hladiny
			int MaxHladina = 7*Y_desetina ;
			int Sirka_hladiny = X_size - 2*X_tricetina ;
			int offset = MaxHladina - Convert.ToInt32(this.Stav*MaxHladina);
			
			Rectangle Rectanglehladina = new Rectangle(X_position + X_tricetina, Y_position + Y_desetina + offset, Sirka_hladiny, MaxHladina-offset);
			
			// Vyplnění barvy hladiny
			gfx.FillRectangle(BarvaTekutiny, Rectanglehladina);
			gfx.FillPolygon(BarvaTekutiny, new Point[]{P[3],P[6],P[7]});
			
			// Vykreslení obrysů tanku 
			gfx.DrawRectangle(BlackPen2, VnejsiRectangle);
			gfx.DrawRectangle(BlackPen2, VnitrniRectangle);
			gfx.DrawRectangle(BlackPen2, RectangleNozicka1);
			gfx.DrawRectangle(BlackPen2, RectangleNozicka2);
			
			gfx.DrawLines(BlackPen2, new Point[]{P[0],P[1],P[2]});
			gfx.DrawLines(BlackPen2, new Point[]{P[3],P[4],P[5],P[6],P[7],P[8],P[9]});
			gfx.DrawLine(BlackPen2, P[3], P[5]);
			
			// Vypsani textu			
			gfx.DrawString(Text1, pismo, Brushes.Black, RectangleText1, FormatRetezce);
			gfx.DrawString(Text2, pismo, Brushes.Black, RectangleText2, FormatRetezce);
			gfx.DrawString(Text3, pismo, Brushes.Black, RectangleText3, FormatRetezce);
			
		}
		
		// Prepsani bazove metody pro zmenu velikosti
		public override void  ReSizeComponet(double Pomer_X, double Pomer_Y)
		{
			base. ReSizeComponet(Pomer_X, Pomer_Y); // Volani puvodni bazove metody
			
			// Definice dulezitych bodu
			int Y_desetina = Y_size/10;							// Pomocne promenne
			int X_tricetina = Convert.ToInt32(X_size/30.0);
		
			P[0] = new Point(X_position, Y_position + Y_desetina);
			P[1] = new Point(X_position + X_size/2, Y_position);
			P[2] = new Point(X_position + X_size, Y_position + Y_desetina);
			P[3] = new Point(X_position + X_tricetina , Y_position + 8*Y_desetina);
			P[4] = new Point(X_position + X_tricetina ,  Y_position + Y_size - X_tricetina - 2);
			P[5] = new Point(X_position + Y_desetina , Y_position + 8*Y_desetina + Y_desetina/4);
			P[6] = new Point(X_position + X_size/2 , Y_position + 9*Y_desetina);
			P[7] = new Point(X_position + X_size - X_tricetina, Y_position + 8*Y_desetina);
			P[8] = new Point(X_position + X_size - X_tricetina, Y_position + Y_size - X_tricetina - 2);
			P[9] = new Point(X_position + X_size - Y_desetina , Y_position + 8*Y_desetina + Y_desetina/4);
			
			// Definice dulezitych ctevercu
			VnejsiRectangle = new Rectangle(P[0], new Size(X_size, 7*Y_desetina));
			VnitrniRectangle = new Rectangle(X_position + X_tricetina, Y_position + Y_desetina, X_size - 2*X_tricetina, 7*Y_desetina);
			RectangleNozicka1 = new Rectangle(X_position , Y_position + Y_size - X_tricetina, 2*X_tricetina, X_tricetina);
			RectangleNozicka2 = new Rectangle(X_position + X_size -  2*X_tricetina, Y_position + Y_size - X_tricetina, 2*X_tricetina, X_tricetina);
			RectangleText2 = new Rectangle(X_position + X_tricetina, Y_position + 2*Y_desetina, X_size - 2*X_tricetina, Y_desetina);
			RectangleText1 = new Rectangle(X_position + X_tricetina, Y_position + 3*Y_desetina, X_size - 2*X_tricetina, Y_desetina);
			RectangleText3 = new Rectangle(X_position + X_tricetina, Y_position + 5*Y_desetina, X_size - 2*X_tricetina, Y_desetina);
			
			if(X_size != 0)
				pismo =  new System.Drawing.Font("",X_size/10, System.Drawing.FontStyle.Regular);
		}
		
		protected override Point ConnectionPoint1()
		{
			return P[1];
		}
		
		protected override Point ConnectionPoint2()
		{
			return P[6];
		}
		
		
		// Vlastnost definující třetí přípojný bod (Snímač)
		public Point GetConnectionPoint3{
			get{
				return new Point(X_position + X_size, Y_position + Y_size/2);
			}
		}
	
		// Kostruktor s parametry
		public Tank()
		{		
		    // Inicializace prvku graficke vizualizace
			BlackPen2 = new Pen(Color.Black,2);
			pismo =  new System.Drawing.Font("",7, System.Drawing.FontStyle.Regular);
			FormatRetezce = new StringFormat();
			FormatRetezce.LineAlignment = StringAlignment.Center;
			FormatRetezce.Alignment = StringAlignment.Center;
			
			// Pridani metod pro vykreslovani, zmenu velikosti atd do delegatu 
			DelgateMetod.InstanceDelegatDrawToScren += new DelgateMetod.DelegatDrawToScren(this.DrawToScreen);
			DelgateMetod.InstanceDelegatResize += new DelgateMetod.DelegatResize(this.ReSizeComponet);	    
		}
		
	}// End class Tank
	
	/*
	 * Komponenta stridaci ventil
	 * Odvozena od tridy Komponenta
	 */	 
	public class StridaciVentil : Komponenta
	{
		// Promenne grafickehe vizualizace
		private Rectangle RectangleText1;
		private Point P;
		private Rectangle[] CtverceVentilu = new Rectangle[3];
		private StringFormat FormatRetezce;
		private Font pismo;
		private Pen BlackPen2;
		
		// Funkce pro vykresleni na obrazovku
		public override void DrawToScreen(Graphics gfx)
		{
			if(!this.INIT)
				throw new Exception("Pokus o vykresleni neinicializovaneho objektu");
			
			if(gfx == null)
				throw new ArgumentNullException(" GFX = NULL, nelze vykreslovat");
				
			// Volani bazove funkce pro vykresleni obrysu je-li kurzor nad komponentou
			base.DrawToScreen(gfx);
			
			// Vyplneni oblasti
			if(this.Stav >= 0.95){
				gfx.FillRectangle(Brushes.Gray, this.CtverceVentilu[1]);
				gfx.FillRectangle(Brushes.Gray, this.CtverceVentilu[0]);
			}
			
			if(this.Stav <= 0.05){
				gfx.FillRectangle(Brushes.Gray, this.CtverceVentilu[1]);
				gfx.FillRectangle(Brushes.Gray, this.CtverceVentilu[2]);
			}
			
			// Vykresleni obrysu
			gfx.DrawRectangles(BlackPen2, CtverceVentilu);
			
			// Vypsani textu
			gfx.DrawString(Text1, pismo, Brushes.Black, RectangleText1, FormatRetezce);
		
		}
		
		// Prepis bazove metody pro zmenu velikosti
		public override void ReSizeComponet(double Pomer_X, double Pomer_Y)
		{
			base.ReSizeComponet(Pomer_X, Pomer_Y); // Volani puvodni bazove metody
			
			// Pomocna promenna
			int Tretina_X = X_size/3;
			int Polovina_Y = Y_size/2;
			
			RectangleText1 = new Rectangle(X_position, Y_position, X_size, Polovina_Y);
			P = new Point(X_position, Y_position + Polovina_Y);
			
			CtverceVentilu[0] = new Rectangle(X_position, Y_position + Polovina_Y,  Tretina_X, Polovina_Y);
			CtverceVentilu[1] = new Rectangle(X_position + Tretina_X, Y_position + Polovina_Y,  Tretina_X, Polovina_Y);
			CtverceVentilu[2] = new Rectangle(X_position + 2*Tretina_X, Y_position + Polovina_Y,  Tretina_X, Polovina_Y);
			  
			if(X_size/8 != 0)
				pismo =  new System.Drawing.Font("",X_size/8, System.Drawing.FontStyle.Regular);
		}
			
		// Definovani abstaktnich bazovych metod pro urceni pripojovacich bodu
		protected override Point ConnectionPoint1()
		{
			return new Point(X_position, Y_position + Y_size - Y_size/4);
		}
		
		protected override Point ConnectionPoint2()
		{
			return new Point(X_position + X_size, Y_position + Y_size - Y_size/4);
		}
		
		// Vlatnost pro treti pripojny bod
		public Point GetConnectionPoint3 {
			get {
				return new Point(X_position + X_size/2, Y_position + Y_size);
			}
		}
		
		// Konstruktor s parametry
		public StridaciVentil()
		{

			FormatRetezce = new StringFormat();
			FormatRetezce.LineAlignment = StringAlignment.Center;
			FormatRetezce.Alignment = StringAlignment.Center;
			pismo =  new System.Drawing.Font("",8, System.Drawing.FontStyle.Regular);
			BlackPen2 = new Pen(Color.Black,2);		
			
			// Pridani metod pro vykreslovani, zmenu velikosti atd do delegatu 
			DelgateMetod.InstanceDelegatDrawToScren += new DelgateMetod.DelegatDrawToScren(this.DrawToScreen);
			DelgateMetod.InstanceDelegatResize += new DelgateMetod.DelegatResize(this.ReSizeComponet);
			DelgateMetod.InstanceDelegatMove += new DelgateMetod.DelegatMove(this.JeMysNadKomponentou);
			DelgateMetod.InstanceDelegatClic += new DelgateMetod.DelegatClic(this.SpustPriKliknutiMysi);
		}
	}
	
	/*
	 * Komponenta výměník
	 * Odvozena od tridy Komponenta
	 */
	public class Vymenik : Komponenta
	{
		// Promenne grafickeho prostredi
		private Point[] P = new Point[6];
		private Rectangle RectangleText1;
		private Rectangle RectangleText2;
		private Rectangle RectangleSterd;
		private StringFormat FormatRetezce;
		private Font pismo;
		private Pen BlackPen2;
		
		// Funkce pro vykresleni na obrazovku
		public override void DrawToScreen(Graphics gfx)
		{
			
			if(!this.INIT)
				throw new Exception("Pokus o vykresleni neinicializovaneho objektu");
			
			if(gfx == null)
				throw new ArgumentNullException(" GFX = NULL, nelze vykreslovat");
			
			// Volani bazove funkce pro vykresleni obrysu je-li kurzor nad komponentou
			base.DrawToScreen(gfx);
			
			// Vyplneni stredove oblasti 		
			if(this.Stav < 0.05)
				gfx.FillRectangle(Brushes.Blue, RectangleSterd);
			else
				gfx.FillRectangle(Brushes.Tomato, RectangleSterd);
			
			// Vykresleni obrysu 
			gfx.DrawRectangle(BlackPen2, RectangleSterd);
			gfx.DrawLine(BlackPen2, P[0], P[1]);
			
			// Vypsani textu
			Text2 = "Výkon: " + Convert.ToString(Convert.ToInt32(100*this.Stav)) + " %";
			gfx.DrawString(Text2, pismo, Brushes.Black, RectangleText2, FormatRetezce);
			gfx.DrawString(Text1, pismo, Brushes.Black, RectangleText1, FormatRetezce);	
		}
		
		// Uprava bazove funkce pro zmenu velkosti prvku
		public override void ReSizeComponet(double Pomer_X, double Pomer_Y)
		{
			base.ReSizeComponet(Pomer_X, Pomer_Y); // Volani bazove funkce
			
			// Pomocne promenne
			int Tretina_Y = Y_size / 3;
			int Ctvrtina_Y = Y_size / 4;
			
			P[0] = new Point(X_position, Y_position + Ctvrtina_Y);
			P[1] = new Point(X_position + X_size, Y_position + 3*Ctvrtina_Y);
			P[2] = new Point(X_position, Y_position + Tretina_Y);
			P[3] = new Point(X_position, Y_position + 2*Tretina_Y); 
		    P[4] = new Point(X_position + X_size, Y_position + Tretina_Y);
			P[5] = new Point(X_position + X_size, Y_position + 2*Tretina_Y);    
			
			RectangleText1 = new Rectangle(X_position, Y_position + 3*Ctvrtina_Y, X_size, Ctvrtina_Y);
			RectangleText2 = new Rectangle(X_position, Y_position, X_size, Ctvrtina_Y);
			RectangleSterd = new Rectangle(P[0], new Size(X_size, 2*Ctvrtina_Y));
			 
			if(X_size != 0)
				pismo =  new System.Drawing.Font("",X_size/9, System.Drawing.FontStyle.Regular);                               
		}
		
		// Funkce navracejici pripojne body
		protected override Point ConnectionPoint1()
		{
			return P[2];
		}
		
		protected override Point ConnectionPoint2()
		{
			return P[3];
		}
		
		// Vlastnosti vracejici zbyvajici pripojovaci body
		public Point GetConnectionPoint3{
			get{
				return P[4];
			}
		}
		
		public Point GetConnectionPoint4{
			get{
				return P[5];
			}
		}
		
		// Konstruktor s parametry
		public Vymenik(){

			//Inicializace prvku graficke vizualizace
			FormatRetezce = new StringFormat();
			FormatRetezce.LineAlignment = StringAlignment.Center;
			FormatRetezce.Alignment = StringAlignment.Center;
			pismo =  new System.Drawing.Font("",8, System.Drawing.FontStyle.Regular);
			BlackPen2 = new Pen(Color.Black,2);
			
			// Pridani metod pro vykreslovani, zmenu velikosti atd do delegatu 
			DelgateMetod.InstanceDelegatDrawToScren += new DelgateMetod.DelegatDrawToScren(this.DrawToScreen);
			DelgateMetod.InstanceDelegatResize += new DelgateMetod.DelegatResize(this.ReSizeComponet);
			DelgateMetod.InstanceDelegatMove += new DelgateMetod.DelegatMove(this.JeMysNadKomponentou);
			DelgateMetod.InstanceDelegatClic += new DelgateMetod.DelegatClic(this.SpustPriKliknutiMysi);
		}
	}
	
	/* 
	 * Komponenta NadrzKoncentratu
	 * Odvozena od tridy komponenty
	 */	 
	public class NadrzKoncentratu : Komponenta
	{
		
		// Promenne grafickeho prostredi
		private Point[] P;
		private Rectangle RectangleMotor;
		private Rectangle RectangleObrys;
		private Rectangle Rectanglehladina;
		private StringFormat FormatRetezce;
		private Font pismo;
		private Pen BlackPen2;
		
		public bool CerpadloKoncentratu;
		
		// Metoda pro zmenu velikosti komponenty
		public override void ReSizeComponet(double Pomer_X, double Pomer_Y)
		{
			base.ReSizeComponet(Pomer_X, Pomer_Y);
			
			// Pomocne promenne
			int Y_petina = Y_size / 5;
			int X_pul = X_size / 2;
			

			P[0] = new Point(X_position , Y_position + Y_petina);
			P[1] = new Point(X_position , Y_position + 2*Y_petina);
			P[2] = new Point(X_position + X_size , Y_position + 2*Y_petina);
			P[3] = new Point(X_position + X_pul , Y_position + Y_petina);
			
			RectangleMotor = new Rectangle(X_position, Y_position, X_pul, Y_petina);
			RectangleObrys = new Rectangle(X_position ,Y_position + 2*Y_petina, X_size, 3*Y_petina);
			
			if(X_size != 0)
				pismo =  new System.Drawing.Font("",X_size/7, System.Drawing.FontStyle.Regular);
			
		}
		
		// Metoda pro vykresleni na obrazovku
		public override void DrawToScreen(Graphics gfx)
		{
			if(!this.INIT)
				throw new Exception("Pokus o vykresleni neinicializovaneho objektu");
			
			if(gfx == null)
				throw new ArgumentNullException(" GFX = NULL, nelze vykreslovat");
			
			// Volani bazove funkce pro vykresleni obrysu je-li kurzor nad komponentou
			base.DrawToScreen(gfx);
			
			// Vypocet Ctverce hladiny
			int MaxHladina =3*Y_size/5 ;
			int offset = MaxHladina - Convert.ToInt32(this.Stav*MaxHladina);
			
			Rectanglehladina = new Rectangle(X_position, Y_position + 2*Y_size/5 + offset, X_size, MaxHladina-offset);
			
			// Vyplneni oblasti
			gfx.FillRectangle(Brushes.LawnGreen, Rectanglehladina);
			
			
			if (CerpadloKoncentratu)
				gfx.FillRectangle(Brushes.Green, RectangleMotor);
			else
				gfx.FillRectangle(Brushes.Red, RectangleMotor);
			
			// Vykresleni obrysu
			gfx.DrawRectangle(BlackPen2, RectangleMotor);
			gfx.DrawRectangle(BlackPen2, RectangleObrys);
			
			gfx.DrawLine(BlackPen2, P[0], P[1]);
			gfx.DrawLine(BlackPen2, P[2], P[3]);
			
			// Vypsání textu
			gfx.DrawString(Text1, pismo, Brushes.Black, RectangleObrys, FormatRetezce);	
			
		}
		
		// metody Vracejejicic pripojne body
		protected override Point ConnectionPoint1()
		{
			return new Point(X_position + X_size/4, Y_position);
		}
		protected override Point ConnectionPoint2()
		{
			return ConnectionPoint1();
		}
		
		// Konstrutor
		public NadrzKoncentratu(){
			

			
			// Inicializace grafikcých proměnných
			P = new Point[4];
			FormatRetezce = new StringFormat();
			FormatRetezce.LineAlignment = StringAlignment.Center;
			FormatRetezce.Alignment = StringAlignment.Center;
			pismo =  new System.Drawing.Font("",8, System.Drawing.FontStyle.Regular);
			BlackPen2 = new Pen(Color.Black,2);
			
			// Pridani metod pro vykreslovani, zmenu velikosti atd do delegatu 
			DelgateMetod.InstanceDelegatDrawToScren += new DelgateMetod.DelegatDrawToScren(this.DrawToScreen);
			DelgateMetod.InstanceDelegatResize += new DelgateMetod.DelegatResize(this.ReSizeComponet);
			DelgateMetod.InstanceDelegatMove += new DelgateMetod.DelegatMove(this.JeMysNadKomponentou);
			DelgateMetod.InstanceDelegatClic += new DelgateMetod.DelegatClic(this.SpustPriKliknutiMysi);
		}
	}

	// Trida obsahujici staticke delegaty pouzivane pro volani v evetnech hlavniho formulare
	public class DelgateMetod{
		
		// Definice delegatu volanych pri udalosti formulare
		public delegate void DelegatDrawToScren(Graphics gfx);
		public delegate void DelegatResize(double PomerX, double PomerY);
		public delegate void DelegatMove(int X, int Y);
		public delegate void DelegatClic();
		
		// Vytvoreni statickych instanci delegatu
		public static DelegatDrawToScren InstanceDelegatDrawToScren;
		public static DelegatResize InstanceDelegatResize;
		public static DelegatMove InstanceDelegatMove;
		public static DelegatClic InstanceDelegatClic;	
	}

	
/************************************************************************************************************************
 *  							Třidy definující jednotlivé numerické modely komponent									*
 ***********************************************************************************************************************/

	// Abstraktni trida, definujici zakladni model soustavy prvního řádu.
	// Od této třídy jsou odvozeny ostatní třídy s numerickýmy komponentami jednotlivých komponent
	public class NumerickeModelyBaze { 
		
		// Systémové proměnné
		protected double VstupniPromenna;
		protected double VystupniPromenna;
		protected double CasovaKonstatna;   // [s]
		protected double PeriodaVzorkovani; // [s]
		protected double Storage;
	
		// Vlastnos Periody vzorkovani
		public double SampleTime{
			get{
				return this.PeriodaVzorkovani;
			}
			set{
				if (value <= 0.0)
					throw new ArgumentOutOfRangeException("Pokus o zadani Periody vzorkovani mensi jak nula");
				
				this.PeriodaVzorkovani = value;
			}
		}
		
		// Vlastnost Casova konstanta
		public double Casova_konstanta{
			get{
				return this.CasovaKonstatna;
			}
			set{
				
				if(value <= 0.0)
					throw new ArgumentOutOfRangeException("Pokus o zadani casove konstany mensi jak nula");
				
				this.CasovaKonstatna = value;
			}
		}
		
	   // Definice vlastnosti stav
		public double Stav{
			get{
				return this.VystupniPromenna;
			}
		}
		
	    // Funkce definujici nelinearitu daneoho systemu
	    // Funkce je vitualni. Definuje linearitu typu nasyceni <-1,1>
		protected double Nelinearita(double vstup)
		{
			if( (vstup <= 1.0) && (vstup >= -1.0))
				return vstup;
			
			else{
				
				if( vstup < -1.0)
					return -1.0;
				
				if( vstup > 1.0)
					return 1.0;		
				}
			
			return 0.0;
		}
		
		// Funkce definující jeden krok simulace
		public virtual void SimStep(){
			
			// Vypocet pomocne promene
			double A = System.Math.Exp(- this.PeriodaVzorkovani/this.CasovaKonstatna);
			
			this.Storage = this.VstupniPromenna * (1 - A) + this.VystupniPromenna*A;
			this.Storage = this.Nelinearita(this.Storage);
			this.VystupniPromenna = this.Storage;			
		}
		public virtual void SimStep(double Vstup){
			
			this.VystupniPromenna = Vstup;
			this.SimStep();
			
		}
		public virtual void SimStep(double VzorkovaciPerioda, double Vstup){
			
			if (VzorkovaciPerioda <= 0.0)
				throw new ArgumentNullException("Pokus o zadani Periody vzorkovani mensi jak nula");
			
			this.PeriodaVzorkovani = VzorkovaciPerioda;
			this.VstupniPromenna = Vstup;
			
			this.SimStep();
		}
		
		
		// Prázdný konstruktor
		public NumerickeModelyBaze(){
			
			VstupniPromenna = 0.0;
			VystupniPromenna = 0.0;
			CasovaKonstatna = 1.2;
			PeriodaVzorkovani = 0.0;
			Storage = 0.0;
		}
	}

	
	// Trida definujici numericky model ventilu
	public class KlapkaNumModel : NumerickeModelyBaze{
		
		public bool StavPoResetu;
		
		// Definice vlastnosti pro stav grafickeho prostredi
		public double StavProVizualizaci
		{
			get{
			
				if (this.VystupniPromenna < 0.05)
					return 2.0;
				
				if (this.VystupniPromenna > 0.95)
					return 3.0;
				
				if(this.VstupniPromenna < this.VystupniPromenna)
					return 0.0;
				
				if(this.VstupniPromenna > this.VystupniPromenna)
					return 1.0;
				
				return 4.0;
			}
		}
		
		// Definice cidel polohy jako vlastnosti dane tridy
		public bool CidloPolohy_close{
			get{
				if(this.VystupniPromenna < 0.05)
					return true;
				else
					return false;
			}
		}
		public bool CidloPolohy_open{
			get{
				if(this.VystupniPromenna > 0.95)
					return true;
				else
					return false;
			}
		}
		
		// Vlastnos definujici zadanou hodnotu
		public double ZadanaHodnota{
			
			set{
				if(value > 0.5)
					this.OtevritVentil();
				else
					this.ZavritVentil();
			}
			get{
				return this.VstupniPromenna;
			}
		}
	    
		// Definici funkci ovladajici ventil
	    public void OtevritVentil(){
	    	this.VstupniPromenna = 1.0;
	    }
	    public void ZavritVentil(){
	    	this.VstupniPromenna = 0.0;
	    }
	
		// Funkce resetu daneho modelu
		public void Reset(){
			if(this.StavPoResetu){
				this.VystupniPromenna = 1.0;
				this.VstupniPromenna = 1.0;
				this.Storage = 1.0;
			}
			else {
				this.VystupniPromenna = 0.0;
				this.VstupniPromenna = 0.0;
				this.Storage = 0.0;
			}
		}
	}

	
    // Trida definujici numericky model pro motor, ventil, snimac
    public class MvsNumModel : NumerickeModelyBaze
    {
        
    	private double MaximalniHodnota;
    	private double MinimalniHodnota;
    	private double ResetStav;
    	
    	// Vlasnost vracejici Int16 decentralizovanou hodnotu aktuální veličiny 
    	// a setující zádanou hodnotu po centralizaci vstuní veličiny
    	public Int16 DestandartizovanaHodnotaWort{
    		get{
    			// Provedení destandartizace výstupní hodnoty (uvažován analogový modul s proudovou smyčkou 4 - 24 mA)
    			return System.Convert.ToInt16(this.VystupniPromenna*27648.0);
    		}
    		set{
    			
    			this.ZadanaHodnotaVjednotkach = (Convert.ToDouble(value) / 27648.0)*(this.MaximalniHodnota - this.MinimalniHodnota) + this.MinimalniHodnota;
    		}
    	} 
    	
    	
    	// Vlastnos pro zadavani zadane hodnoty
    	public double ZadanaHodnotaVprocentechRozsahu{
    		get{
    			return this.VstupniPromenna;
    		}
    		set{
    			if( value < 0.0 && value > 1.0 )
    				throw new ArgumentOutOfRangeException("Pokus o zadani zadane hodnoty mimo rozsah <0,1>");
    			
    			this.VstupniPromenna = value;
    		}
    	}
    	
    	// Vlastnost vracejici stav * MaximaliHodnota
    	public double StavVjednotkach{
    		get{
    			return (this.VystupniPromenna*(this.MaximalniHodnota - this.MinimalniHodnota) + this.MinimalniHodnota);
    		}
    	}
    	
    	// Vlastnost zadavajici zadanou hodnotu zobrazovanou na cidelch
    	public double ZadanaHodnotaVjednotkach{
    		set{
    			if(value <= this.MaximalniHodnota && value >= this.MinimalniHodnota )
    				this.VstupniPromenna = value/(this.MaximalniHodnota - this.MinimalniHodnota);
    			else
    				throw new ArgumentOutOfRangeException("Pokus o zadani zadane hodnoty mimo rozsah prvku hodnota prvku");
    		}
    	}
    	
    	// Vlastnos MaxHodnota
    	public double MaxHodnota{
    		get{
    			return this.MaximalniHodnota;
    		}
    		set{
    			if(value < this.MinimalniHodnota)
    				throw new ArgumentOutOfRangeException("Maximální hodnota rozsahu nemůže být větší jak minimální");
    			this.MaximalniHodnota = value;
    		}
    	}
    	
		// Vlastnos MaxHodnota
    	public double MinHodnota{
    		get{
    			return this.MinimalniHodnota;
    		}
    		set{
				if(value > this.MaximalniHodnota)
    				throw new ArgumentOutOfRangeException(" Minimální hodnota rozsahu nemůže být větší jak maximální");
    			this.MinimalniHodnota = value;
    		}
    	}
    	
    	// Vlastnos Cidlo Zapnuto
    	public bool CidloZapnuto{
    		get{
    			if(this.VystupniPromenna > 0.05)
    				return true;
    			else
    				return false;
    		}
    	}
    	
		// Vlastnost U cerpadel vracejici stav tepelne pojistky
		public bool TepelnaPojistka{
			get{ return false; }
		}
    	
		// Funkce resetu modelu
		public void Reset(){
			this.VstupniPromenna = this.ResetStav;
			this.VystupniPromenna = this.ResetStav;
			this.Storage = this.ResetStav;
			
		}
    
		// Definice prazdneho konstruktoru
    	public MvsNumModel(){
    		this.MaxHodnota = 0.0;
    		this.MinimalniHodnota = 0.0;
    		this.ResetStav = 0.0;
    	}
    }
	
    
    // Trida definujici numericky model tanku s roztoky a koncentraty
    public class TankMumModel{
    	
    	// Definice promennych modelu taku
    	private double MaxObjem;				// Tato promenna definuje maximalni mozny objem tanku;
    	private double Objem;					// Obsahuje aktualni hodnotu objemu tanku;
    	private double Pritok;					// Udava hodntou pritoku do tanku Litry/sekundu
    	private double Odtok; 					// Udava hodnotu odtoku z tanku Litry/sekundu
    	private double PrumerTanku;				// Udava prumer tanku metry
    	
    	private double PeriodaVzorkovani;		
    	private double TeplotaRoztoku;			// Udava teplotu roztoku v tanku, je-li tank prazdny = nule
    	private double KoncentraceRoztoku;			// Udava koncetraci kyseliny/louhu v roztoku tanku
    	
    	private double ResetKoncentrace;
    	private double ResseObjem;
    	
    	public bool CerpadloKoncentratu;		// Tato proměnná je používána puze u zásobníku koncetrátu, signalizuje stav dávkovacího čerpadla
    	public bool ResetCerpadlaKoncentratu;
    	private double PrutokCerpadlaKoncentratu;
    	
    	private double Povrch;					// Hodnota plochy tanku, používá se pro výpočet ztrátového tepla;
    	private double TloustkaSteny; 			// Udává tlouštku stěny tanku, používá se pro výpocet ztrátového tepla;
    	private double TeplotaOkoli;			// Teplota okolí je pouzita pro výpočet ztrátového tepla
    	private double SoucTepelVodivosti;		// Tepelna vodivost steny tanku Nerez ocel ( k =14)
    	
    	private double MtkH2O;					//  Merna tepelna kapacita vody
    	
    	
    	// Vlastnos Teplota
    	public double Teplota{
    		get{
    				return this.TeplotaRoztoku;
    		}
    	}
    	
    	// Vlastnost Povrch tanku
    	public double PovrchTanku{
    		set{
    			if(value > 0.0)
    				this.Povrch = value;
    			else 
    				throw new ArgumentOutOfRangeException();    			
    		}
    		
    		get{ return this.Povrch; }
    	}
    	
    	// Vlastnost tepelna vodivost steny
    	public double TepelnaVodivostSteny{
    		set{
    			if(value > 0.0)
    				this.SoucTepelVodivosti = value;
    			else 
    				throw new ArgumentOutOfRangeException();    			
    		}
    		
    		get{ return this.SoucTepelVodivosti; }
    	}
    	
    	// Vlastnost udavajici prumer tanku
    	public double Prumer{
    		set{
    			if(value > 0.0)
    				this.PrumerTanku = value;
    			else 
    				throw new ArgumentOutOfRangeException();    			
    		}
    		
    		get{ return this.PrumerTanku; }
    	}
    	
    	// Vlastnost Měrná tepelná kapacita 
    	public double MernaTepelnaKapacita{
    		set{
    			if(value > 0.0)
    				this.MtkH2O = value;
    			else 
    				throw new ArgumentOutOfRangeException();
    		}
    	}
    	
    	// Vlastnost tloušťky stěny tanku
    	public double TloustkaStenyTanku{
    		set {
    			if(value > 0.0)
    				this.TloustkaSteny = value;
    			else 
    				throw new ArgumentOutOfRangeException();
    		}
    		get{ return this.TloustkaSteny;}
    	}
    	
    	// Vlastnost Koncentrace
    	public double Koncetntace{
    		get{
    			return this.KoncentraceRoztoku;
    		}
    		set{
    			if(value < 0.0 || value > 1)
    				throw new ArgumentOutOfRangeException();
    			else 
    				this.KoncentraceRoztoku = value;
    					
    		}
    	}
    	
    	// Vlastnost MaximalniObjem
    	public double MaximalniObjem{
    		get{
    			return this.MaxObjem;
    		}
    		set{
    			if(value <= 0.0)
    				throw new ArgumentOutOfRangeException("Pokus o zadani zaporneho nebo nuloveho objemu tanku");
    			else
    				this.MaxObjem = value;
    		}
    	}
    	
    	// Vlastnos teploty okoli
    	public double TeplotaOkoliTanku{
    		set{ this.TeplotaOkoli = value;}
    		get{ return this.TeplotaOkoli;}
    	}
    	
    	// Vlastnos Periody vzorkovani
		public double SampleTime{
			get{
				return this.PeriodaVzorkovani;
			}
			set{
				if (value <= 0.0)
					throw new ArgumentOutOfRangeException("Pokus o zadani Periody vzorkovani mensi jak nula");
				
				this.PeriodaVzorkovani = value;
			}
		}
    	
    	// Vlastnos definujici stav hladiny tanku v procentech
    	public double Stav{
    		get{
    			return this.Objem/this.MaxObjem;
    		}
    	}
    	
    	// Vlastnos definujici resetovaci hodnotu objemu
    	public double ResetHodnotaObjemu{
    		set{
    			if( value > 1.0 || value < 0)
    				throw new ArgumentOutOfRangeException();
    			
    			this.ResseObjem = value;
    		}
    		
    		get{ return this.ResseObjem;}  		
    	}
    	
    	// Vlastnost definujici resetovaci hodnotu koncentrace v tanku
    	public double ResetHodnotaKoncentrace{
    		set{
    			if( value > 1.0 || value < 0)
    				throw new ArgumentOutOfRangeException();
    			
    			this.ResetKoncentrace = value;
    		}
    		
    		get{ return this.ResetKoncentrace;}  		
    	}
    	
    	// Vlasnost tepelne pojistky cerpadla koncentrátu
    	public bool TepelnaPojistka{
			get{ return false; }
		}
    	
    	// Vlastnost prutok koncetratu
    	public double PrutokKoncentratu{
    		get{
    			if(this.CerpadloKoncentratu == false)
    				return 0.0;
    			
    			if(this.Stav < 0.01)
    				return 0.0;
    			
    			return this.PrutokCerpadlaKoncentratu;
    		}
    	}
    	// Vlastnos definujici binarni snimace na tanku
    	public bool SnimacLAH{
    		get{
    			if(this.Stav > 0.95)
    				return true;
    			else
    				return false;
    		}
    	}
    	public bool SnimacLAL{
    		get{
    			if(this.Stav > 0.05)
    				return true;
    			else
    				return false;
    		}
    	}
    	
    	// Vlastnosts zadane hodnoty pro cerpadlo koncentratu
    	public double ZadanaHodnota{
			
			set{
				if(value > 0.5)
					this.CerpadloKoncentratu = true;
				else
					this.CerpadloKoncentratu = false;
			}
			get{
    			if(this.CerpadloKoncentratu)
    				return 1.0;
    			else
    				return 0.0;
			}
		}
    	
    	// Vlastnosti pro zadani aktualniho pritoku a odtoku do/z tanku
    	public double PritokTanku{
    		set{
    			if(value < 0)
    				throw new ArgumentOutOfRangeException("Pokus o zadani zaporneho pritoku do tanku");
    			else
    				this.Pritok = value;
    		}
    		
    		get{ return this.Pritok; }
    	}
    	
    	public double OdtokTanku{
    		set{
    			if(value < 0)
    				throw new ArgumentOutOfRangeException("Pokus o zadani zaporneho odtoku z tanku");
    			else
    				if(this.Stav >= 0.01)
    					this.Odtok = value;
    				else
    					this.Odtok = 0.0;
    		}
    		get{ return this.Odtok;}
    	}
    			
    	// Funkce provadejici jeden krok simulace
    	public void SimStep(){
    		
    		this.Objem += (this.Pritok-this.Odtok)*this.PeriodaVzorkovani;		
    		
    		if(this.Objem > this.MaxObjem)
    			this.Objem = this.MaxObjem;
    		
    		if(this.CerpadloKoncentratu)
    			this.Objem -= this.PrutokCerpadlaKoncentratu*this.PeriodaVzorkovani;
    		
    		if(this.Objem < 0.0)
    			this.Objem = 0.0;
    	}
    	
    	
    	// Funkce provádějící výpočet nové hodnoty teploty v tanku
    	public void VypoctiTeplotu(double TeplotaPritoku, double CrirkualciniPrutok, double TeplotaVcirkulaci){
    		
    		// Pokud je v tanku nejaka kapalina
    		if(this.Stav > 0.01){
    			
    			// Vypocet stavajiciho tepla v tanku
    			double Q = (Stav*MaxObjem - Pritok*PeriodaVzorkovani)*MtkH2O*(TeplotaRoztoku + 273.15);
    			
    			// Pokud do tanku neco priteklo
    			if(Pritok > 0.01)	
    				Q += Pritok*PeriodaVzorkovani*MtkH2O*(TeplotaPritoku + 273.15);
    			
    			// Pokud je spuštěn cirkulační objeh tanku
    			if(CrirkualciniPrutok > 0.01){	// Pokud je spustena cirkulace
    				Q += CrirkualciniPrutok*PeriodaVzorkovani*MtkH2O*(TeplotaVcirkulaci - TeplotaRoztoku);
    				
    			}
    			
    			// Pokud je teplota v tanku vyžší jak teplota okolí
    			// uplatní se ztráty vedení tepla přes plášť tanku;
    			if(this.TeplotaRoztoku != this.TeplotaOkoli){
    				
    				if(TloustkaSteny != 0.0)
    					Q -= PeriodaVzorkovani*SoucTepelVodivosti*(Povrch*Stav)*(TeplotaRoztoku - TeplotaOkoli)/TloustkaSteny;
    				else 
    					throw new DivideByZeroException();
    			}
    			
    			// Vypocet nove hodnoty teploty v tanku
    			this.TeplotaRoztoku = Q/( (Stav*MaxObjem)*MtkH2O) - 273.15;
    			
    			if(this.TeplotaRoztoku > 100.0) 	// Teplota vody nemůže přesáhonou thodnotu 100 °C
    				this.TeplotaRoztoku = 100.0;
    			
    		}
    		else
    			
    			this.TeplotaRoztoku = this.TeplotaOkoli;
    	}
    	
		// Funkce provádějící výpočet koncentrace
		public void VypočtiKoncentraci(double PritokKoncentratu, double Koncentrace, double koncentrace_pritoku){
			
			this.KoncentraceRoztoku = (this.KoncentraceRoztoku*this.Objem + PritokKoncentratu*this.PeriodaVzorkovani*Koncentrace)/(this.Objem + PritokKoncentratu*this.PeriodaVzorkovani);
			this.Objem += PritokKoncentratu*this.PeriodaVzorkovani;
			
			this.KoncentraceRoztoku = (this.KoncentraceRoztoku*this.Objem + this.Pritok*this.PeriodaVzorkovani*koncentrace_pritoku)/(this.Objem +  this.Pritok*this.PeriodaVzorkovani);
		}

    	// Funkce resetu modelu
    	public void Reset(){
    		this.CerpadloKoncentratu = this.ResetCerpadlaKoncentratu;
    		this.Objem = this.ResseObjem * this.MaxObjem;
    		this.KoncentraceRoztoku = this.ResetKoncentrace;
    		this.TeplotaRoztoku = this.TeplotaOkoli;
    	}
    	
    	// Konstruktory
    	public TankMumModel(){
    		
    		this.MaxObjem = 4000.0;
    		this.Objem = 2000.0;
    		this.Odtok = 0.0;
    		this.Pritok = 0.0;
    		this.PeriodaVzorkovani = 0.0;
    		this.TeplotaOkoli = 25.0;
    		this.TeplotaRoztoku = 25.0;
    		this.KoncentraceRoztoku = 0.0;
    		this.MtkH2O = 4190.0;				// Měrná tepelná kapacita vody
    		this.SoucTepelVodivosti = 3.0; 	    // Hodnota soucinitele tepelne vodivosti 
    		this.TloustkaSteny = 0.1;			// Tloustka steny tanku bude prednastavena na hodnotu 10 cm;
    		this.CerpadloKoncentratu = false;
    		this.Povrch = 700.0;				// Pocatecni hodnota povrchu byla stanovena na 900 metru cteverecnich
    		this.Prumer = 15.0;
    		this.ResseObjem = 0.5;
    		this.ResetKoncentrace = 0.00;
    		this.ResetCerpadlaKoncentratu = false;
    		this.PrutokCerpadlaKoncentratu = 0.5; // litru za sekundu
    	}
    	
    	public TankMumModel(double MaximalniObjem, double PocatecniStav){
    		
    		if(PocatecniStav < 0.0 && PocatecniStav > 1.0)
    			throw new ArgumentOutOfRangeException();
    		
    		this.MaxObjem = MaximalniObjem;
    		this.Objem = MaximalniObjem*PocatecniStav;
    		this.Odtok = 0.0;
    		this.Pritok = 0.0;
    		this.PeriodaVzorkovani = 0.0;
    		this.TeplotaOkoli = 25.0;
    		this.TeplotaRoztoku = 25.0;
    		this.KoncentraceRoztoku = 0.0;
    		this.MtkH2O = 4190.0;				// Měrná tepelná kapacita vody
    		this.SoucTepelVodivosti = 3.0; 	    // Hodnota soucinitele tepelne vodivosti 
    		this.TloustkaSteny = 0.1;			// Tloustka steny tanku bude prednastavena na hodnotu 10 cm;
    		this.CerpadloKoncentratu = false;
    		this.Povrch = 700.0;				// Pocatecni hodnota povrchu byla stanovena na 900 metru cteverecnich
    		this.Prumer = 15.0;
    		this.ResseObjem = 0.5;
    		this.ResetKoncentrace = 0.00;
    		this.ResetCerpadlaKoncentratu = false;
    		this.PrutokCerpadlaKoncentratu = 0.5; // litru za sekundu

    	}
    }
	
    
    // Trida definujici potrubi
    public class Potrubi{
    	
    	public double Prutok;
    	public double Teplota;
    	public double KoncentraceNaOH;
    	public double KoncentraceHNO3;
    	private double MtkH2O = 4190.0;	//  Merna tepelna kapacita vody
    	
    	// Funkce pro urceni teploty kapaliny v potrubi na zaklade teplot jednotlivych privodu do potrubi
    	public void VypocetTeploty(double[] Pritoky, double[] TeplotyPritoku, double PeriodaVzorkovani){
    		
    		// Velikost obou poli v parametrech funkce musi byt stejna
    		if(Pritoky.Length != TeplotyPritoku.Length)
    			throw new ArrayTypeMismatchException("Vypocet teploty roztoku v potrubi: Nesouhlasi velikost poli Pritoky a TeplotyPritoku");
    	
    		// Pomocne promenne:
    		double Q = 0.0; 				//	Celkove teplo Q
    		double CelkovyObjem = 0.0;		//  Hodnota Celkoveho pritoku krat perioda vzorkovani
    		
    		for (int i = 0; i < Pritoky.Length; i++){
    			
    			Q += Pritoky[i]*PeriodaVzorkovani*MtkH2O*(TeplotyPritoku[i] + 273.15);
    			CelkovyObjem += Pritoky[i]*PeriodaVzorkovani;
    		}
    		
    		// Pokud je celkovy pritok nulovy, nema novou teplotu smysl pocital
    		if(CelkovyObjem > 0.0){
    			this.Teplota = Q/( CelkovyObjem * MtkH2O) - 273.15;
    		}

    	}
    
    	// Funkce pro urceni teploty v cirkulacnim okruhu;
    	public void VypocetTeploty(double TepelnyPrikon, double TeplotaPredOhratim, double PeriodaVzorkovani){
    		
    		if (TepelnyPrikon > 0.0){
    			
    			double DodaneTeplo = TepelnyPrikon*PeriodaVzorkovani;
    			double RozdilTeploty = 0.0;
    			
    			if(this.Prutok > 0.01){
    				RozdilTeploty = DodaneTeplo/(this.Prutok*PeriodaVzorkovani*this.MtkH2O);
    				this.Teplota = TeplotaPredOhratim  + RozdilTeploty;
    			}
    			else{
    				RozdilTeploty = DodaneTeplo/(100.0*this.MtkH2O);
    				this.Teplota += RozdilTeploty;
    			}
    			
    		
    		} else
    			
    			this.Teplota = TeplotaPredOhratim;
    		
    		if(this.Teplota > 100.0)
    			this.Teplota = 100.0;
    	}
    	
    	// Prazdny konstruktor
    	public Potrubi(){
    		
    		this.Prutok = 0.0;
    		this.KoncentraceNaOH = 0.0;
    		this.KoncentraceHNO3 = 0.0;
    		this.Teplota = 25.0;
    	}
    }
    
    
/* ********************************************************************************************************
 *					 Hlavni trida definujici celkovy numeriky model cistici stanice						  *
 * *******************************************************************************************************/
   
	public class NumerickyModelCIP{

		#region Komponenty numerickeho modelu
		public TankMumModel TankNaOH;
		public TankMumModel TankHNO3;
		public TankMumModel TankVypVoda;
		public TankMumModel TankCisVoda;
		public TankMumModel DP111;
		public TankMumModel DP112;
		
		public KlapkaNumModel BV104_03;
		public KlapkaNumModel BV103_03;
		public KlapkaNumModel BV102_05;
		public KlapkaNumModel BV100_01;
		public KlapkaNumModel BV101_03;
		public KlapkaNumModel BV101_01;
		public KlapkaNumModel BV102_01;
		public KlapkaNumModel BV103_01;
		public KlapkaNumModel BV104_01;
		
		public MvsNumModel CP109;
		public MvsNumModel CP107;
		public MvsNumModel CP106;
		
		public KlapkaNumModel SSV109_01;
		public MvsNumModel THE_105;
		public MvsNumModel THE_106;
	
		public MvsNumModel QIC109_03;
		public MvsNumModel TIC109_02;	
		public MvsNumModel FIC109_01;	
		public MvsNumModel TIC102_03;	
		public MvsNumModel TIC103_03;
		public MvsNumModel TIC105_02;
		public MvsNumModel QIC105_01;
		public MvsNumModel TIC106_02;
		public MvsNumModel QIC106_01;
		
		// Poturbi
		public Potrubi PotrubiVratky;
		public Potrubi VystupniPotrubi;
		public Potrubi CirkulaceNaOH;
		public Potrubi CirkualceHNO3;
		public Potrubi PritokCisteVody;
		
		// Vystupni fronta
		private System.Collections.ArrayList  Fronta;
		private int Pocitadlo = 0;
		
		// Vodivosti roztoku
		public double vodivost_vratky =  0.0;
		public double vodivost_NaOH = 0.0;
		public double vodivost_HNO3 = 0.0;
			
		#endregion
		
		// Funkce pro reset
		public void Reset(){
			
			TankNaOH.Reset();
			TankHNO3.Reset();
			TankVypVoda.Reset();
			TankCisVoda.Reset();
			
			DP111.Reset();
			DP112.Reset();
			CP109.Reset();
			CP107.Reset();
			CP106.Reset();
			
			BV104_03.Reset();
			BV103_03.Reset();
			BV102_05.Reset();
			BV100_01.Reset();
			BV101_03.Reset();
			BV101_01.Reset();
			BV102_01.Reset();
			BV103_01.Reset();
			BV104_01.Reset();
			SSV109_01.Reset();
		
			THE_105.Reset();
			THE_106.Reset();
		}
		
		// Funkce pro nastaveni periody vzorkovani u jednotlivych prvku
		public void SetSampleTime(double SampleTime){
	
		TankNaOH.SampleTime = SampleTime;
		TankHNO3.SampleTime = SampleTime;
		TankVypVoda.SampleTime = SampleTime;
		TankCisVoda.SampleTime = SampleTime;
		DP111.SampleTime = SampleTime;
		DP112.SampleTime = SampleTime;
		BV104_03.SampleTime = SampleTime;
		BV103_03.SampleTime = SampleTime;
		BV102_05.SampleTime = SampleTime;
		BV100_01.SampleTime = SampleTime;
		BV101_03.SampleTime = SampleTime;
		BV101_01.SampleTime = SampleTime;
		BV102_01.SampleTime = SampleTime;
		BV103_01.SampleTime = SampleTime;
		BV104_01.SampleTime = SampleTime;
		CP109.SampleTime = SampleTime;
		CP107.SampleTime = SampleTime;
		CP106.SampleTime = SampleTime;
		SSV109_01.SampleTime = SampleTime;
		THE_105.SampleTime = SampleTime;
		THE_106.SampleTime = SampleTime;
		QIC109_03.SampleTime = SampleTime;
		TIC109_02.SampleTime = SampleTime;	
		FIC109_01.SampleTime = SampleTime;	
		TIC102_03.SampleTime = SampleTime;	
		TIC103_03.SampleTime = SampleTime;
		TIC105_02.SampleTime = SampleTime;
		QIC105_01.SampleTime = SampleTime;
		TIC106_02.SampleTime = SampleTime;
		QIC106_01.SampleTime = SampleTime;
		}
		
		// Funkce pro nastavení teploty okolního prostředí
		public void SetTeplotaOkoli(double Teplota){
			
			this.TankCisVoda.TeplotaOkoliTanku = Teplota;
			this.TankHNO3.TeplotaOkoliTanku = Teplota;
			this.TankNaOH.TeplotaOkoliTanku = Teplota;
			this.TankVypVoda.TeplotaOkoliTanku = Teplota;
		}
		
		// Funkce pro nastaveni merne tepelne kapacity roztoku
		public void SetMTK(double MTK){
			
			this.TankCisVoda.MernaTepelnaKapacita = MTK;
			this.TankHNO3.MernaTepelnaKapacita = MTK;
			this.TankNaOH.MernaTepelnaKapacita = MTK;
			this.TankVypVoda.MernaTepelnaKapacita = MTK;
		}
		
		// Buffer simulujici pripojeni tanku na vystupu
		private Potrubi VystupniBuffer(Potrubi Vstupni_hodnota, double Zpozdeni, double Perioda_vzorkovani){
			
			Potrubi pom = new Potrubi();
			
			int Velikost = System.Convert.ToInt32(Zpozdeni/Perioda_vzorkovani);
			++ this.Pocitadlo;
	
					
			// Vlozeni prvku na vstup fronty
		
			Fronta.Insert(0, Vstupni_hodnota);
			
			// Pokud je vystupni fronta naplnena, odebere se první vložený prvek
			if (Pocitadlo >= 300){
				
				Pocitadlo = 300;
				pom = (Potrubi) Fronta[Pocitadlo-1];
				Fronta.RemoveAt(Pocitadlo-1);
				return pom;
				
			}
			
			pom = new Potrubi();
			pom.KoncentraceHNO3 = 0.0;
			pom.KoncentraceNaOH = 0.0;
			pom.Prutok = 0.0;
			pom.Teplota = this.TankHNO3.TeplotaOkoliTanku;
			
			return pom;
				
		
		}
		
		
	
		public void KrokSimulace(object data){
			
			// Provedeni dilcich kroku u ventilu a klapek
			BV104_03.SimStep();
			BV103_03.SimStep();
			BV102_05.SimStep();
			BV100_01.SimStep();
			BV101_03.SimStep();
			BV101_01.SimStep();
			BV102_01.SimStep();
			BV103_01.SimStep();
			BV104_01.SimStep();
			SSV109_01.SimStep();
		    THE_105.SimStep();
		    THE_106.SimStep();
		    
		    CP109.SimStep();
			CP107.SimStep();
			CP106.SimStep();
			
		   	
			// -----------------------------------------------------------------
			// Výpocet novych hodnot prutoku potrubim, pritoku a odtoku z tanku
		    // -----------------------------------------------------------------
		  		    
			// Pokud je stridaci ventil nastaven na vystupni potrubi ze stanice
			if(this.SSV109_01.Stav < 0.5){
  	
		    	 // Pro pripad, ze vystupni potrubi vede do kanalu
		   		 
		    	 // Výstupní odtok ze stanice je závislý na stavu výstupního čerpadla,
		    	 // Na stavech ventilu vedoucího do výstupních ventilů
		    	 // A v neposlední řadě musí být v tancích nějaký obsah, jenž může odtékat
		    	 
		    	 double pom = 0.0;
		   		 if(this.TankCisVoda.Stav > 0.01)   	// Pokud je v tanku nejaka tekutina, muze dochazet k vypousteni tanku;
		   		 	pom += this.BV101_01.Stav;			// Na celkovém odtoku ze stanice se daný tank podílý svým odtokem v závistlosti na otevření klapky na výstupu z ventilu 
		   		 if(this.TankHNO3.Stav > 0.01)
		   		 	pom += this.BV102_01.Stav;
		   		 if(this.TankNaOH.Stav > 0.01)
		   		 	pom += this.BV103_01.Stav;
		   		 if(this.TankVypVoda.Stav > 0.01)
		   		 	pom += this.BV104_01.Stav;
						   			
		   		 if(  pom > 1.0 )
			    	pom = 1.0;
			    
		   		 // Výstupní prutok je tedy dan Stavem Cerpadala na vystupu * stav ventilu na vstupu potrubi * stav stridaciho ventilu
			    this.VystupniPotrubi.Prutok = this.CP109.StavVjednotkach * pom * (1 - 2*this.SSV109_01.Stav);
			    
			    
			    // Inkrementace fronty realizujici zpozdeni mezi vystupem s tanice a jejim vstupem
			    
			    this.PotrubiVratky = this.VystupniBuffer(VystupniPotrubi, 15.0, this.TankHNO3.SampleTime);
		    	
		   	}
		    
			// Pro pripad prepnuti stridaciho ventilu do rezimu napousteni tanku
			if(this.SSV109_01.Stav > 0.5){
				
				 // V tomto případě se jedná o uzavřený okruh uvnitř čistící staniceů
				 
				 // Výstupní odtok ze stanice je závislý na stavu výstupního čerpadla,
		    	 // Na stavech ventilu vedoucího do výstupních ventilů
		    	 // Na stavu střídacího ventilu
		    	 // Jelikož se jedná o uzavřený okruh je výstupní odtok závistlý i na stavech ventilů
		    	 //  	na potrubí vratky
		    	 // A v neposlední řadě musí být v tancích nějaký obsah, jenž může odtékat
				 
		    	 // Stav ventilu pripojených na výstupní potrubí
		    	 double Pom1 = 0.0;
				 if(this.TankCisVoda.Stav > 0.01)   		// Pokud je v tanku nejaka tekutina, muze dochazet k vypousteni tanku;
		   		 	Pom1 += this.BV101_01.Stav;				// Na celkovém odtoku ze stanice se daný tank podílý svým odtokem v závistlosti na otevření klapky na výstupu z ventilu 
		   		 if(this.TankHNO3.Stav > 0.01)
		   		 	Pom1 += this.BV102_01.Stav;
		   		 if(this.TankNaOH.Stav > 0.01)
		   		 	Pom1 += this.BV103_01.Stav;
		   		 if(this.TankVypVoda.Stav > 0.01)
		   		 	Pom1 += this.BV104_01.Stav;
						   			
		   		 if(  Pom1 > 1.0 )
			    	Pom1 = 1.0;
				
		   		 // Stav Ventilů připojených na potrubí vratky
		   		 double Pom2 = this.BV100_01.Stav + this.BV102_05.Stav + this.BV103_03.Stav + this.BV104_03.Stav;
				 if(Pom2 > 1.0)
					Pom2 = 1.0;
				
				// Výpočet výstupního průtoku
 				this.VystupniPotrubi.Prutok = this.CP109.StavVjednotkach * Pom1 * Pom2 * (2*this.SSV109_01.Stav - 1);
				
 				// Jelikož se jedná o uzavřený okruh má výstupní potrubí a potrubí vratky stejné parametry
 				this.PotrubiVratky.Prutok = this.VystupniPotrubi.Prutok;
				this.PotrubiVratky.Teplota = this.VystupniPotrubi.Teplota;
				this.PotrubiVratky.KoncentraceHNO3 = this.VystupniPotrubi.KoncentraceHNO3;
				this.PotrubiVratky.KoncentraceNaOH = this.VystupniPotrubi.KoncentraceNaOH;
			}
		       
			// Průtok cirkulačním potrubím je dán stavem cirkulačního čerpadla
			// Aby mohla probíhat cirkulace, musí být v tancích neco co může cirkulovat :-)
			
			if(this.TankHNO3.Stav >= 0.01)
				this.CirkualceHNO3.Prutok = this.CP106.StavVjednotkach;
			else
				this.CirkualceHNO3.Prutok = 0.0;
				
			if(this.TankNaOH.Stav >= 0.01)
				this.CirkulaceNaOH.Prutok = this.CP107.StavVjednotkach;
			else
				this.CirkulaceNaOH.Prutok = 0.0;
			
			// Vypocet novych hodnot pritoku tanku
			// Pritoky jednotlivych tanku jsou urceny rozdelenim Prutoku vratky podle podilu otevreni ventilu
			
			// Pomocna proměnná udávající součet stavu otevreni klapek;
			double Suma_stavu = this.BV100_01.Stav + this.BV102_05.Stav + this.BV103_03.Stav + this.BV104_03.Stav;
			
			if(Suma_stavu >= 0.01)
			{
				// Vypocet novych pritoku u jednotlivych tanku;
				this.TankHNO3.PritokTanku = (this.BV102_05.Stav/Suma_stavu)*this.PotrubiVratky.Prutok;
				this.TankNaOH.PritokTanku = (this.BV103_03.Stav/Suma_stavu)*this.PotrubiVratky.Prutok;
				this.TankVypVoda.PritokTanku = (this.BV104_03.Stav/Suma_stavu)*this.PotrubiVratky.Prutok;
			}
			else{
				this.TankHNO3.PritokTanku = 0.0;
				this.TankNaOH.PritokTanku = 0.0;
				this.TankVypVoda.PritokTanku = 0.0;
			}
				
			// Pritok do tanku s cistou vodou je dan pouze stavem otevreni klapky na pritoku tohoto tanku
			this.TankCisVoda.PritokTanku = this.PritokCisteVody.Prutok*this.BV101_03.Stav;
			
			// Vypocet jednotlivych odtoku z tanku
			// Celkový odtok ze stanice bude rozdělen v poměru otevření jednoltivých ventilů
			Suma_stavu = 0.0;
			if(this.TankCisVoda.Stav > 0.01)   			// Pkud v tanku nad ventilem nic neni, nemůže se podílet na odtoku				
		   		 Suma_stavu += this.BV101_01.Stav;				
		   	if(this.TankHNO3.Stav > 0.01)
		   		 Suma_stavu += this.BV102_01.Stav;
		   	if(this.TankNaOH.Stav > 0.01)
		   		 Suma_stavu += this.BV103_01.Stav;
		   	if(this.TankVypVoda.Stav > 0.01)
		   		 Suma_stavu += this.BV104_01.Stav;
						   						
			// Pokud jsou výstupní ventily otevřeny
			if(Suma_stavu >= 0.01)
			{
				if(this.TankHNO3.Stav >= 0.01)	// pokud má z tanku co odtíkat
					this.TankHNO3.OdtokTanku = (this.BV102_01.Stav/Suma_stavu)*this.VystupniPotrubi.Prutok; // Rozdělý se celkový odtok v poměru hodnoty otevření jednotlivých ventilů
				
				if(this.TankNaOH.Stav >= 0.01)
					this.TankNaOH.OdtokTanku = (this.BV103_01.Stav/Suma_stavu)*this.VystupniPotrubi.Prutok;
				
				if(this.TankVypVoda.Stav >= 0.01)
					this.TankVypVoda.OdtokTanku = (this.BV104_01.Stav/Suma_stavu)*this.VystupniPotrubi.Prutok;
		    	
				if(this.TankCisVoda.Stav >= 0.01)
					this.TankCisVoda.OdtokTanku = (this.BV101_01.Stav/Suma_stavu)*this.VystupniPotrubi.Prutok;
			
			// Pokud jsou výstupní ventily zavřené, nemůže nic odtíkat...
			} else{
				this.TankHNO3.OdtokTanku = 0.0;
				this.TankNaOH.OdtokTanku = 0.0;
				this.TankVypVoda.OdtokTanku = 0.0;
		    	this.TankCisVoda.OdtokTanku = 0.0;
			}
		   		
			
			//--------------------------------------------------------------
			// Výpočet nových hodnto teplot v tancich a potrubi
		    //--------------------------------------------------------------
		    
		    // Vypocet teploty ve vystupnim potrubi
		    double[] Pritoky = new double[]{ TankCisVoda.OdtokTanku, TankHNO3.OdtokTanku, TankNaOH.OdtokTanku, TankVypVoda.PritokTanku};
		    double[] TeplotyPritoku = new double[]{ TankCisVoda.Teplota, TankHNO3.Teplota, TankNaOH.Teplota, TankVypVoda.Teplota};
		    
		    this.VystupniPotrubi.VypocetTeploty(Pritoky, TeplotyPritoku, this.CP106.SampleTime);
		    
		    // Vypocet teploty v cyrkulacnich okruzich;
		    this.CirkualceHNO3.VypocetTeploty(THE_105.StavVjednotkach, TankHNO3.Teplota, TankHNO3.SampleTime);
		    this.CirkulaceNaOH.VypocetTeploty(THE_106.StavVjednotkach, TankNaOH.Teplota, TankNaOH.SampleTime);
		    
		    // Vypocet novych teplot v tankci
		    this.TankHNO3.VypoctiTeplotu(PotrubiVratky.Teplota, CirkualceHNO3.Prutok, CirkualceHNO3.Teplota);
		    this.TankNaOH.VypoctiTeplotu(PotrubiVratky.Teplota, this.CirkulaceNaOH.Prutok, CirkulaceNaOH.Teplota);
		    this.TankVypVoda.VypoctiTeplotu(PotrubiVratky.Teplota, 0.0, 0.0);
		    this.TankCisVoda.VypoctiTeplotu(PritokCisteVody.Teplota, 0.0, 0.0);
		    
		    //--------------------------------------------------------------
		    // Výpočet nových koncentrací roztoků
		    //--------------------------------------------------------------
		    
		    this.TankHNO3.VypočtiKoncentraci(this.DP111.PrutokKoncentratu, this.DP111.Koncetntace, this.PotrubiVratky.KoncentraceHNO3);
		    	
		    this.TankNaOH.VypočtiKoncentraci(this.DP112.PrutokKoncentratu, this.DP112.Koncetntace, this.PotrubiVratky.KoncentraceNaOH);
		    
		    if(this.BV101_01.Stav > 0.05 && this.VystupniPotrubi.Prutok > 0.01 && this.TankCisVoda.Stav > 0.01){
		    	
		    	this.VystupniPotrubi.KoncentraceHNO3 = 0.0;
		    	this.VystupniPotrubi.KoncentraceNaOH = 0.0;
		    }
		    
		    if(this.BV104_01.Stav > 0.05 && this.VystupniPotrubi.Prutok > 0.01 && this.TankVypVoda.Stav > 0.01){
		    	
		    	this.VystupniPotrubi.KoncentraceHNO3 = 0.0;
		    	this.VystupniPotrubi.KoncentraceNaOH = 0.0;
		    }
		    
		    if(this.CP106.Stav > 0.05) // Pokud je spusteno cirkulacni cerpadlo okruhu HNO3
		    	this.CirkualceHNO3.KoncentraceHNO3 = this.TankHNO3.Koncetntace;
		    
		    if(this.CP107.Stav > 0.05) // Pokud je spusteno cirkulacni cerpadlo okruhu NaOH
		    	this.CirkulaceNaOH.KoncentraceNaOH = this.TankNaOH.Koncetntace;
		     
		    if(this.BV102_01.Stav > 0.05 && this.VystupniPotrubi.Prutok > 0.01 && this.TankHNO3.Stav > 0.01)
		    	this.VystupniPotrubi.KoncentraceHNO3 = this.TankHNO3.Koncetntace;
		    else
		    	this.VystupniPotrubi.KoncentraceHNO3 = 0.0;
		    
		    if(this.BV103_01.Stav > 0.05 && this.VystupniPotrubi.Prutok > 0.01 && this.TankNaOH.Stav > 0.01)
		    	this.VystupniPotrubi.KoncentraceNaOH = this.TankNaOH.Koncetntace;
		     else
		    	this.VystupniPotrubi.KoncentraceNaOH = 0.0;
		    
		    
			//--------------------------------------------------------------------------------
		    // Vypocet vodivosti
		    //---------------------------------------------------------------------------------
		    
		    this.vodivost_vratky = (0.3*this.PotrubiVratky.KoncentraceNaOH + 0.45*this.PotrubiVratky.KoncentraceHNO3)*(1.0 + 0.01*(this.PotrubiVratky.Teplota - 25.0));
		    this.vodivost_NaOH = (0.3*this.CirkulaceNaOH.KoncentraceNaOH )*(1.0 + 0.01*(this.CirkulaceNaOH.Teplota - 25.0));
		    this.vodivost_HNO3 = (0.45*this.CirkualceHNO3.KoncentraceHNO3 )*(1.0 + 0.01*(this.CirkualceHNO3.Teplota - 25.0));
		    
		    // Predani nových parametru snimačum
		    QIC109_03.ZadanaHodnotaVjednotkach = vodivost_vratky*1000.0;
			TIC109_02.ZadanaHodnotaVjednotkach = this.PotrubiVratky.Teplota;
			FIC109_01.ZadanaHodnotaVjednotkach = this.VystupniPotrubi.Prutok;
			
			TIC102_03.ZadanaHodnotaVjednotkach = this.TankHNO3.Teplota;
			TIC103_03.ZadanaHodnotaVjednotkach = this.TankNaOH.Teplota;
			
			TIC105_02.ZadanaHodnotaVjednotkach = this.CirkualceHNO3.Teplota;
			QIC105_01.ZadanaHodnotaVjednotkach = this.vodivost_HNO3*1000.0;
			
			TIC106_02.ZadanaHodnotaVjednotkach = this.CirkulaceNaOH.Teplota;
			QIC106_01.ZadanaHodnotaVjednotkach = this.vodivost_NaOH*1000.0;
			
		     // Provedeni simulačních kroků v tanku
		    this.TankVypVoda.SimStep();
		    this.TankHNO3.SimStep();
		    this.TankNaOH.SimStep();
		    this.TankCisVoda.SimStep();
		    this.DP111.SimStep();
		    this.DP112.SimStep();
		    
		    // Provedení simulačních kroků simímačů
		    QIC109_03.SimStep();
			TIC109_02.SimStep();
			FIC109_01.SimStep();
			TIC102_03.SimStep();	
			TIC103_03.SimStep();
			TIC105_02.SimStep();
			QIC105_01.SimStep();
			TIC106_02.SimStep();
			QIC106_01.SimStep();
			
		}
		
		// prazdny konsturktor modelu
		public NumerickyModelCIP(){
			
			TankNaOH = new TankMumModel();
			TankNaOH.ResetHodnotaKoncentrace = 0.03;
			TankNaOH.Koncetntace = 0.03;
				
			TankHNO3 = new TankMumModel();
			TankHNO3.ResetHodnotaKoncentrace = 0.03;
			TankHNO3.Koncetntace = 0.03;
			
			TankVypVoda = new TankMumModel();
			
			TankCisVoda = new TankMumModel(2000.0, 0.5);
			TankCisVoda.Prumer = 7.0;

			
			DP111 = new TankMumModel(300, 1.0);
			DP111.Koncetntace = 0.95;
			DP111.ResetHodnotaKoncentrace = 0.95;
			DP111.ResetHodnotaObjemu = 1.0;
			
			DP112 = new TankMumModel(300, 1.0);
			DP112.Koncetntace = 0.95;
			DP112.ResetHodnotaKoncentrace = 0.95;
			DP112.ResetHodnotaObjemu = 1.0;
			
			BV104_03 = new KlapkaNumModel();
			BV103_03 = new KlapkaNumModel();
			BV102_05 = new KlapkaNumModel();
			BV100_01 = new KlapkaNumModel();
			BV101_03 = new KlapkaNumModel();
			BV101_01 = new KlapkaNumModel();
			BV102_01 = new KlapkaNumModel();
			BV103_01 = new KlapkaNumModel();
			BV104_01 = new KlapkaNumModel();
			
			CP109 = new MvsNumModel();
			CP109.MaxHodnota = 7;  // Litru za sekundu;
			CP109.MinHodnota = 0.0;
			
			CP107 = new MvsNumModel();
			CP107.MaxHodnota = 8.3; // Litru za sekundu;
			CP107.MinHodnota = 0.0;
			
			CP106 = new MvsNumModel();
			CP106.MaxHodnota = 8.3; // Litru za sekundu;
			CP106.MinHodnota = 0.0;
			
			SSV109_01 = new KlapkaNumModel();
			
			THE_105 = new MvsNumModel();
			THE_105.MaxHodnota = 750000.0; // 750 kW;
			THE_105.MinHodnota = 0.0;
			
			THE_106 = new MvsNumModel();
			THE_106.MaxHodnota = 750000.0; // 750 kW;
			THE_106.MinHodnota = 0.0;
					
			TIC109_02 = new MvsNumModel();
			TIC109_02.MaxHodnota = 100; // °C
			TIC109_02.MinHodnota = 0.0;
			TIC109_02.Casova_konstanta = 0.6; //s
				
			FIC109_01 = new MvsNumModel();
			FIC109_01.MaxHodnota = 100;
			FIC109_01.MinHodnota = 0.0;
			
			TIC102_03 = new MvsNumModel();
			TIC102_03.MaxHodnota = 100;
			TIC102_03.MinHodnota = 0.0;
			TIC102_03.Casova_konstanta = 0.6;
				
			TIC103_03 = new MvsNumModel();
			TIC103_03.MaxHodnota = 100;
			TIC103_03.MinHodnota = 0.0;
			TIC103_03.Casova_konstanta = 0.6;
			
			TIC105_02 = new MvsNumModel();
			TIC105_02.MaxHodnota = 100;
			TIC105_02.MinHodnota = 0.0;
			TIC105_02.Casova_konstanta = 0.6;
			
			TIC106_02 = new MvsNumModel();
			TIC106_02.MaxHodnota = 100;
			TIC106_02.MinHodnota = 0.0;
			TIC106_02.Casova_konstanta = 0.6;
			
			QIC105_01 = new MvsNumModel();
			QIC105_01.MaxHodnota = 300;
			QIC105_01.MinHodnota = 0.0;
			QIC105_01.Casova_konstanta = 2.0;
			
			QIC106_01 = new MvsNumModel();
			QIC106_01.MaxHodnota = 300;
			QIC106_01.MinHodnota = 0.0;
			QIC106_01.Casova_konstanta = 2.0;
			
			QIC109_03 = new MvsNumModel();
			QIC109_03.MaxHodnota = 300;
			QIC109_03.MinHodnota = 0.0;
			QIC109_03.Casova_konstanta = 2.0;
			
			this.VystupniPotrubi = new Potrubi();
			this.PotrubiVratky = new Potrubi();
			this.CirkualceHNO3 = new Potrubi();
			this.CirkulaceNaOH = new Potrubi();
			
			this.PritokCisteVody = new Potrubi();
			this.PritokCisteVody.Teplota = 18.0;
			this.PritokCisteVody.Prutok =  20.0;
			
			// Inicializace vystupni fronty
			Fronta = new System.Collections.ArrayList ();
		}
	}
	
    

}//End namespace KomponetyCIP
