#ifndef _check_cpp #define _check_cpp //CONTROLLATO PER MEMORY LEAK - 21 NOV 2001 - MP //SEARCHACTIVITY //DATO UN CODICE DI ATTIVITA RITORNA LA POSIZIONE IN CUI SI TROVA IN ACTIVITY_LIST int SearchActivity(String *what) { if(activity_list.IsEmpty()) return 0; for(int i=0; iGetItem(),activity_list.GetData(i).GetCode()->GetItem())) return i+1; } return 0; } //SEARCHSECTOR //DATO IL CODICE DI UN SETTORE RITORNA LA POSIZIONE IN CUI SI TROVA IN ACTIVITY_LIST int SearchSector(String *what, int from=0) { if(activity_list.IsEmpty()) return 0; for(int i=from; iGetItem(),activity_list.GetData(i).GetSettore()->GetItem())) return i+1; } return 0; } //SEARCHTYPE //DATO IL TIPO RITORNA LA POSIZIONE IN CUI SI TROVA IN ACTIVITY_LIST int SearchType(String *what, int from=0) { if(activity_list.IsEmpty()) return 0; for(int i=from; iGetItem(),activity_list.GetData(i).GetTipo()->GetItem())) return i+1; } return 0; } //SEARCHEXAM //DATO UN CODICE DI ESAME RITORNA LA POSIZIONE IN CUI SI TROVA IN EXAM_LIST //HIDDEN: TIENE CONTO SE E' CANCELLATO O MENO (1= cerca fra tutti, 0= non cerca quelli nascosti) //FROM: STABILISCE DA CHE PUNTO INIZIA LA RICERCA int SearchExam(String *what, int hidden=0, int from=0) { if(exam_list.IsEmpty()) return 0; for(int i=from; iGetItem(),exam_list.GetData(i).GetName()->GetItem())) return i+1; } else if(!strcmp(what->GetItem(),exam_list.GetData(i).GetName()->GetItem())) return i+1; } return 0; } //CHECKNOPROPACT //CARICA LE ATTIVITA' CHE POSSONO ESSERE AGGIUNTE SENZA VIOLARE LA PROPEDEUTICITA' //CIOE' ATTIVITA' CON PROPEDEUTICITA' PRESENTE IN CARRIERA void CheckNoPropAct() { int found; if(!noprop_activity_list.IsEmpty()) noprop_activity_list.DelList(); //cancello la vecchia lista for(int i=0; iGetLen(); j++) { if(!(found=SearchExam(&activity_list.GetData(i).GetProp()->GetData(j)),0)) break; } if(found)//se ho trovato tutte le propedeuticità nella carriera (oppure se non c'era prop) { Activity *tmp = new Activity(activity_list.GetData(i));//copio l'attività noprop_activity_list.InsertElement(*tmp); //inserisco in lista } } } //end for(i) } //SEARCHSUPERYEAR //CERCA SE LE ATTIVITÀ IN CARRIERA FINO AL VALORE MAX RISPETTANO L'ANNO WHICH int SearchSuperYear(int which, int max) { if(exam_list.IsEmpty()) return 0; if(exam_list.IsHidden()) return 0; for(int i=0; i < max; i++) { if(!exam_list.GetHide(i)) if(exam_list.GetData(i).GetYear()>which) return i+1; } return 0; } //VALIDACTIVITY //CONTROLLA SE UN ATTIVITA' E' VALIDA COMPIENDO 3 CONTROLLI //1. E' IN OFFERTA //2. RISPETTA L'ANNO MINIMO //3. LA SUA PROPEDEUTICITA' E' VALIDA (<- RICHIAMA VALIDACTIVITY) int ValidActivity(Exam &data, int where) { int found; int position; //1. cerco l'attivita nell'offerta if(!(found = SearchActivity(data.GetName()))) { LOG.DEV("ERRORE: attività non presente nell'offerta didattica: ", 0); LOG.DEV(data.GetChar()); return 0; } found--; //found e' uno pseudo booleano (0 se non e' valido) e va aggiustato di uno per avere //la posizine corretta dell'elemento in lista (0-len) //2. controllo l'anno if(data.GetYear() < activity_list.GetData(found).GetAnno()) { LOG.DEV("ERRORE: ",0); LOG.DEV(data.GetChar(), 0); LOG.DEV(" non rispetta l'anno minimo: ", 0); LOG.DEV(activity_list.GetData(found).GetAnno()); return 0; } //3. controlla se le attivita propedeutiche sono in carriera e sono valide int k; for(int i=0; i < activity_list.GetData(found).GetProp()->GetLen(); i++) { if(!(k = SearchExam(&activity_list.GetData(found).GetProp()->GetData(i),0))) //cerca se l'attivita' e' in carriera { LOG.DEV("ERRORE: ", 0); LOG.DEV(data.GetChar(), 0); LOG.DEV(" non rispetta la lista delle propedeuticita': ",0); LOG.DEV(activity_list.GetData(found).GetProp()->GetData(i).GetChar()); return 0; } k--; if(exam_list.GetData(k).GetYear()>data.GetYear()) //controlla se gli anni non rispettavano la propedeuticità { LOG.DEV("ERRORE: ", 0); LOG.DEV(data.GetChar(), 0); LOG.DEV(" non rispetta l'anno in seguito a ",0); LOG.DEV(exam_list.GetData(k).GetChar()); return 0; } if(exam_list.GetHide(k)) //controlla se l'attivita' e' valida (cioe' non nascosta) { LOG.DEV("ERRORE: ", 0); LOG.DEV(data.GetChar(), 0); LOG.DEV(" non rispetta la propedeuticita' in seguito a ",0); LOG.DEV(exam_list.GetData(k).GetChar()); return 0; } else if(!ValidActivity(exam_list.GetData(k), k)) //controlla la validità in maniera più completa (ricorsivamente) { LOG.DEV("ERRORE: ", 0); LOG.DEV(data.GetChar(), 0); LOG.DEV(" non rispetta la propedeuticita' in seguito a ",0); LOG.DEV(exam_list.GetData(k).GetChar()); errors++; exam_list.Hide(k+1); return 0; } } //se passa i tre controlli allora e' ok return 1; } //REDUCERULE //RIDUCE LA REGOLA DATA DEL NUMERO DI UNITA O CREDITI TROVATI void ReduceRule(Rule &data) { int foundexam, foundactivity; int bond=0; //dice se è un vincolo oppure no int bound = data.GetOriginalBound(); //valore da cui sottrarre crediti/unita int wkou=1; //what kind of unit (crediti=0 o unita=1) if(!strcmp(data.GetUnita()->GetItem(), "crediti")) wkou = 0; //l'unità è crediti if(strcmp(data.GetQta()->GetItem(),"almeno")) bond=1; //è un vincolo //inizio fase di conteggio if(!strcmp(data.GetT_att()->GetItem(), "corso")) { if(!strcmp(data.GetT_amb()->GetItem(), "corsi")) { for(int i=0; iGetLen(); i++) { //cerchiamo tutti gli esami nella carriera che corrispondono al codice presente nella lista ambito di questa regola foundexam = SearchExam(&data.GetL_amb()->GetData(i)); //se lo trova prendiamo i crediti corrispondenti cercando nell'offerta if(foundexam) { if(wkou) //controllo unita di misura bound--; else bound -= activity_list.GetData(SearchActivity(&data.GetL_amb()->GetData(i))-1).GetCrediti(); if(bond) //controllo vincolo violato if(bound<0) { data.SetBound(bound); //cosi rendo visibile l'errore LOG.DEV("ERRORE: ",0); LOG.DEV(exam_list.GetData(foundexam-1).GetChar(),0); LOG.DEV(" viola il vincolo: ",0); LOG.DEV(data.GetChar()); exam_list.Hide(foundexam,2); //flag 2 esame errato } } } } else if(!strcmp(data.GetT_amb()->GetItem(), "settori")) //cntrl superfluo { for(int i=0; iGetLen(); i++) { //prendo tutti gli esami e li cerco in offerta //se il loro settore corrisponde allora è fatta for(int ix=0; ixGetData(i).GetItem(), activity_list.GetData(foundactivity-1).GetSettore()->GetItem())) { if(wkou) //controllo unita di misura bound--; else bound -= activity_list.GetData(foundactivity-1).GetCrediti(); if(bond) //controllo vincolo violato if(bound<0) { data.SetBound(bound); //cosi rendo visibile l'errore LOG.DEV("ERRORE: ",0); LOG.DEV(exam_list.GetData(ix).GetChar(),0); LOG.DEV(" viola il vincolo: ",0); LOG.DEV(data.GetChar()); exam_list.Hide(ix+1,2); //flag 2 esame errato } } }//fine for(ix) }//fine for(i) }//fine else } else if(!strcmp(data.GetT_att()->GetItem(), "complessivamente")) { for(int i=0; iGetItem(), activity_list.GetData(foundactivity-1).GetTipo()->GetItem())) { if(wkou) //controllo unita di misura bound--; else bound -= activity_list.GetData(foundactivity-1).GetCrediti(); if(bond) //controllo vincolo violato if(bound<0) { data.SetBound(bound); //cosi rendo visibile l'errore LOG.DEV("ERRORE: ",0); LOG.DEV(exam_list.GetData(i).GetChar(),0); LOG.DEV(" viola il vincolo: ",0); LOG.DEV(data.GetChar()); exam_list.Hide(i+1,2); //flag 2 esame errato } } }//fine for(i) } data.SetBound(bound); } //CHECKCRONOLOGY //CONTROLLO LA CRONOLOGIA DELLA CARRIERA void CheckCronology() { int position; Exam *tmp; String *name; for(int i=1; i < exam_list.GetLen(); i++) { if(!exam_list.GetHide(i)) if(position=SearchSuperYear(exam_list.GetData(i).GetYear(), i)) { position--; //aggiusto il valore pseudobooleano LOG.DEV("ERRORE: cronologia non rispettata a causa di ",0,1); LOG.DEV(exam_list.GetData(i).GetChar(),0, 1); LOG.DEV(" (In conseguenza di ",0, 1); LOG.DEV(exam_list.GetData(position).GetChar(),0,1); LOG.DEV(")",1,1); errors++; exam_list.Hide(i+1); } } } //CHECKOFFER //CONTROLLO L'OFFERTA void CheckOffer() { //---------------------------------------1 LOG.DEV("Controllo offerta (", 0, 1); LOG.DEV(activity_list.GetLen(),0, 1); LOG.DEV(" attivita')",1,1); //controllo se le attivita' propedeutiche esistono in offerta for(int i=0; i < activity_list.GetLen(); i++) { for(int k=0; k < activity_list.GetData(i).GetProp()->GetLen(); k++) //controllo tutte le attivita' in lista_prop { if(!SearchActivity(&activity_list.GetData(i).GetProp()->GetData(k))) { LOG.DEV("ERRORE: lista di attivita' propedeutiche errata: ",0); LOG.DEV(activity_list.GetData(i).GetChar()); activity_list.Del(i); //cancello l'attivita' che contiene l'errore i--; //sposto il puntatore alla lista break; } } } //passo in rassegna l'offerta controllando se le attivita' sono state svolte o meno for(int i=0; i < activity_list.GetLen(); i++) { if(SearchExam(activity_list.GetData(i).GetCode())) //cerco in carriera { if(!activity_list.GetHide(i)) { LOG.DEV("Nascondo attività in offerta: ",0,2); LOG.DEV(activity_list.GetData(i).GetChar(),1,2); activity_list.Hide(i+1); //se e' presente la nascondo } } else { if(activity_list.GetHide(i)) { LOG.DEV("Ripristino attività in offerta: ",0,2); LOG.DEV(activity_list.GetData(i).GetChar(),1,2); activity_list.UnHide(i+1); //altrimenti torna visibile :) } } } CheckNoPropAct(); //controllo se ci sono attività con propedeuticità completata } //CHECKORDER //CONTROLLO L'ORDINAMENTO void CheckOrder() { //---------------------------------------2 LOG.DEV("Controllo ordinamento (", 0, 1); LOG.DEV(rule_list.GetLen(),0, 1); LOG.DEV(" regole)",1,1); int prevbound; violations=0; obj=0; tot_obj=0; //controlla che gli ambiti siano compatibili con l'offerta e lo segnala if(activity_list.IsEmpty()) { LOG.DEV("ERRORE CRITICO: impossibile trovare l'offerta didattica"); for(int i=0; i < rule_list.GetLen(); i++) rule_list.Hide(i+1, 0); //ripristino le regole return; } for(int i=0; i < rule_list.GetLen(); i++) { if(rule_list.GetData(i).GetL_amb()!=NULL) for(int k=0; k < rule_list.GetData(i).GetL_amb()->GetLen(); k++) { if(!strcmp(rule_list.GetData(i).GetT_amb()->GetItem(),"corsi")) { if(!SearchActivity(&rule_list.GetData(i).GetL_amb()->GetData(k))) { LOG.DEV("ERRORE: attivita' indicata in ordinamento non e' presente in offerta: ",0); LOG.DEV(rule_list.GetData(i).GetL_amb()->GetData(k).GetChar()); rule_list.Del(i); i--; break; } } else //if(!strcmp(rule_list.GetData(i).GetT_amb()->GetItem(),"corsi")) { if(!SearchSector(&rule_list.GetData(i).GetL_amb()->GetData(k))) { LOG.DEV("ERRORE: settore indicato in ordinamento non e' presente in offerta: ",0); LOG.DEV(rule_list.GetData(i).GetL_amb()->GetData(k).GetChar()); rule_list.Del(i); i--; break; } } } //end for(k) }//end for(i) for(int i=0; i < exam_list.GetLen(); i++) if(exam_list.GetHide(i)==2) exam_list.Hide(i+1, 0); //rendo tutto visibile //riduce le regole una alla volta for(int i=0; i < rule_list.GetLen(); i++) { prevbound = rule_list.GetData(i).GetBound(); //memorizza il valore precedente la riduzione (serve per i vincoli che non vengono hiddati e che lo erano) ReduceRule(rule_list.GetData(i)); //controllo obiettivi e vincoli if(!strcmp(rule_list.GetData(i).GetQta()->GetItem(), "almeno")) { if(rule_list.GetData(i).GetBound()<=0) { obj++; //obiettivo soddisfatto if(!rule_list.GetHide(i)) //notifica solo se non era già stato soddisfatto { LOG.DEV("SODDISFATTO: ",0,1); LOG.DEV(rule_list.GetData(i).GetChar(), 1,1); rule_list.Hide(i+1); } } else { if(rule_list.GetHide(i)) //notifica solo se era soddisfatto { LOG.DEV("NON PIU' SODDISFATTO: ", 0,1); LOG.DEV(rule_list.GetData(i).GetChar(), 1,1); rule_list.UnHide(i+1); } } tot_obj++; //numero di obiettivi incrementato } else //if(!strcmp(data.GetQta(), "al piu'")) { if(rule_list.GetData(i).GetBound()<0) { //LOG.DEV("ATTENZIONE: VIOLATO: ", 0,1); //LOG.DEV(rule_list.GetData(i).GetChar(),1,1); violations++; //vincolo violato rule_list.Hide(i+1,2); } else { if(prevbound<0) //se il vincolo era violato allora di che adesso non lo è più { LOG.DEV("NON PIU' VIOLATO: ", 0, 1); LOG.DEV(rule_list.GetData(i).GetChar(), 1,1); rule_list.Hide(i+1, 0); } } } } //end for(i) if(violations) { LOG.DEV("Violati ",0); LOG.DEV(violations,0); LOG.DEV(" vincoli"); } LOG.DEV("Soddisfatti ",0); LOG.DEV(obj,0); LOG.DEV(" obiettivi su ",0); LOG.DEV(tot_obj); } //CHECKCARRIER //CONTROLLO LA CARRIERA void CheckCarrier() { errors=0; //--------------------------------------3 LOG.DEV("Controllo carriera (", 0, 1); LOG.DEV(exam_list.GetLen(),0, 1); LOG.DEV(" attivita' svolte)",1,1); for(int i=0; i < exam_list.GetLen(); i++) exam_list.UnHide(i+1); //rendo tutto visibile //prendo una alla volta tutte le attivita contenute nella carriera //e controllo se sono valide for(int i=0; i < exam_list.GetLen(); i++) { if(!exam_list.GetHide(i)) if(!ValidActivity(exam_list.GetData(i), i)) //vedo se e' valida { errors++; exam_list.Hide(i+1); //se non e' valida cancello } }//end for CheckCronology(); } //CHECK //COMPIE I TRE CONTROLLI SULLE TRE LISTE GLOBALI // 1. AGGIORNAMENTO OFFERTA: OGNI ATTIVITA NELL'OFFERTA E' NASCOSTA SE PRESENTE IN CARRIERA // 2. RIDUZIONE REGOLE // 3. CONTROLLO CARRIERA: OGNI ATTIVITA NELLA CARRIERA E' VALIDA SE ValidActivity E' VERA void Check() { //if(exam_list.GetLen()&&activity_list.GetLen()) //{ //la carriera va controllata solo //se e' presente un offerta //altrimenti tutte le attività vengono cancellate in quanto ritenute non valide CheckCarrier(); //il controllo dell'offerta e' integrato in carriera //} //else //if(activity_list.GetLen()) CheckOffer(); //questo si può fare sempre //if(rule_list.GetLen()&&exam_list.GetLen()) //e' inutile controllare l'ordinamento se non c'e' una carriera CheckOrder(); if((errors)||(violations)) LOG.DEV("CARRIERA NON CORRETTA"); else if(exam_list.IsEmpty()) LOG.DEV("CARRIERA VUOTA"); else if((tot_obj-obj)||(!tot_obj)) LOG.DEV("CARRIERA NON COMPLETA"); else LOG.DEV("CARRIERA COMPLETA"); } //CLEARCARRIER //RIORDINA LE ATTIVITA' CRONOLOGICHE E //CANCELLA TUTTI GLI EXAM NASCOSTI IN LIST_EXAM (CHIEDE CONFERMA) void ClearCarrier() { if(!errors&&!violations) { LOG.DEV("Carriera corretta!"); return; } for(int i=0; i < exam_list.GetLen(); i++) exam_list.UnHide(i+1); //rendo tutto visibile int position; Exam *tmp; String *name; LOG.DEV("Sistemazione errori di cronologia..."); for(int i=1; i < exam_list.GetLen(); i++) { if(position=SearchSuperYear(exam_list.GetData(i).GetYear(), i)) { position--; //aggiusto il valore pseudobooleano LOG.DEV(exam_list.GetData(i).GetChar(),0,2); LOG.DEV("L'attivita' verra' spostata in maniera tale da rispettare la cronologia",1,2); //devo copiare i dati in un altra locazione perche' dopo li cancello name = name->Create(exam_list.GetData(i).GetName()->GetItem()); tmp = new Exam(name, exam_list.GetData(i).GetYear()); //inserisco prima del nodo che da problemi exam_list.InsertElement(*tmp, position); //cancello il dato che ho spostato (contando che si e' spostato di uno) exam_list.Del(i+1); } } Check(); if((!errors)&&(!violations)) { LOG.DEV("La carriera è stata ordinata cronologicamente e risulta corretta",1,1); return; } else LOG.DEV("La carriera è ordinata cronologicamente ma ci sono altri tipi di errori",1,1); VIDEO.Pause(); //VIDEO.Clear(); LOG.DEV("Rimozione attivita' errate..."); int q; while((errors)||(violations)) { for(int i=0; i < exam_list.GetLen(); i++) //devo prendere il primo exam errato { if(exam_list.GetHide(i)) { exam_list.Print(i); VIDEO.Endl(); q=question("Cancellare quest'attività dalla carriera?"); if(q==1) { exam_list.Del(i); i--; } if(q!=2) break; if(i==exam_list.GetLen()-1) q=0; } }//end for(i) if(!q) break; //cancel Check(); //controllo rapido per vedere cosa cambia (vincoli) VIDEO.Clear(); } Check(); } #endif