//===========================================================================//
// File:    lranlyzr.cpp                                                     
// Project: LabRat                                                 		 
// Contents: 				  
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 07/12/96  JSE  Initial coding.                                             
//---------------------------------------------------------------------------//
// Copyright (C) 1996, Virtual World Entertainment, Inc.                     //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#include "stdafx.h"

#include "lranlyzr.hpp"
#include "math.h"
#include "LabRatDoc.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


//##########################################################################
//#######################    TraceAnalyzerRegistry    
//##########################################################################

TraceAnalyzerRegistry::TraceAnalyzerRegistry(void)
{
	REGISTER_ANALYZER(OnAnalyzer);
	REGISTER_ANALYZER(OffAnalyzer);
	REGISTER_ANALYZER(LogicalAnalyzer);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

TraceAnalyzerRegistry::~TraceAnalyzerRegistry(void)
{
	CObject *delete_me;

	while(!analyzerList.IsEmpty())
	{
		delete_me = analyzerList.RemoveHead();
		delete delete_me;
	}

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

CMenu *TraceAnalyzerRegistry::CreateMenu(int type)
{
	CMenu *menu = new CMenu;
	menu->CreateMenu();

	TraceAnalyzer *analyzer;
	POSITION pos = analyzerList.GetHeadPosition();
	while(pos != NULL)
	{
		analyzer = (TraceAnalyzer *)analyzerList.GetNext(pos);

		if (analyzer->WorkWithTraceType(type))
		{
			int id = analyzer->GetMessageID();
			CString text = analyzer->GetTextLabel();
			menu->AppendMenu(MF_STRING, id, text);
		}
	}

	return menu;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void TraceAnalyzerRegistry::Analyze(CChildFrame *parent, int indexOfTrace, int nID)
{
	TraceAnalyzer *analyzer;
	POSITION pos = analyzerList.GetHeadPosition();
	while(pos != NULL)
	{
		analyzer = (TraceAnalyzer *)analyzerList.GetNext(pos);

		if (analyzer->GetMessageID() == nID)
		{
			analyzer->RunAnalyzer(parent, indexOfTrace);
		}
	}
}
//##########################################################################
//#######################    TraceAnalyzer
//##########################################################################

Logical
	TraceAnalyzer::WorkWithTraceType(int type)
{
	int count;
	int *array = GetAvailableTraces(count);

	if (count == 0)
	{
		return False;
	}

	for (int i = 0; i < count; ++i)
	{
		if (array[i] == type)
		{
			return TRUE;
		}
	}

	return False;
}

//##########################################################################
//#######################    OnOffAnalyzer   
//##########################################################################

OnAnalyzer::OnAnalyzer()
{
	textLabel = "On";

	compatableTracesCount = 5;
	compatableTraces = new int [compatableTracesCount];
	compatableTraces[0] = CLabRatDoc::LogicalTraceType;
	compatableTraces[1] = CLabRatDoc::IntegerTraceType;
	compatableTraces[2] = CLabRatDoc::ScalarTraceType;
	compatableTraces[3] = CLabRatDoc::ReceiverMessageTraceType;
	compatableTraces[4] = CLabRatDoc::DefaultTraceType;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void 
	OnAnalyzer::RunAnalyzer(CChildFrame *parent, int indexOfTrace)
{


	// if the trace is selected then toggle all the selected traces
	// on

	// if not only do it the menued trace

	
	TraceLine *trace_line;
	trace_line = (TraceLine *)parent->traceListArray->GetAt(indexOfTrace);
	
	if (trace_line->selected)
	{

	
		for (int i = 0; i < parent->traceCount; ++i)
		{
			trace_line = (TraceLine *)parent->traceListArray->GetAt(i);
			if (trace_line->selected)
			{
				trace_line->on = True;
			}
		}
	}
	else
	{
		trace_line->on = True;
	}

	parent->Draw(parent->nameView);
	parent->Draw(parent->logicView);
}


//##########################################################################
//#######################    OnOffAnalyzer   
//##########################################################################

OffAnalyzer::OffAnalyzer()
{
	textLabel = "Off";

	compatableTracesCount = 5;
	compatableTraces = new int [compatableTracesCount];
	compatableTraces[0] = CLabRatDoc::LogicalTraceType;
	compatableTraces[1] = CLabRatDoc::IntegerTraceType;
	compatableTraces[2] = CLabRatDoc::ScalarTraceType;
	compatableTraces[3] = CLabRatDoc::ReceiverMessageTraceType;
	compatableTraces[4] = CLabRatDoc::DefaultTraceType;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void 
	OffAnalyzer::RunAnalyzer(CChildFrame *parent, int indexOfTrace)
{


	TraceLine *trace_line;
	trace_line = (TraceLine *)parent->traceListArray->GetAt(indexOfTrace);
	
	if (trace_line->selected)
	{
		for (int i = 0; i < parent->traceCount; ++i)
		{
			trace_line = (TraceLine *)parent->traceListArray->GetAt(i);
			if (trace_line->selected)
			{
				trace_line->on = False;
			}
		}
	}
	else
	{
		trace_line->on = False;
	}

	parent->Draw(parent->nameView);
	parent->Draw(parent->logicView);
}


//##########################################################################
//#######################    LogicalAnalyzer   
//##########################################################################

LogicalAnalyzer::LogicalAnalyzer()
{
	textLabel = "Logical Analyzer";

	compatableTracesCount = 1;
	compatableTraces = new int [compatableTracesCount];
	compatableTraces[0] = CLabRatDoc::LogicalTraceType;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void 
	LogicalAnalyzer::RunAnalyzer(CChildFrame *parent, int indexOfTrace)
{
	TraceLine *trace_line;
	trace_line = (TraceLine *)parent->traceListArray->GetAt(indexOfTrace);
	
	AnalyzeBox *box = new AnalyzeBox;
	box->Create(IDD_MESSAGE_BOX, parent->GetParent());

	Logical fake_selection = False;
	if (!trace_line->selected)
	{
		trace_line->selected = True;
		fake_selection = True;
	}
	
	Time start_time = parent->viewedTime.startTimeSel;
	Time end_time = parent->viewedTime.endTimeSel;

	if (start_time == end_time)
	{
		CLabRatDoc *document = (CLabRatDoc *)parent->logicView->GetDocument();

		end_time =  document->lastTrace;
		start_time = document->firstTrace;
	}
	
	char temp[60];
	char time[60];
	sprintf(time, "%8.4fs", (parent->viewedTime.startTimeSel));
	strcpy(temp, time);
	
	CString str;
	str = "StartSel : ";
	str += temp;
	str += "  ";
	sprintf(time, "%8.4fs", (parent->viewedTime.endTimeSel));
	strcpy(temp, time);
	
	str += "EndSel : ";
	str += temp;
	str += "  ";
	sprintf(time, "%8.4f", (fabs(parent->viewedTime.endTimeSel-parent->viewedTime.startTimeSel)) / SCALES[parent->viewedTime.secondEnum]);
	strcpy(temp, time);
	strcat(temp, SCALES_TEXT[parent->viewedTime.secondEnum]);
	str += "TotalTimeSelected : ";
	str += temp;


	Time grand_total_time_up = 0.0f;
	Time grand_total_time_down = 0.0f;
	double grand_total_percent_up = 0.0f;
	double grand_total_percent_down = 0.0f;




	box->AddString("Time Analyzed");
	box->AddString("-----------------------------");
	box->AddString(str);

	for (int i = 0; i < parent->traceCount; ++i)
	{
		trace_line = (TraceLine *)parent->traceListArray->GetAt(i);
		if (trace_line->selected)
		{
			if (WorkWithTraceType(trace_line->GetTraceType()))
			{
				AnalyzeTrace(parent, box, trace_line, start_time, end_time, grand_total_time_up);
			}
		}
	}


	Time total_time = end_time - start_time;

	grand_total_time_down = total_time - grand_total_percent_up;
	
	if (total_time != 0.0f)
	{
		grand_total_percent_up = grand_total_time_up / total_time;
	}
	else
	{
		grand_total_time_up = 0.0f;
	}
	grand_total_percent_up *= 100;
	grand_total_percent_down = 100.0f - grand_total_percent_up;


	box->AddString("");
	box->AddString("");
	box->AddString("Total Activities Summary");
	box->AddString("-----------------------------");

	str.Format("Time High : %f%s : Time Low :%f%s ",
		(fabs(grand_total_time_up)) / SCALES[parent->viewedTime.secondEnum],
		SCALES_TEXT[parent->viewedTime.secondEnum],
		(fabs(grand_total_time_down)) / SCALES[parent->viewedTime.secondEnum],
		SCALES_TEXT[parent->viewedTime.secondEnum]
	);
	box->AddString(str);

	str.Format("Percent High : %f : Percent Low :%f ", grand_total_percent_up, grand_total_percent_down);
	box->AddString(str);




	if (fake_selection)
	{
		trace_line = (TraceLine *)parent->traceListArray->GetAt(indexOfTrace);
		trace_line->selected = False;
	}


}

//-------------------------------------------------------------------------------
//-------------------------------------------------------------------------------

void
	LogicalAnalyzer::AnalyzeTrace(
		CChildFrame *parent, 
		AnalyzeBox *box, 
		TraceLine *trace_line, 
		Time start_time, 
		Time end_time,
		Time &grand_total_time_up
	)
{
	CString str;
	box->AddString("");
	box->AddString("");
	box->AddString(trace_line->traceName);
	box->AddString("-----------------------------");
	str.Format("Overall Trace Activity Count  = %d", trace_line->dataHolder->traceEntryCount);
	box->AddString(str);

	int counter = 0;

	Time last_trace_time = start_time;

	Time total_time = end_time - start_time;


	Time total_time_up = 0.0f;


	int traces_high = 0;
	int traces_low = 0;

	for (int i = 0; i < trace_line->dataHolder->traceEntryCount; ++i)
	{
		Time time_of_trace;
		ToggleTraceStorage *trace_element = (ToggleTraceStorage *)
				TraceStorage::FindElement(trace_line->dataHolder, i);
		
		time_of_trace = trace_element->GetTraceTime();
	
		if ((time_of_trace >= start_time) && (time_of_trace < end_time))
		{
			int trace_position = trace_element->GetPosition();
			
			if (trace_position == CLabRatDoc::GoingUpFlag)
			{
				total_time_up += (time_of_trace - last_trace_time);
				++traces_high;
			}

			last_trace_time = time_of_trace;

			++counter;
		}
	}
	
	traces_low = counter - traces_high;

	Time total_time_down = total_time - total_time_up;
	double percent_time_up;
	double percent_time_down;


	if (total_time != 0.0f)
	{
		percent_time_up = total_time_up / total_time;
	}
	else
	{
		percent_time_up = 0.0f;
	}

	percent_time_up *= 100;
	percent_time_down = 100.0f - percent_time_up;

	str.Format("Total Trace Activity Analysed Count : %d", counter);
	box->AddString(str);


	str.Format("Rising Edge : %d : Falling Edge :%d ", traces_high, traces_low);
	box->AddString(str);


	str.Format("Time High : %f%s : Time Low :%f%s ",
		(fabs(total_time_up)) / SCALES[parent->viewedTime.secondEnum],
		SCALES_TEXT[parent->viewedTime.secondEnum],
		(fabs(total_time_down)) / SCALES[parent->viewedTime.secondEnum],
		SCALES_TEXT[parent->viewedTime.secondEnum]
	);

	//str.Format("Time High : %f \t Time Low :%f ", total_time_up, total_time_down);
	box->AddString(str);

	str.Format("Percent High : %f : Percent Low :%f ", percent_time_up, percent_time_down);
	box->AddString(str);

	grand_total_time_up += total_time_up;


}






