/*! \page pageAddANewProblem How to add a new kind of problem

Tools based on OMOptimBasis can be extended in different ways. This document illustrates how to add a new kind of problem.

To add your own kind of problem, one should procede in several steps :

- create MyProblem class, inheriting Problem
- create MyResult class, inheriting Result
- create MyProblemInterface class, inheriting ProblemInterface.

Please note that sometimes, MyResult could be similar to an existing result (e.g. OptimResult). In that case, you don't need to create a new class.

\section sec1 Create MyProblem class
MyProblem should inherit Problem class.

\code
class MyProblem : public Problem
{
}
\endcode

Then, one should implement needed functions (Problem is an abstract class).

\subsection secLaunch Computation function
The most important function is MyProblem::launch(...): it defines the computation of the problem. Launch function should return a pointer to a Result inheriting instance. It may also return a NULL pointer if problem failed. In that case, one can also return a Result instance whose function isSuccess() returns false.

\code
Result* MyProblem::launch(ProblemConfig config)
{
	// your computation code
}
\endcode

\subsection ssec1	Other functions 
\code
// toXmlData function is used to save problem in a xml file (and thus to be reloaded).
virtual QDomElement toXmlData(QDomDocument & doc)
{
	QDomElement cProblem = doc.createElement(getClassName());

	...
	
	return cProblem;
}
\endcode

\section sec2 Create MyProblemInterface class
ProblemInterface is used by Project class to manage problems (cf. \ref pageProblemInterface). MyProblemInterface should implement next functions :




\code
   Problem* MyProblemInterface::createNewProblem(ProjectBase* projectBase,const QStringList modelsList,QString problemType)
{
	if(problemType==MyProblem::className()) // security check
		return new MyProblem(project);	
	else
		return NULL;		
}

// Graphical user interface functions

QWidget* MyProblemInterface::createProblemTab(Problem * problem,QWidget* parent)
{
    OneSimulation* oneSim = dynamic_cast<OneSimulation*>(problem);
    return new TabOneSim(oneSim,parent);
}


QWidget* MyProblemInterface::createResultTab(Result* result,QWidget* parent)
{
    OneSimResult* oneSimResult = dynamic_cast<OneSimResult*>(result);
    return new TabResOneSim(oneSimResult,parent);
}

// save/loading functions

Problem* MyProblemInterface::loadProblem(QFileInfo saveFile,const QDomElement & domOMCase, ProjectBase * projectBase)
{
    if(domOMCase.isNull() || domOMCase.tagName()!="OMCase" )
        return NULL;

    QDomElement domOMProblem = domOMCase.firstChildElement("OMProblem");

    Problem* problem = NULL;
    bool ok = true;

    QDomElement domProblem = domOMProblem.firstChildElement(MyProblem::className());
    problem = new MyProblem(domProblem,projectBase,ok);

    if(!ok)
    {
        delete problem;
        problem = NULL;
    }
    else
    {
        problem->setEntireSavePath(saveFile.absoluteFilePath());
    }

    return problem;
}


Result* MyProblemInterface::loadResult(QFileInfo saveFile,const QDomElement & domOMCase, ProjectBase * projectBase)
{
    if(domOMCase.isNull() || domOMCase.tagName()!="OMCase" )
        return NULL;

    // read problem
    bool ok;
    QDomElement domOMProblem = domOMCase.firstChildElement("OMProblem");
    QDomElement domProblem = domOMProblem.firstChildElement(MyProblem::className());
    MyProblem problem(domProblem,projectBase,ok);

    if(!ok)
    {
        InfoSender::instance()->send( Info(ListInfo::RESULTFILECORRUPTED,saveFile.filePath()));
        return NULL;
    }

    // create result
    QDomElement domOMResult = domOMCase.firstChildElement("OMResult");
    QDomElement domResult = domOMResult.firstChildElement(MyResult::className());
    Result* result = new MyResult(projectBase,domResult,problem,ok);

    if(!result)
    {
        InfoSender::instance()->send( Info(ListInfo::RESULTFILECORRUPTED,saveFile.filePath()));
        return NULL;
    }
	else
    {
        // attribute file path to result
        result->setEntireSavePath(saveFile.filePath());
    }

    return result;
}

\endcode
	
 **/
