/* 
 * Tactic is the legal property of its developers, whose names are too numerous 
 * to list here.  Please refer to the COPYRIGHT file distributed with this 
 * source distribution. 
 * 
 * This library is free software; you can redistribute it and/or 
 * modify it under the terms of the GNU Lesser General Public 
 * License as published by the Free Software Foundation; either 
 * version 2.1 of the License, or (at your option) any later version. 
 * 
 * This library is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
 * Lesser General Public License for more details. 
 * 
 * You should have received a copy of the GNU Lesser General Public 
 * License along with this library; if not, write to the Free Software 
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
 *
 * See README for more informations
 *
 * InferenceEngine.cpp
 *
 * ...
 * Date 02/03/06
 *
 */

#include "InferenceEngine.h"
#include "FvEvaluation.h"
#include "DebugAI.h"

using namespace std;

InferenceEngine::InferenceEngine(void){
	FuzzyValue* fvtemp = new FuzzyValue(VALUE_LIST_RESULT_EMPTY, -1);
	listResult.push_back(*fvtemp);
	result = FuzzyValue(VALUE_INFERATE_NOT_USED, -1);
	vectorSize = listResult.size();
	hash = 0;		// Need to put the pointer to 0 for the first time we used this.inferate()
	values = 0;		// same
	length = 0;		// same
}

InferenceEngine::~InferenceEngine(void){
	delete[vectorSize] values;
	delete[vectorSize] hash;
	delete[vectorSize] length;
}

void InferenceEngine::inferate (std::vector<FuzzyRule>* theFuzzyRules){
		// free the values, hash and length pointer
		delete[vectorSize] values;
		delete[vectorSize] hash;
		delete[vectorSize] length;
	
		// Initialise listResult
		listResult.clear();
		
		vectorSize = theFuzzyRules->size(); // Length of the list of FuzzyRules
		// cout << "Nombre de fuzzyRules : " << vectorSize << '\n';
		hash = new fuzzyValueName[vectorSize]; // Contains each FuzzyValue name
		values = new float[vectorSize];		// Contains the values of FuzzyValues
		length = new int[vectorSize];		// Countain the number of occurence of each fuzzy value
		
		// Clear the previous possible result
		result.setValue(-1);
		
		// Initialise the board to 0
		for(int i=0; i < vectorSize; i++){
			length[i] = 0;
			values[i] = 0;
		}
		
		// Evaluate the FuzzyValues result and the create a list with them 
		for(int i=0; i < vectorSize; i++){
			FuzzyRule tmpRule = theFuzzyRules->at(i);
			// The FuzzyRule which is evaluated.
			tmpRule.evaluate();
			// System.out.println(tmpRule.toString());
			
			int index = 0;
			bool found = false;
			while((index < vectorSize) && !found){
				if(tmpRule.getResult().getName() == (hash[index]) || length[index] == 0){
					
					//cout << "comparaison : " << tmpRule.getResult().getName() << "\n";
					//cout << "case parcourue : " << index << "\n";
					//cout << "nom de la valeur floue parcourue dans le tableau : ";
					//cout << tmpRule.getResult().getName() << '\n';
					//cout << "nom de la valeur floue a inserer dans le tableau : ";
					//cout << '\n';
					
					hash[index] = tmpRule.getResult().getName();
					values[index] += tmpRule.getResult().getValue();
					length[index] += 1;
					found = true;
				}
				index++;
			}
		}
		
		
		for(int i=0; (i < vectorSize) && (length[i] != 0); i++){
			values[i] = values[i]/length[i];
			// Calculate the average
			listResult.push_back(FuzzyValue(hash[i], values[i]));

			// Put the FuzzyValues in listResult
			if(result.getValue() < values[i]){
				// System.out.println("Passe pas par la");
				result = FuzzyValue(hash[i], values[i]);
			}
		}
		vectorSize = listResult.size();		
	DebugAI::trace('e',toString() );
}

FuzzyValue InferenceEngine::getResult(){
	if (result.getValue() < MIN_RESULT_VALUE) {
		return FvEvaluation();
	}
	return result;
}

std::vector<FuzzyValue> InferenceEngine::getAllResult(){
	return listResult;
}

std::string InferenceEngine::toString(){
	std::string myInfEngine;
	myInfEngine = "Set of FuzzyValues result :";
	myInfEngine += '\n';
	for(int i = 0; i < vectorSize; i++){
		myInfEngine += '\t';
		myInfEngine += listResult.at(i).toString();
		myInfEngine += '\n';
	}
	myInfEngine = myInfEngine + '\t' + "Best result :";
	myInfEngine += '\n';
	myInfEngine += '\t';
	myInfEngine += result.toString();
	myInfEngine += '\n';
	myInfEngine += '\t';
	myInfEngine += "Number of results : ";
	myInfEngine += Converter::floatToString(vectorSize);
	myInfEngine += '\n';
	return myInfEngine;
}
