// UTS 2000 - Fichier 'selectif.cpp' Lecture des variables pour la conduite en mode sélectif dans le fichier de configuration, 
// et gestion de ce mode - 
// V3.7c - Le 30/09/2016
/*****************************************************************************/
/* Début SELECTIF                                                            */
/*****************************************************************************/
#include  <windows.h>
#include  <string.h>
#include  <stdlib.h>
#include  <stdio.h>
#include "Train_UTS.h"
#include "selectif.h"
#include "canton.h"
#include "train.h"

#define _CRT_SECURE_NO_WARNINGS  // Limite les messages de warning dans Visual C++

// Déclaration des fonctions externes
extern cCanton  canton;
extern cTrain   train;
extern void EasyTextOut(int , int , char* );
extern void EasyLine(int, int, int, int);


// Déclaration des variables externes
extern HDC     hMemDC;
extern HFONT   bmp_fonte;
extern HPEN    bmp_stylo_noir, bmp_stylo_gris128, bmp_stylo_gris192, bmp_stylo_blanc, bmp_stylo_gris192, bmp_stylo_jaune;
extern HBRUSH  bmp_pinceau_blanc, bmp_pinceau_gris192, bmp_pinceau_gris220, bmp_pinceau_jaune;
extern int screen_mode;
extern int touche_char;

extern int vio_det[NB_CARTE][NB_CANTON];
extern int vio_aig_pos0[NB_AIG];
extern int vio_aig_pos1[NB_AIG];
extern int nb_selectif_lus;	// Pour connaitre le nombre de terme Cx:+- lus dans la partie '#selectif' de 'config.txt' pour ne pas dépasser la limite de 100.
extern int cfg_tempo_libe_cant; // 0 à 99 = Temporisation pour libérer un canton. Valeur lue dans 'config.txt'.
extern int x_mouse,y_mouse, screen_mode_retour;

//
cSelectif selectif;

//
cSelectif::cSelectif(void)
{
	check_aig=0;
}

//
void cSelectif::init(char filename[])
/* Lecture du fichier 'config.txt'. Lecture de la section '#selectif' pour connaitre le rattachement des cantons les uns aux autres.
  #selectif
  [
  c6:+ c7-    c6:- c0+ a0.1      c6:- c1- a0.0 a1.0       c6:- c2- a0.0 a1.1
  ]

Cette ligne est convertie dans le tableau descr[][].
  'c6:+ c7-'        => descr[0][ 6, 0, 7, 1, -1, -1, -1, -1, -1...]
                                c6  + c7  -
  'c6:- c0+ a0.1'   => descr[0][ 6, 1, 0, 0,  0   1, -1, -1, -1...]
                                c6  -  c0 +  a0   1

int descr[NB_SELECTIF][IND_SELECTIF_TAILLE];  // [Nombre maxi de terme 'Cx:' dans la partie '#selectif' de 'config.txt'][Cx:(+-) Cy(+-) suivi de 6 aiguillages maxi ].

Ce programme rempli le tableau suivant : 
  descr[nb][IND_CANT_COUR_NUM]        = Numéro du canton courant = 'X' de 'cX:'
  descr[nb][IND_CANT_COUR_SENS]       = Sens de parcours '0' si 'cX:+' ou '1' si 'cX:-'
  descr[nb][IND_CANT_PREC_NUM]        = 'X' de 'cX'
  descr[nb][IND_CANT_PREC_SENS]       = '0' si 'cX+'  ou '1' si 'cX-'
  descr[nb][IND_AIG_NUM_BASE+2*i_aig] = Numéro d'aiguillage = 'X' de 'aX'
  descr[nb][IND_AIG_POS_BASE+2*i_aig] = Position de l'aiguillage = 'Y' de 'aX.Y'

*/
{
	FILE* pf;
	char ch[CHAR_CONFIG_NB];
	char c,c1,c2;
	int  i,j,i_aig;
	int  nb,aig,pos,cant,cant_base,sens_base;
	for (j=0; j<NB_SELECTIF; j++) {
		for(i=0; i<IND_SELECTIF_TAILLE; i++) descr[j][i]=-1;
	}
	nb=-1;
	if ((pf=fopen(filename,"rt"))==NULL) {
		MessageBox(NULL,"Impossible d'ouvrir le fichier de configuration du selectif","Erreur",MB_OK|MB_ICONERROR);	exit(1);
	}
	while(fscanf(pf," %c",&c)!=EOF){
		if (c=='@') {
			do{ if(fscanf(pf,"%c",&c)==EOF) break; }while(c!='\n');
			continue;
		}
		if (c=='#') {
			fscanf(pf," %s",ch);
			if (!strcmp(ch,"selectif")) {
				fscanf(pf," %s",ch); // Ignore le caractère '['
				do {
					fscanf(pf," %c",&c);
					if (c=='c') {
						fscanf(pf," %d",&cant); //get canton no
						fscanf(pf,"%c",&c1);    //get : + -
						if (c1==':'){								// 'Cx:'
							nb++;
							cant_base=cant;
							descr[nb][IND_CANT_COUR_NUM]=cant_base;
							i_aig=0;
							fscanf(pf,"%c",&c2);
							if (c2=='-') descr[nb][IND_CANT_COUR_SENS]=sens_base=1;
							if (c2=='+') descr[nb][IND_CANT_COUR_SENS]=sens_base=0;
						}
						else {
							descr[nb][IND_CANT_PREC_NUM]=cant;				// 'Cx'
							if(c1=='-') descr[nb][IND_CANT_PREC_SENS]=1;
							if(c1=='+') descr[nb][IND_CANT_PREC_SENS]=0;
						}
					}
					if (c=='+' || c=='-') {
							nb++;
							descr[nb][IND_CANT_COUR_NUM]=cant_base;
							descr[nb][IND_CANT_COUR_SENS]=sens_base;
							i_aig=0;
					}
					if (nb >= NB_SELECTIF) {  // NB_SELECTIF = 100.
						MessageBox(NULL,"Le fichier 'config.txt' comporte trop de lignes dans la section '#selectif' !","Erreur",MB_OK|MB_ICONERROR);
						MessageBox(NULL,"Pas plus de 100 termes 'Cx :' dans la partie '#selectif' de 'config.txt'","Erreur",MB_OK|MB_ICONERROR); exit(1);
					}
					if (c=='a') {
						fscanf(pf," %d",&aig);     //get aig no
						fscanf(pf," %c",&c1);      //remove .
						fscanf(pf," %d",&pos);     //get aig pos
						descr[nb][IND_AIG_NUM_BASE+2*i_aig]=aig;
						descr[nb][IND_AIG_POS_BASE+2*i_aig]=pos;
						i_aig++;
						if (i_aig>IND_AIG_NUM_MAX) {
							MessageBox(NULL,"Le fichier 'config.txt' comporte une ligne trop complexe dans la section '#selectif' !","Erreur",MB_OK|MB_ICONERROR);
							MessageBox(NULL,"Un terme 'cX:+ cY+' doit être suivi de 6 aiguillages au maximum !","Erreur",MB_OK|MB_ICONERROR); exit(1);
						}
					}
				}
				while(c!=']');
				do {} while (fscanf(pf,"%c",&c)!=EOF);  // va à la fin du fichier pour éviter de retomber sur le mot '#selectif' dans un texte de commentaires.
			}
		}
	}
	nb_selectif_lus=nb; // valeur affichée sur la page débug des cantons.
	fclose(pf);
}

//
void cSelectif::verif(void)
{
	FILE* pf;
	int j,i;
	pf=fopen("selectif_debug.txt","wt");
	for(j=0;j<NB_SELECTIF;j++){
		fprintf(pf,"\n");
		for(i=0;i<IND_SELECTIF_TAILLE;i++) fprintf(pf,"%3d ",descr[j][i]);
	}
	fclose(pf);
}

//
void cSelectif::tick(void)
// En manuel, le canton suivant est sélectionné si la vitesse est <>0 et en fonction du sens du train.
// Le canton actuel est désélectionné si le canton suivant est sélectionné et immédiatement quand le canton actuel n'est plus détecté occupé.
// Il faudrait une petite tempo avant de désélectionner le canton actuel.

{
	int t,i,j,k,ok,canton_prec,canton_cour,sens,inv,a,aig,pos;  // pour les boucles
//1. maj master_selectif (met à zero si pas de détection et au moins une autre détection pour un train)
	for (t=0; t<NB_TRAIN; t++) {
//1.1. ajout
// Si le canton n'est pas reservé ET le train n° 't' est sur le canton ET le canton est physiquement occupé ET 
		for(j=0; j<NB_CARTE; j++) {
			for (i=0; i<NB_CANTON; i++) {
				if (canton.res_auto[j][i]==0 && canton.num_train[j][i]==t && canton.master_selectif[j][i]==0 && vio_det[j][i]==1 && canton.update_selectif[j][i]==1) {
					canton.master_selectif[j][i]=1;
				}
			}
		}
//1.2. retrait
		ok=0;
		for(j=0; j<NB_CARTE; j++) { 
			for(i=0; i<NB_CANTON; i++) {
				if (canton.num_train[j][i]==t && canton.master_selectif[j][i]==1 && vio_det[j][i]==1) {
					ok=1;
					// Remet à zéro le compteur de temporisation si le train est détecté sur le canton, même après une courte abscence.
					canton.master_selectif_tempo[j][i]=0;  
				}
			}
		}
		if (ok==1) {
			for (j=0; j<NB_CARTE; j++) {
				for(i=0; i<NB_CANTON; i++) {
					if (canton.num_train[j][i]==t && canton.master_selectif[j][i]==1 && vio_det[j][i]==0) {
						canton.master_selectif_tempo[j][i]++;
						 // Libére le canton si le train n'est pas détecté dessus depuis un certain temps = 'cfg_tempo_libe_cant' en 1/10 de secondes.
						if (canton.master_selectif_tempo[j][i] >= cfg_tempo_libe_cant) {
							canton.master_selectif[j][i] = 0;
							canton.inv_selectif[j][i]=0;  // V3.7c
						}
					}
				}
			}
		}
	}
	for(j=0; j<NB_CARTE; j++) { 
		for(i=0; i<NB_CANTON; i++) {
			if (canton.res_auto[j][i]==0 && canton.master_selectif[j][i]==0) {
				canton.num_train[j][i]=-1;
			}
		}
	}
//2. maj des cantons adjacents aux cantons master
	for (j=0; j<NB_CARTE; j++) {
		for (i=0; i<NB_CANTON; i++) {
			canton.update_selectif[j][i]=0; // Ne pas faire de reset bit canton inversé dans cette boucle ! : canton.inv_selectif[j][i]=0; 
		}
	}
//	for(t=0;t<NB_TRAIN;t++) /*if(train.vit[t]!=0)*/ if(train.vit[t]>5                || train.vit[t]<-5               ) if(train.enable[t]){
	for(t=0; t<NB_TRAIN; t++) { /*if(train.vit[t]!=0)*/
		if (train.enable[t] && (train.vit[t]>VITESSE_CANT_MIN || train.vit[t]<(-VITESSE_CANT_MIN))) {
			for (j=0; j<NB_CARTE; j++) {
				for (i=0; i<NB_CANTON; i++) {
					if (canton.master_selectif[j][i]==0 && vio_det[j][i]==0 && canton.res_auto[j][i]==0 && canton.update_selectif[j][i]==0) {
						canton_cour=100*j+i;
						for (k=0; k<NB_SELECTIF; k++) {
							if (descr[k][IND_CANT_COUR_NUM]==-1) break; // Fin du tableau description 'Sélectif'.
							if (descr[k][IND_CANT_COUR_NUM]==100*j+i) {
								canton_prec=descr[k][IND_CANT_PREC_NUM];
								ok=1;
								for (a=0; a<IND_AIG_NUM_MAX; a++){
									aig=descr[k][IND_AIG_NUM_BASE+2*a];
									if (aig==-1) break; // Fin de la partie aiguillages du tableau description 'Sélectif'.
									pos=descr[k][IND_AIG_POS_BASE+2*a];
									if ((pos==0 && vio_aig_pos0[aig]==0) || (pos==1 && vio_aig_pos1[aig]==0)) { 
										ok=0;
										break;
									}
								}
								if (ok) {
									if (canton.num_train[canton_prec/100][canton_prec%100]==t && canton.master_selectif[canton_prec/100][canton_prec%100]==1) {  /*&& vio_det[canton_prec/100][canton_prec%100]==1) {*/
										if (train.vit[t]>=0) sens=0;
										else sens=1;
										if (canton.inv_selectif[canton_prec/100][canton_prec%100]) sens^=1;
										if (descr[k][IND_CANT_PREC_SENS]==sens) {
											if ((sens==0 && descr[k][IND_CANT_PREC_SENS]==descr[k][IND_CANT_COUR_SENS] && (canton.allowed_sens[j][i]&1))    // UU-NEW-SENS-allowed
											||  (sens==1 && descr[k][IND_CANT_PREC_SENS]==descr[k][IND_CANT_COUR_SENS] && (canton.allowed_sens[j][i]&2))    // UU-NEW-SENS-allowed
											||  (sens==0 && descr[k][IND_CANT_PREC_SENS]!=descr[k][IND_CANT_COUR_SENS] && (canton.allowed_sens[j][i]&2))    // UU-NEW-SENS-allowed
											||  (sens==1 && descr[k][IND_CANT_PREC_SENS]!=descr[k][IND_CANT_COUR_SENS] && (canton.allowed_sens[j][i]&1))) { // UU-NEW-SENS-allowed
												inv=canton.inv_selectif[canton_prec/100][canton_prec%100];
												if(descr[k][IND_CANT_PREC_SENS]!=descr[k][IND_CANT_COUR_SENS]) inv^=1;
												canton.inv_selectif[j][i]=inv;
												canton.update_selectif[j][i]=1;
												canton.num_train[j][i]=t;
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}
	
//3. attribution des vitesses
	for (j=0; j<NB_CARTE; j++) {
		for (i=0; i<NB_CANTON; i++) {
			t=canton.num_train[j][i];
			if (t!=-1 && canton.res_auto[j][i]==0 && (canton.master_selectif[j][i]==1 || canton.update_selectif[j][i]==1)) {
				if (canton.inv_selectif[j][i]==0) {
					canton.vit_selectif[j][i]=train.vit[t]; 
				}
				else {
					canton.vit_selectif[j][i]=-train.vit[t];
				}
			}
			else {
				canton.vit_selectif[j][i]=0;
			}
		}
	}
}

//
// Affiche le tableau des option selectif des cantons à partir du menu : 'Debug > Selectif'.
// Affiche les cantons des cartes 0-1 ou 2-3 avec les n° de cantons adjacents.
//
//
void cSelectif::debug(int action)
{
	int i, j, y;
	char ch[200], signe1, signe2, ch2[10];
	static int select_deb=0;
	static int dimnx=44;    // Dimension horizontal d'une cellule 'Numéro'
	static int dimcx=125;   // Dimension horizontal d'une cellule 'Cantons'
	static int dimy=16;     // Dimension vertical d'une cellule
	static int nblignes=32; // Nombre de ligne du tableau (sans le titre)	
	static int decaly=16;   //Decalage de la premiére ligne vers les bas.

	SelectObject(hMemDC,bmp_fonte); SetBkMode(hMemDC,TRANSPARENT);
	SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_gris192);

	if(action==DEBUG_TOTAL_PAINT) {     // ACTION = REDESSINE TOUTE LA FENETRE.
		Rectangle(hMemDC,0,0,800,700);
		SetTextColor(hMemDC,RGB(0,0,0));	// Texte en noir.
		SelectObject(hMemDC,bmp_pinceau_gris192); SelectObject(hMemDC,bmp_stylo_gris192); Rectangle(hMemDC,800-15,15,800-2,2); // Rectangle gris pour fermer la fenêtre.
		SelectObject(hMemDC,bmp_stylo_noir); EasyLine(800-14,3,800-3,14 ); EasyLine(800-14,13,800-3,2); // Croix noire.
		SelectObject(hMemDC,bmp_stylo_noir);  EasyLine(800-2,1,800-2,16); EasyLine(800-16,15,800-1,15); // Trait noir.
		SelectObject(hMemDC,bmp_stylo_gris128); EasyLine(800-3,2,800-3,15); EasyLine(800-15,14,800-2,14); // Trait gris foncé.
		SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_gris192);
		EasyTextOut(2,2,"AFFICHE LES VALEURS DU TABLEAU INTERNE 'CANTONS SELECTIFS'  (100 valeurs maximum)"); EasyTextOut(800-140,2,"(QUITTER = ESC)");
		EasyTextOut(2,decaly+(nblignes+2)*dimy,"Section '#selectif'");
		SelectObject(hMemDC,bmp_stylo_noir); SelectObject(hMemDC,bmp_pinceau_gris220); // Rectangle gris foncé.
		Rectangle(hMemDC,0, decaly+(nblignes+3)*dimy-2, 97, decaly+(nblignes+4)*dimy);
		SelectObject(hMemDC,bmp_stylo_gris128);
		EasyLine(1,  decaly+(nblignes+4)*dimy-2, 96, decaly+(nblignes+4)*dimy-2);  	// Relief rectangle.
		EasyLine(95, decaly+(nblignes+3)*dimy-2+1, 95, decaly+(nblignes+4)*dimy-2);	// Relief rectangle.
		SelectObject(hMemDC,bmp_stylo_noir);
		EasyLine(97 - 10, decaly + (nblignes + 4)*dimy - 2, 97, decaly + (nblignes + 4)*dimy - 12);  // Dessine un trait dans l'angle = valeurs modifiables.
		SelectObject(hMemDC, bmp_pinceau_blanc); SelectObject(hMemDC, bmp_stylo_gris192);
		EasyTextOut(2,decaly+(nblignes+3)*dimy," CLIC-DROIT :AFFICHE LES PAGES 1->2->3, [00-31]->[32-63]->[64-95]");
		EasyTextOut(2,decaly+(nblignes+4)*dimy,"Mode de passage d'un canton à l'autre, en fonction du sens de parcours du canton");
		EasyTextOut(2,decaly+(nblignes+5)*dimy,"  cX+ --> cY+ = Train qui avance sur le canton X avancera sur le canton Y");
		EasyTextOut(2,decaly+(nblignes+6)*dimy,"  cX+ --> cY- = Train qui avance sur le canton X reculera sur le canton Y");
		EasyTextOut(2,decaly+(nblignes+7)*dimy,"  cX- --> cY+ = Train qui reculera sur le canton X avancera sur le canton Y");
		EasyTextOut(2,decaly+(nblignes+8)*dimy,"  cX- --> cY- = Train qui reculera sur le canton X reculera sur le canton Y");
		SetTextColor(hMemDC,RGB(255,0,0)); // Texte en rouge.
		EasyTextOut(              2,2+decaly,"n°Sel" );		   // Indice 'i' du tableau : descr[i][].
		EasyTextOut(2+dimnx+0*dimcx,2+decaly,"    Cantons");    // Cantons concernés : c15- >c14+.
		EasyTextOut(2+dimnx+1*dimcx,2+decaly,"  Conditions sur les aiguillages" );   // Conditions sur les aiguillages.
	}

	if(action==DEBUG_MOUSE) { // ACTION = CLIC GAUCHE DE LA SOURIS
		if ((x_mouse > 0 && x_mouse < 97) && (y_mouse > decaly+(nblignes+3)*dimy-2 && y_mouse < decaly+(nblignes+4)*dimy)) { //	Clique dans [CLIC DROIT]
			action=DEBUG_MOUSE_RIGHT; //	Simule le clique-droit traité plus loin.
		}
		else {
			if ((x_mouse > 800-15 && x_mouse < 800-2) && (y_mouse > 2 && y_mouse < 15)) {
				screen_mode= screen_mode_retour; 
				return;	// On ferme la fenêtre.
			}
		}
	}

	if(action==DEBUG_MOUSE_RIGHT) {    // ACTION = CLIC DROIT DE LA SOURIS, on passe à la page suivante.
    	Rectangle(hMemDC,0,decaly+dimy,800,dimy*(nblignes+1)+decaly);	// N'efface que la partie du tableau.
		switch(select_deb/nblignes) {
			case 0 : { screen_mode= MD_ECRAN_SELECT2; break;}
			case 1 : { screen_mode= MD_ECRAN_SELECT3; break;}
			case 2 : { screen_mode= MD_ECRAN_SELECT1; break;}
			default: break;
		}
	}

	if (screen_mode==MD_ECRAN_SELECT1) select_deb= 0;	// Valeur du premier déplacement à afficher.
	if (screen_mode==MD_ECRAN_SELECT2) select_deb=   nblignes;
	if (screen_mode==MD_ECRAN_SELECT3) select_deb= 2*nblignes;

	if(action==DEBUG_KEY) { }          // ACTION = TOUCHE ENFONCEE

	SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_blanc);
	Rectangle(hMemDC,1, dimy+decaly, 799, (nblignes+1)*dimy+decaly+1);
	SelectObject(hMemDC,bmp_stylo_gris192);


	EasyLine(    0,      decaly,          0,(nblignes+1)*dimy+decaly); // Traces les lignes  verticales
	EasyLine(dimnx,      decaly,      dimnx,(nblignes+1)*dimy+decaly);
	EasyLine(dimnx+dimcx,decaly,dimnx+dimcx,(nblignes+1)*dimy+decaly);
	EasyLine(800-1,      decaly,      800-1,(nblignes+1)*dimy+decaly);
	for (i=0;i<nblignes+2;i++) { EasyLine(0,dimy*i+decaly,800,dimy*i+decaly); }  // Trace les lignes horizonatles

	SetTextColor(hMemDC,RGB(0,0,255));	// Texte en bleu.
	for(i=0;i<nblignes;i++) {
		if(select_deb+i<NB_SELECTIF) {
			sprintf_s(ch,"%3d",select_deb+i);
			if(descr[select_deb+i][IND_CANT_COUR_NUM]==-1) 	SetTextColor(hMemDC,RGB(192,192,192));	// Texte en gris 192.
			EasyTextOut(10,2+dimy*(i+2),ch); // N° d'indice du tableau
			SetTextColor(hMemDC,RGB(0,0,255));	// Texte en bleu.
			if(descr[select_deb+i][IND_CANT_COUR_NUM]!=-1) {
				if (descr[select_deb+i][IND_CANT_COUR_SENS]==0) signe1='+'; else signe1='-';
				if (descr[select_deb+i][IND_CANT_PREC_SENS]==0) signe2='+'; else signe2='-';
				sprintf_s(ch,"c%-2d%c --> c%-2d%c",descr[select_deb+i][IND_CANT_PREC_NUM],signe2,descr[select_deb+i][IND_CANT_COUR_NUM],signe1);               
				EasyTextOut(dimnx+10,2+dimy*(i+2),ch); // N° des cantons départ --> N° des cantons arrivée.
				if (descr[select_deb+i][IND_CANT_PREC_SENS]==0) signe2='+'; else signe2='-';
				sprintf_s(ch," ");
				for (j=0;j<IND_AIG_NUM_MAX;j++) {
					y = descr[select_deb+i][IND_AIG_NUM_BASE+2*j];
					if (descr[select_deb+i][IND_AIG_NUM_BASE+2*j]!=-1) {
						strcat(ch,"a");
						sprintf_s(ch2,"%d",descr[select_deb+i][IND_AIG_NUM_BASE+2*j]);
						strcat(ch,ch2);
						if (descr[select_deb+i][IND_AIG_POS_BASE+2*j]==0) strcat(ch,"=0   ");
						if (descr[select_deb+i][IND_AIG_POS_BASE+2*j]==1) strcat(ch,"=1   ");
					}
				}
				EasyTextOut(dimcx+dimnx+10,2+dimy*(i+2),ch);				// affiche le texte sur les conditions sur les aiguillages.
			}
		}
	}
}

/*****************************************************************************/
/* Fin SELECTIF                                                              */
/*****************************************************************************/
