/* ----------------------------------------------------------------------- *
 *                                                                         *
 *    (C) Copyright 1997 by:  aiNet                                        *
 *										Trubarjeva 42                                *
 *                            SI-3000 Celje                                *
 *										Europe, Slovenia                             *
 *     All Rights Reserved                                                 *
 *                                                                         *
 *     Subject: C code for a hole in the square problem.                   *
 *     File:    T4RUNTIM - Hole int the square - dynamic binding           *
 *                                                                         *
 * ----------------------------------------------------------------------- */

/*
 * This file assumes that ainetxx.dll will be loaded at run time,
 * which is default option and no flags need to be defined.
 * ainetxx.lib must NOT be included in the linking process.
 */
#include "ainetdll.h"

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h> /* This is Borland specific header.      */
                   /* It is used for getch() function only. */

/*
 * Path and the filename of dll which will be loaded.
 */

#if defined(__WIN32__)
const char ainetDll[] = "ainet32.dll";
#else
const char ainetDll[] = "ainet16.dll";
#endif
/*
 * Pointers to ainet dll functions. They are made global - all functions
 * can use them.
 */

t_aiRegistration              aiRegistration;
t_aiGetVersion                aiGetVersion;
t_aiCreateModel               aiCreateModel;
t_aiCreateModelFromCSVFile    aiCreateModelFromCSVFile;
t_aiDeleteModel               aiDeleteModel;
t_aiNormalize                 aiNormalize;
t_aiDenormalize               aiDenormalize;
t_aiPrediction                aiPrediction;
t_aiGetNumberOfVariables      aiGetNumberOfVariables;
t_aiGetNumberOfModelVectors   aiGetNumberOfModelVectors;
t_aiGetNumberOfInputVariables aiGetNumberOfInputVariables;
t_aiSetDiscreteFlag           aiSetDiscreteFlag;
t_aiGetDiscreteFlag           aiGetDiscreteFlag;
t_aiSetVariable               aiSetVariable;
t_aiGetVariable               aiGetVariable;
t_aiGetVariableVB             aiGetVariableVB;
t_aiGetCSVFileModelSize       aiGetCSVFileModelSize;
// New in version 1.24
t_aiSetCapacity					aiSetCapacity;
t_aiGetCapacity					aiGetCapacity;
t_aiGetFreeEntries				aiGetFreeEntries;
t_aiInsertModelVector			aiInsertModelVector;
t_aiOverwriteModelVector		aiOverwriteModelVector;
t_aiAppendModelVector			aiAppendModelVector;
t_aiDeleteModelVector			aiDeleteModelVector;
t_aiPredictionEx					aiPredictionEx;
t_aiExcludeModelVector			aiExcludeModelVector;
t_aiExcludeModelVectorRange	aiExcludeModelVectorRange;
t_aiIsModelVectorExcluded		aiIsModelVectorExcluded;
t_aiSaveCSVFile					aiSaveCSVFile;


/*
 *  ainet32.dll module variable.
 */

HINSTANCE hLib;

/*
 *  The load_aiNetLibrary() function is implemented below.
 *  This function will load ainet32.dll and define pointers to
 *  ainet functions.
 */

int load_aiNetLibrary(void);

/*
 * #########################################################################
 */

void main()
{
	/*
	 * Please, see the manual (Part 1, Chapter 2.3) for more details about a
	 * hole in the square problem.
	 */

	int i;
   int counter;
   int loop;
	int version;
   int outcome;
	aiModel* model;
   float x,y;
   int mvIndex[5];

   /* Let us define 6 vectors to be predicted.
    * This definitely not enough for a good test set. However, this
    * is just an example how to use aiNet.DLL library. You can
    * construct a larger if you like.

    * Test points were selected near the 'border'. One half of the set
    * lies slightly inside - in the hole, and the other half of the
    * set lies slightly outside - in the square.
    *       +-------+--------+-------+-------+--------+
    *       |   Fi  |   R    |   X   |   Y   | IN/OUT |
    *       +-------+--------+-------+-------+--------+
    *    1  |    0  |  0.75  | 0.750 | 0.000 |  OUT   |
    *    2  |   60  |  0.65  | 0.325 | 0.563 |  IN    |
    *    3  |  120  |  0.75  |-0.375 | 0.650 |  OUT   |
    *    4  |  180  |  0.65  |-0.650 | 0.000 |  IN    |
    *    5  |  240  |  0.75  |-0.375 |-0.650 |  OUT   |
    *    6  |  300  |  0.65  | 0.325 |-0.563 |  IN    |
    *       +-------+--------+-------+-------+--------+
    */
	float predict[6][3] = { { 0.750, 0.000, 999 },  /* vectors to be predicted */
									{ 0.325, 0.563, 999 },
									{-0.375, 0.650, 999 },
									{-0.650, 0.000, 999 },
									{-0.375,-0.650, 999 },
									{ 0.325,-0.563, 999 } };
   /*
    * Load DLL
    */
   if( !load_aiNetLibrary() ) {
		exit(EXIT_FAILURE);
	}
   
	/*
	 * Print out the title
	 */
	version = aiGetVersion();
	printf( "\naiNetDLL version %i.%i! (C) Copyright by aiNet, 1997",
			  version/100, version%100 );
	printf( "\n---------------------------------------------------\n" );

	/*
	 * Register DLL
	 */
	aiRegistration( "Your registration name", "Your code" );

	/*
	 * Setup the model. We will start with 10 model vectors. They will be
    * generated using random number generator.
	 */
	model = aiCreateModel(10,3,2);
	if(!model) {
		printf( "\nError: Something went wrong during model creation!" );
		exit(EXIT_FAILURE);
	}

   /* Let us generate initial model vectors */
   randomize();
   for(i=1; i<=10; i++) {
   	float inside;
   	x = (float)((random(2000)-1000))/1000.0;
   	y = (float)((random(2000)-1000))/1000.0;

      if ( (x*x + y*y - 0.490) <= 0.0 )
      	inside = 1.0;
   	else
      	inside = 0.0;

      aiSetVariable(model,i,1,x);
      aiSetVariable(model,i,2,y);
      aiSetVariable(model,i,3,inside);
   }

	/*
	 * Output the model
	 */

	printf( "\n             Model name: aiNet DLL test 4 (Hole in the square)" );
	printf( "\nNumber of model vectors: %i", aiGetNumberOfModelVectors(model));
	printf( "\n    Number of variables: %i", aiGetNumberOfVariables(model));
	printf( "\n         Variable names: X,   Y,   IN(1)/OUT(0)" );
	printf( "\n          Discrete flag: %i,   %i,   %i",
			  aiGetDiscreteFlag(model,1),
			  aiGetDiscreteFlag(model,2),
			  aiGetDiscreteFlag(model,3) );
	for( i=1; i<=aiGetNumberOfModelVectors(model); i++ ) {
		printf( "\n\t\t\t % 5.3f, % 5.3f, % 5.3f",
				  aiGetVariable(model, i,1),
				  aiGetVariable(model, i,2),
				  aiGetVariable(model, i,3) );
	}

	/* This loop will be repeated 7 times                        */
   /* Each time new model vectors will be added to the problem. */

	for(loop=0; loop<7; loop++) {
   	int oldSize;
		/*
		 * Normalize the model
		 */
		aiNormalize(model,NORMALIZE_REGULAR);

		/*
		 * Prediction: Pen. coefficient = 0.30, Pen. method = STATIC
		 * This test has static penalty coefficient 0.30
		 */

		printf( "\n\n  Penalty coefficient: 0.15" );
		printf(   "\n       Penalty method: STATIC" );
		printf(   "\n\t X(inp), Y(inp), IN/OUT (out)" );
		counter = 0;
		for ( i=0; i<6; i++ ) {
      	int inside;
         int j;
         /* TRUE stands for most influent MV */
			aiPredictionEx( model, predict[i], 0.15, PENALTY_STATIC, mvIndex, 5, TRUE );
			printf( "\n    % 7.4f, % 7.4f, % 7.4f",
					  predict[i][0],predict[i][1],predict[i][2] );
         inside = predict[i][2] >= 0.5;
	      if( inside )
   	   	printf( " IN " );
      	else
      		printf( " OUT" );
	      if( inside == i%2 ) {
   	   	printf( " PASSED" );
      	   counter++;
	      }
   	   else {
      		printf( " FAILED" );
	      }
         printf( " Most inf. MVs: " );
         for( j=0; j<5; j++ ) {
         	printf( "%i", mvIndex[j] );
            if(j!=4) printf(", ");
         }
		}
	   printf( "\n\t%i Correct predictions (%3.2f)!", counter, counter/6.0*100.0 );
      printf( "\nPress any key to continue!" );
	   getch();

		/*
		 * Denormalize the model!
   	 * We must do that, because new model vectors will be added to the model.
		 */
		aiDenormalize(model);

      /*
       * Each time, 100 new model vectors will be added to the model
       */
		oldSize = aiGetCapacity(model);
		outcome = aiSetCapacity(model,oldSize+100);
      if(outcome < 0) {
			printf( "\nError: Something went wrong during capacity call!" );
			exit(EXIT_FAILURE);
      }

      for(i=0; i<100; i++) {
      	float newModelVector[3];
	   	float inside;
   		x = (float)((random(2000)-1000))/1000.0;
   		y = (float)((random(2000)-1000))/1000.0;

	      if ( (x*x + y*y - 0.490) <= 0.0 )
   	   	inside = 1.0;
   		else
      		inside = 0.0;

	      newModelVector[0] = x;
	      newModelVector[1] = y;
	      newModelVector[2] = inside;
         outcome = aiAppendModelVector(model,newModelVector);
	      if(outcome < 0) {
				printf( "\nError: Appending new model vector failure!" );
				exit(EXIT_FAILURE);
	      }
      }
   }

	/*
    * Finally we will use other new functions. There is no particular
    * reason for their use. We will use them for demonstration purposes only!
    */

    printf( "\n" );
    printf( "\nNumber of model vectors in the model: %i",
    			aiGetNumberOfModelVectors(model));
    printf( "\nCapacity of the model: %i",
    			aiGetCapacity(model));
    printf( "\nFree entries in the model: %i",
    			aiGetFreeEntries(model));

	/*
    * Before we can save the model, the model must be denormalized in order
    * to restore initial model values.
    */

	aiSaveCSVFile(model,"Test.csv");
	/*
	 * We must call the aiDeleteModel function here since the model
	 * was allocated dynamicaly using the aiCreateModelFromCSVFile function.
	 */
	aiDeleteModel(model);

   model = aiCreateModelFromCSVFile("Test.csv");
   aiDeleteModel(model);

	printf( "\n\nEnd." );
   getch();
	exit(EXIT_SUCCESS);
}

/*
 *  This function binds AINET.DLL with function prototypes.
 */

int load_aiNetLibrary()
{
   /*
    * Load the Dynamic Link Library AINET32.DLL
    */

   hLib = LoadLibrary(ainetDll);
   if((unsigned)hLib<=HINSTANCE_ERROR){
      char bfr[40];
      wsprintf(bfr, "Failure loading library: %s", ainetDll);
      MessageBox(NULL, bfr, "Error", MB_OK|MB_APPLMODAL);
      return 0;
   }

   /*
    * Get all the entry points for the functions in ainet32.dll
    */

	aiRegistration              = (t_aiRegistration)              GetProcAddress(hLib, "aiRegistration");
   aiGetVersion                = (t_aiGetVersion)                GetProcAddress(hLib, "aiGetVersion");
   aiCreateModel               = (t_aiCreateModel)               GetProcAddress(hLib, "aiCreateModel");
   aiCreateModelFromCSVFile    = (t_aiCreateModelFromCSVFile)    GetProcAddress(hLib, "aiCreateModelFromCSVFile");
   aiDeleteModel               = (t_aiDeleteModel)               GetProcAddress(hLib, "aiDeleteModel");
   aiNormalize                 = (t_aiNormalize)                 GetProcAddress(hLib, "aiNormalize");
   aiDenormalize               = (t_aiDenormalize)               GetProcAddress(hLib, "aiDenormalize");
   aiPrediction                = (t_aiPrediction)                GetProcAddress(hLib, "aiPrediction");
   aiGetNumberOfVariables      = (t_aiGetNumberOfVariables)      GetProcAddress(hLib, "aiGetNumberOfVariables");
   aiGetNumberOfModelVectors   = (t_aiGetNumberOfModelVectors)   GetProcAddress(hLib, "aiGetNumberOfModelVectors");
   aiGetNumberOfInputVariables = (t_aiGetNumberOfInputVariables) GetProcAddress(hLib, "aiGetNumberOfInputVariables");
   aiSetDiscreteFlag           = (t_aiSetDiscreteFlag)           GetProcAddress(hLib, "aiSetDiscreteFlag");
   aiGetDiscreteFlag           = (t_aiGetDiscreteFlag)           GetProcAddress(hLib, "aiGetDiscreteFlag");
   aiSetVariable               = (t_aiSetVariable)               GetProcAddress(hLib, "aiSetVariable");
   aiGetVariable               = (t_aiGetVariable)               GetProcAddress(hLib, "aiGetVariable");
   aiGetVariableVB             = (t_aiGetVariableVB)             GetProcAddress(hLib, "aiGetVariableVB");
   aiGetCSVFileModelSize       = (t_aiGetCSVFileModelSize)       GetProcAddress(hLib, "aiGetCSVFileModelSize");
   aiSetCapacity               = (t_aiSetCapacity)               GetProcAddress(hLib, "aiSetCapacity");
   aiGetCapacity               = (t_aiGetCapacity)               GetProcAddress(hLib, "aiGetCapacity");
   aiGetFreeEntries            = (t_aiGetFreeEntries)            GetProcAddress(hLib, "aiGetFreeEntries");
   aiInsertModelVector         = (t_aiInsertModelVector)         GetProcAddress(hLib, "aiInsertModelVector");
   aiOverwriteModelVector      = (t_aiOverwriteModelVector)      GetProcAddress(hLib, "aiOverwriteModelVector");
   aiAppendModelVector         = (t_aiAppendModelVector)         GetProcAddress(hLib, "aiAppendModelVector");
   aiDeleteModelVector         = (t_aiDeleteModelVector)         GetProcAddress(hLib, "aiDeleteModelVector");
   aiPredictionEx              = (t_aiPredictionEx)              GetProcAddress(hLib, "aiPredictionEx");
   aiExcludeModelVector        = (t_aiExcludeModelVector)        GetProcAddress(hLib, "aiExcludeModelVector");
   aiExcludeModelVectorRange   = (t_aiExcludeModelVectorRange)   GetProcAddress(hLib, "aiExcludeModelVectorRange");
   aiIsModelVectorExcluded     = (t_aiIsModelVectorExcluded)     GetProcAddress(hLib, "aiIsModelVectorExcluded");
   aiSaveCSVFile               = (t_aiSaveCSVFile)               GetProcAddress(hLib, "aiSaveCSVFile");

   /*
    * GetProcAddress returns null on failure
    */
   if( aiRegistration == NULL
       || aiGetVersion == NULL
       || aiCreateModel == NULL
       || aiCreateModelFromCSVFile == NULL
       || aiDeleteModel == NULL
       || aiNormalize == NULL
       || aiDenormalize == NULL
       || aiPrediction == NULL
       || aiGetNumberOfVariables == NULL
       || aiGetNumberOfModelVectors == NULL
       || aiGetNumberOfInputVariables == NULL
       || aiSetDiscreteFlag == NULL
       || aiGetDiscreteFlag == NULL
       || aiSetVariable == NULL
       || aiGetVariable == NULL
       || aiGetVariableVB == NULL
       || aiGetCSVFileModelSize == NULL
		 || aiSetCapacity == NULL
       || aiGetCapacity == NULL
       || aiGetFreeEntries == NULL
       || aiInsertModelVector == NULL
       || aiOverwriteModelVector == NULL
       || aiAppendModelVector == NULL
       || aiDeleteModelVector == NULL
       || aiPredictionEx == NULL
       || aiExcludeModelVector == NULL
       || aiExcludeModelVectorRange == NULL
       || aiIsModelVectorExcluded == NULL
       || aiSaveCSVFile == NULL ) {
		MessageBox(NULL, "Failure locating procedures.", "Error",
            MB_OK|MB_APPLMODAL);
      return 0;
	}
   return 1;
}

/* THE END */
