//---------------------------------------------------------------------------
#pragma hdrstop
#include "SkemaKontrol.h"
//------------------------------bytte funktioner------------------------------//
///Funktionen vurder om det kan lade sig gøre at bytte en lektion med en anden.
///Hvis det kan lade sig gøre bytte de 2 lektioner.
///Alt efter udfaldet returneres en sandhedsværdi.
bool SkemaKontrol::VurderOgBytLektion(string ID, int blok, char type, int fra_col,
                              int fra_row, int til_col, int til_row)
{
	return BytInitialiser(ID, blok, type, fra_col, fra_row, til_col, til_row, 'u');
}//
///Funktionen vurdere om det kan lade sig gøre at bytte en lektion med en anden.
///Alt efter udfaldet returneres en sandhedsværdi.
bool SkemaKontrol::VurderBytningAfLektion(string ID, int blok, char type, int fra_col,
                                  int fra_row, int til_col, int til_row)
{
	return BytInitialiser(ID, blok, type, fra_col, fra_row, til_col, til_row, 'v');
}//
///Funktionen undersøger om der er en tilsvarende lektionen på det angivene skema.
///Herefter kanalisere funktionen alt efter vurderingen videre til
///henholdsvis en byt eller en flyt funktion.
bool SkemaKontrol::BytInitialiser(string ID, int blok, char type, int fra_col,
                                  int fra_row, int til_col, int til_row, char form)
{
    fra.indsaet(fra_col, fra_row);
    til.indsaet(til_col, til_row);
    if(!KontrollerKoordinat(fra, blok) && !KontrollerKoordinat(til, blok))
      return false;
    bool ok = false;
    switch(type)
    {
      case 'h':
      if(HS.HentSkema(ID, s.Hskema) && //Findes skemaet?
         s.Hskema->HentLektion(lPtr, fra_col, fra_row) && //Er der en lektion!
         lPtr.HoldID == ID && lPtr.blokstoerrelse == blok && //Er lektionen identisk.
         LS.HentSkema(lPtr.LaererID, s.Lskema) &&  //findes laerer skema?
         LOS.HentSkema(lPtr.LokaleID, s.LOskema)) //findes lokale skema?
      {
        //hvis dobbelt lektionen ikke er en rigtig dobbelt lektion.
        if(blok == 2 && !ErDobbeltLektion(s, fra))
          return false;
        if(FindEgnetBytteLektion(lPtr2, s, til_col, til_row)) //er den anden god?
        {
          if(lPtr2.blokstoerrelse == blok && //har den anden lektion samme blok
             HS.HentSkema(lPtr2.HoldID, s2.Hskema) && //findes hold skema?
             LS.HentSkema(lPtr2.LaererID, s2.Lskema) && //findes lærer skema?
             LOS.HentSkema(lPtr2.LokaleID, s2.LOskema)) //findes lokale skema?
          {
            //hvis den anden lektion ikke er en rigtig dobbelt lektion
            if(blok == 2 && !ErDobbeltLektion(s2, til))
              return false;
            else //Der er noget i begge lektioner =>
              return BytningAfLektion(lPtr, lPtr2, s, s2, fra, til, form);
          }
        }
        else  //den anden lektion er tom.!
          return FlytningAfLektion(lPtr, s, fra, til, lPtr.blokstoerrelse, form);
      }
      break;
      case 'l':
      if(LS.HentSkema(ID, s.Lskema) &&
         s.Lskema->HentLektion(lPtr, fra_col, fra_row) &&
         lPtr.LaererID == ID && lPtr.blokstoerrelse == blok &&
         HS.HentSkema(lPtr.HoldID, s.Hskema) && LOS.HentSkema(lPtr.LokaleID, s.LOskema))
      {
        if(blok == 2 && !ErDobbeltLektion(s, fra))
          return false;
        if(FindEgnetBytteLektion(lPtr2, s, til_col, til_row))
        {
          if(lPtr2.blokstoerrelse == blok &&
             LS.HentSkema(lPtr2.LaererID, s2.Lskema) &&
             HS.HentSkema(lPtr2.HoldID, s2.Hskema) &&
             LOS.HentSkema(lPtr2.LokaleID, s2.LOskema))
          {
            if(blok == 2 && !ErDobbeltLektion(s2, til))
              return false;
            else
              return BytningAfLektion(lPtr, lPtr2, s, s2, fra, til, form);
          }
        }
        else
          return FlytningAfLektion(lPtr, s, fra, til, lPtr.blokstoerrelse, form);
      }
      break;
      case 'k':
      if(LOS.HentSkema(ID, s.LOskema) &&
         s.LOskema->HentLektion(lPtr, fra_col, fra_row) &&
         lPtr.LokaleID == ID && lPtr.blokstoerrelse == blok &&
         LS.HentSkema(lPtr.LaererID, s.Lskema) && HS.HentSkema(lPtr.HoldID, s.Hskema))
      {
        if(blok == 2 && !ErDobbeltLektion(s, fra))
          return false;
        if(FindEgnetBytteLektion(lPtr2, s, til_col, til_row))
        {
          if(lPtr2.blokstoerrelse == blok &&
             LOS.HentSkema(lPtr2.LokaleID, s2.LOskema) &&
             LS.HentSkema(lPtr2.LaererID, s2.Lskema) &&
             HS.HentSkema(lPtr2.HoldID, s2.Hskema))
          {
            if(blok == 2 && !ErDobbeltLektion(s2, til))
              return false;
            else
              return BytningAfLektion(lPtr, lPtr2, s, s2, fra, til, form);
          }
        }
        else
          return FlytningAfLektion(lPtr, s, fra, til, lPtr.blokstoerrelse, form);
      }
      break;
    }
    return false;
}//
///Funktionen forsøger at finder den første lektion den møder i koordinatet på et af
///skemaerne til relationen. Herefter returnere den en sandhedsværdi.
bool SkemaKontrol::FindEgnetBytteLektion(lektion& lPtr2, SkemaPtr& s, int til_col, int til_row)
{
    bool ok = false;
	if(!ok && s.Hskema->HentLektion(lPtr2, til_col, til_row))
      ok = lPtr2.LaererID == lPtr.LaererID ||  lPtr2.LokaleID == lPtr.LokaleID;
    if(!ok && s.Lskema->HentLektion(lPtr2, til_col, til_row))
      ok = lPtr2.HoldID == lPtr.HoldID || lPtr2.LokaleID == lPtr.LokaleID;
    if(!ok && s.LOskema->HentLektion(lPtr2, til_col, til_row))
      ok = lPtr2.HoldID == lPtr.HoldID || lPtr2.LaererID == lPtr.LaererID;
    return ok;
}//
///Funktionen bytter direkte 2 lektioner med hinanden.
void SkemaKontrol::BytLektion(string ID, char type, int fra_col, int fra_row,
                      int til_col, int til_row)
{
    fra.indsaet(fra_col, fra_row);
    til.indsaet(til_col, til_row);
    switch(type)
    {
      case 'h':
        if(HS.HentSkema(ID, s.Hskema) && //Findes skemaet?
           s.Hskema->HentLektion(lPtr, fra_col, fra_row) && //Findes lektionen?
           LS.HentSkema(lPtr.LaererID, s.Lskema) && //findes lærer skema
           LOS.HentSkema(lPtr.LokaleID, s.LOskema)) //findes lokale skema
        {
          if(FindEgnetBytteLektion(lPtr2, s, til_col, til_row)) //er den anden god!
          {
            if(HS.HentSkema(lPtr2.HoldID, s2.Hskema) && //findes hold skema?
               LS.HentSkema(lPtr2.LaererID, s2.Lskema) && //findes lærer skema?
               LOS.HentSkema(lPtr2.LokaleID, s2.LOskema)) //findes lokale skema?
              BytLektion(lPtr, lPtr2, s, s2, fra, til);
          }
          else
            FlytLektion(lPtr, s, fra, til, lPtr.blokstoerrelse);
        }
        break;
      case 'l':
        if(LS.HentSkema(ID, s.Lskema) &&
           s.Lskema->HentLektion(lPtr, fra_col, fra_row) &&
           HS.HentSkema(lPtr.HoldID, s.Hskema) &&
           LOS.HentSkema(lPtr.LokaleID, s.LOskema))
        {
          if(FindEgnetBytteLektion(lPtr2, s, til_col, til_row))
          {
            if(HS.HentSkema(lPtr2.HoldID, s2.Hskema) &&
               LOS.HentSkema(lPtr2.LokaleID, s2.LOskema) &&
               LS.HentSkema(lPtr2.LaererID, s2.Lskema))
              BytLektion(lPtr, lPtr2, s, s2, fra, til);
          }
          else
            FlytLektion(lPtr, s, fra, til, lPtr.blokstoerrelse);
        }
        break;
      case 'k':
        if(LOS.HentSkema(ID, s.LOskema) &&
           s.LOskema->HentLektion(lPtr, fra_col, fra_row) &&
           LS.HentSkema(lPtr.LaererID, s.Lskema) &&
           HS.HentSkema(lPtr.HoldID, s.Hskema))
        {
          if(FindEgnetBytteLektion(lPtr2, s, til_col, til_row))
          {
            if(LS.HentSkema(lPtr2.LaererID, s2.Lskema) &&
               HS.HentSkema(lPtr2.HoldID, s2.Hskema) &&
               LOS.HentSkema(lPtr2.LokaleID, s2.LOskema))
              BytLektion(lPtr, lPtr2, s, s2, fra, til);
          }
          else
            FlytLektion(lPtr, s, fra, til, lPtr.blokstoerrelse);
        }
        break;
    }
}//
//----------------------------------------------------------------------------//
///Funktionen undersøger om det kan lade sig gøre at bytte to lektioner.
///alt efter vTypen udføres eller vurderes kun bytningen.
///Alt efter udfaldet returneres en sandhedsværdi.
bool SkemaKontrol::BytningAfLektion(const lektion& lPtr1, const lektion& lPtr2,
                            const SkemaPtr& s1, const SkemaPtr& s2,
							const koord& fra, const koord& til,
                            char vType)
{
    //den anden lektion slettes fra skemaet.
    SletLektion(s2, til, lPtr2.blokstoerrelse);

    //kan første lektion flyttes over på anden lektions plads (den er tom!)
    if(FlytningAfLektion(lPtr1, s1, fra, til, lPtr1.blokstoerrelse, 'v')) //kun vurder
    {
      //anden lektion lægges tilbage
      LaegLektion(lPtr2, s2, til, lPtr2.blokstoerrelse);

      //første lektion slettes.
      SletLektion(s1, fra, lPtr1.blokstoerrelse);
      //kan anden lektion flyttes over på første lektions plads (den er tom!)
      if(FlytningAfLektion(lPtr2, s2, til, fra, lPtr2.blokstoerrelse, vType))
      {
        //Alt efter typen byttes eller lægges tilbage
        if(vType == 'u')      //vurder og derefter byt
          LaegLektion(lPtr1, s1, til, lPtr1.blokstoerrelse);  //lPtr2 er flyttet helt!
        else if(vType == 'v') //vurder kun
          LaegLektion(lPtr1, s1, fra, lPtr1.blokstoerrelse);
        return true;
      }
      LaegLektion(lPtr1, s1, fra, lPtr1.blokstoerrelse);
    }
    LaegLektion(lPtr2, s2, til, lPtr2.blokstoerrelse);
    return false;
}//
///Funktionen bytter direkte 2 lektioner med hinanden uden overhovedet at vurdere.!
void SkemaKontrol::BytLektion(const lektion& lPtr1, const lektion& lPtr2, const SkemaPtr& s1,
                      const SkemaPtr& s2, const koord& fra, const koord& til)
{
     for(int i = 0; i < lPtr2.blokstoerrelse; i++)
     {
       //NB: Man må ikke skifte lektioner 2 gange på et skema.. Derfor
       //tages der højde for dette v.h.a if sætningerne
       if(s1.Hskema != s2.Hskema)
         s2.Hskema->BytLektioner(fra.col, fra.row+i, til.col, til.row+i);
       s1.Hskema->BytLektioner(fra.col, fra.row+i, til.col, til.row+i);
       if(s1.Lskema != s2.Lskema)
         s2.Lskema->BytLektioner(fra.col, fra.row+i, til.col, til.row+i);
       s1.Lskema->BytLektioner(fra.col, fra.row+i, til.col, til.row+i);
       if(s1.LOskema != s2.LOskema)
         s2.LOskema->BytLektioner(fra.col, fra.row+i, til.col, til.row+i);
       s1.LOskema->BytLektioner(fra.col, fra.row+i, til.col+i, til.row+i);
     }
}//
//----------------------------------------------------------------------------//
///Funktionen vurdere om en lektion kan flyttes hvorefter den evt. flyttes.
bool SkemaKontrol::FlytningAfLektion(const lektion& lPtr, const SkemaPtr& s,
							 const koord& fra, const koord& til,
                             int blok, char vType)
{
    //Lektionen slettes.
    SletLektion(s, fra, blok);
    //hvis pladsen som den skal flyttes over på er fri
    if(ErLektionTom(s, til, blok))
    {
      //vurder om lektionen kan ligge det nye sted
      if(VurderLektion(lPtr, s, til, blok))
      {
        if(vType == 'u') //vurder og flyt
          LaegLektion(lPtr, s, til, blok);
        else if(vType == 'v') //vurder kun!
          LaegLektion(lPtr, s, fra, blok);
        return true;
      }
    }
    LaegLektion(lPtr, s, fra, blok);
    return false;
}//
///Funktionen flytter direkte en lektion uden at vurdere noget.
void SkemaKontrol::FlytLektion(const lektion& lPtr, const SkemaPtr& s, const koord& fra,
                       const koord& til, int blok)
{
	for(int i = lPtr.blokstoerrelse-1 ; i >= 0; i--)
    {
      s.Hskema->FlytLektion(fra.col, fra.row+i, til.col, til.row+i);
      s.Lskema->FlytLektion(fra.col, fra.row+i, til.col, til.row+i);
      s.LOskema->FlytLektion(fra.col, fra.row+i, til.col, til.row+i);
    }
}//
//-----------------------------opret funktioner-------------------------------//
///Funktionen opretter og lægger en lektion på de forskellige skemaer.
///Alt efter udfaldet returneres en sandhedsværdi.
bool SkemaKontrol::OpretOgLaegLektion(string HoldID, string FagID, string LaererID,
                              string LokaleID, int blok, int col, int row)
{
    lPtr.indsaet(HoldID, FagID, LaererID, LokaleID, blok);

    //hvis skemaerne findes til de enkelte ID'er
    if(HentSkemaPtr(lPtr))
    {
      k.indsaet(col, row);
      LaegLektion(lPtr, s, k, 1);
      return true;
    }
    return false;
}//
///Funktionen vurdere om en prioritets lektion kan placeres på lærer skemaet.
bool SkemaKontrol::VurderOgLaegPLektion(string LaererID, int prioritet, int col, int row)
{
	if(KontrollerKoordinat(col, row))
      if(LS.HentSkema(LaererID, s.Lskema))
        return s.Lskema->LaegPLektion(prioritet, col, row);
    return false;
}//
///Funktionen opretter et nyt skema dersom det ikke allerede er oprettet
bool SkemaKontrol::OpretSkema(const string& ID, char type)
{
    switch(type)
    {
	  case 'h': //hold
        return HS.NytSkema(ID);
      case 'l': //laerer
        return LS.NytSkema(ID);
      case 'k': //lokale
        return LOS.NytSkema(ID);
    }
    return false;
}//
//-----------------------------Asscess funktioner-----------------------------//
///Funktionen henter det skema som hører til ID'et.
//Alt efter om skemaet eksistere returneres en sandhedsværdi.
bool SkemaKontrol::HentSkema(const string& ID, stack<LektionsData*>* Stack, char type)
{
    switch(type)
    {
      case 'h':
        if(HS.HentSkema(ID, s.Hskema)) //hvis skemaet findes.
        {
          s.Hskema->FyldSkemaPaaStack(*Stack);
          return true;
        }
        break;
      case 'l':
        comm << ID;
        if(LS.HentSkema(ID, s.Lskema))
        {
          s.Lskema->FyldSkemaPaaStack(*Stack);
          return true;
        }
        break;
      case 'k':
        if(LOS.HentSkema(ID, s.LOskema))
        {
          s.LOskema->FyldSkemaPaaStack(*Stack);
          return true;
        }
        break;
    }
    return false;
}//
///Funktionen henter det næste skema i rækken.
///Alt efter om der er flere skemaer på listen returneres en sandhedsværdi.
bool SkemaKontrol::HentNaesteSkema(stack<LektionsData*>& Stack, char type)
{
    switch(type)
    {
      case 'h':
        if(HS.HentNaesteSkema(s.Hskema)) //findes skemaet?
        {
          s.Hskema->FyldSkemaPaaStack(Stack);
          return true;
        }
        break;
      case 'l':
        if(LS.HentNaesteSkema(s.Lskema))
        {
          s.Lskema->FyldSkemaPaaStack(Stack);
          return true;
        }
        break;
      case 'k':
        if(LOS.HentNaesteSkema(s.LOskema))
        {
          s.LOskema->FyldSkemaPaaStack(Stack);
          return true;
        }
        break;
    }
    return false;
}//
///Funktionen henter næste prioritets skemaerne på lærer listen.
///Alt efter om der er flere tilbage returneres en sandhedsværdi.
bool SkemaKontrol::HentNaestePSkema(stack<PLektionsData*>& Stack, string& LaererID)
{
    if(LS.HentNaesteSkema(s.Lskema))
    {
      LaererID = s.Lskema->ID;
      s.Lskema->HentPSkema(Stack);
      return true;
    }
    return false;
}//
///Funktionen henter en bestemt læreres prioritets skema.
bool SkemaKontrol::HentPSkema(stack<PLektionsData*>& Stack, const string& LaererID)
{
    if(LS.HentSkema(LaererID, s.Lskema))
    {
      s.Lskema->HentPSkema(Stack);
      return true;
    }
    return false;
}//
//--------------------------------access funktioner---------------------------//
///Funktionen sletter alle skemaer.!
void SkemaKontrol::SletAlt()
{
	HS.SletAlt(1);
    LS.SletAlt(0);
    LOS.SletAlt(0);
}//
///Funktionen resetter cursoren ude i listerne. Benyttes inden indlæsningen
///af alle skemaer i en bestemt type.
void SkemaKontrol::Reset(char type)
{
    switch(type)
    {
      case 'h': HS.reset();
        break;
      case 'l': LS.reset();
        break;
      case 'k': LOS.reset();
        break;
    }
}//
///Funktionen vurdere om lektionen i koordinatet på et givent skema er tom.
bool SkemaKontrol::ErLektionTom(string ID, char type, int col, int row)
{
    if(KontrollerKoordinat(col, row))
    {
      switch(type)
      {
        case 'h': //hold
          if(HS.HentSkema(ID, s.Hskema))
            return s.Hskema->ErTom(col, row);
          break;
        case 'l': //laerer
          if(LS.HentSkema(ID, s.Lskema))
            return s.Lskema->ErTom(col, row);
          break;
        case 'k': //lokale
          if(LOS.HentSkema(ID, s.LOskema))
            return s.LOskema->ErTom(col, row);
          break;
      }
    }
    return false;
}//
///Funktionen vurdere om den pågældende lektion på et givent skema i et
///givent koordinat passer med det overførte FagID.
bool SkemaKontrol::ErFagLektion(string HoldID, string FagID, int col, int row)
{
    if(KontrollerKoordinat(col, row))
      if(HS.HentSkema(HoldID, s.Hskema))
        s.Hskema->ErFagLektion(FagID, col, row);
    return false;
}//
///Funktionen vurdere om lektionen i et bestemt koordinat på et givent skema
///er en dobbelt lektion.
bool SkemaKontrol::ErLektionDobbelt(string ID, char type, int col, int row)
{
    bool ErTom = false;
    if(KontrollerKoordinat(col, row))
    {
      k.indsaet(col, row);
      if(Initialiser(ID, lPtr, s, type, col, row, ErTom))
        return ErDobbeltLektion(s, k);
    }
    return false;
}//
bool SkemaKontrol::Initialiser(string ID, lektion& Ptr, SkemaPtr& s, char type,
								int col, int row, bool& ErTom)
{
    ErTom = false;
    switch(type)
    {
      case 'h': //hold
        if(HS.HentSkema(ID, s.Hskema))
        {
          if(s.Hskema->HentLektion(Ptr, col, row))
            return LS.HentSkema(Ptr.LaererID, s.Lskema) &&
                   LOS.HentSkema(Ptr.LokaleID, s.LOskema) &&
                   GodkendLektion(Ptr, s, col, row);
          else
          {
            ErTom = true;
            return false;
          }
        }
        break;
      case 'l': //laerer
        if(LS.HentSkema(ID, s.Lskema))
        {
          if(s.Lskema->HentLektion(Ptr, col, row))
            return HS.HentSkema(Ptr.HoldID, s.Hskema) &&
                   LOS.HentSkema(Ptr.LokaleID, s.LOskema) &&
                   GodkendLektion(Ptr, s, col, row);
          else
          {
            ErTom = true;
            return false;
          }
        }
        break;
      case 'k': //lokale
        if(LOS.HentSkema(ID, s.LOskema))
        {
          if(s.LOskema->HentLektion(Ptr, col, row))
            return HS.HentSkema(Ptr.HoldID, s.Hskema) &&
                   LS.HentSkema(Ptr.LaererID, s.Lskema) &&
                   GodkendLektion(Ptr, s, col, row);
          else
          {
            ErTom = true;
            return false;
          }
        }
        break;
    }
    return false;
}
bool SkemaKontrol::GodkendLektion(const lektion& Ptr, const SkemaPtr& s, int col, int row)
{
	return s.Hskema->EnsLektion(Ptr, col, row) &&
           s.Lskema->EnsLektion(Ptr, col, row) &&
           s.LOskema->EnsLektion(Ptr, col, row);
}
//------------------------------kontrol funktioner----------------------------//
///Funktionen kontrollere om de lektioner der ligger på hold skemaerne også
///ligger de tilsvarende steder på lærer og lokale skemaerne.
///Antallet af fejl optælles og en sandhedsværdi returneres herfor.
bool SkemaKontrol::KontrollerSkemaer(int& fejl, char type)
{
    stack<LektionsData*> Stack;
    LektionsData* l;
    fejl = 0;
    switch(type)
    {
      case 'h':
        HS.reset();
        while(HS.HentNaesteSkema(s.Hskema))
          s.Hskema->FyldSkemaPaaStack(Stack);
        break;
      case 'l':
        LS.reset();
        while(LS.HentNaesteSkema(s.Lskema))
          s.Lskema->FyldSkemaPaaStack(Stack);
        break;
      case 'k':
        LOS.reset();
        while(LOS.HentNaesteSkema(s.LOskema))
          s.LOskema->FyldSkemaPaaStack(Stack);
        break;
    }

    while(!Stack.tom())
    {
      l = Stack.pop();

      switch(type)
      {
        case 'h':
          if(HS.HentSkema(l->HoldID, s.Hskema))
             if(!s.Hskema->EnsLektion(l->HoldID, l->FagID,
                l->LaererID, l->LokaleID, l->Blok, l->col, l->row))
               fejl++;
          break;
        case 'l':
          if(LS.HentSkema(l->LaererID, s.Lskema))
           if(!s.Lskema->EnsLektion(l->HoldID, l->FagID,
               l->LaererID, l->LokaleID, l->Blok, l->col, l->row))
              fejl++;
          break;
        case 'k':
          if(LOS.HentSkema(l->LokaleID, s.LOskema))
            if(!s.LOskema->EnsLektion(l->HoldID, l->FagID,
                l->LaererID, l->LokaleID, l->Blok, l->col, l->row))
              fejl++;
          break;
      }
      delete l;
    }
    return fejl == 0;

}//
///Funktionen vurdere om en given lektion er en dobbelt lektion på 3 givne
///skemaer i et bestemt koordinat.
bool SkemaKontrol::ErDobbeltLektion(const SkemaPtr& s, const koord& k)
{
    return(s.Hskema->ErDobbelt(k.col, k.row) &&
           s.Lskema->ErDobbelt(k.col, k.row) &&
           s.LOskema->ErDobbelt(k.col, k.row));
}//
///Funktionen vurdere om en lektion er tom i et givent koordinat på 3 bestemte
///skemaer.
bool SkemaKontrol::ErLektionTom(const SkemaPtr& s, const koord& k, int blok)
{
    bool ok = true;
    int i;
    for(i = 0; ok && i < blok; i++)
      ok = (s.Hskema->ErTom(k.col, k.row+i) &&
            s.Lskema->ErTom(k.col, k.row+i) &&
            s.LOskema->ErTom(k.col, k.row+i));

    if(ok && i == blok)
      return true;
    return false;
}//
//---------------------------basis funktioner---------------------------------//
///Funktionen henter en lektion på et givent skema i et bestemt koordinat
///Alt efter om lektionen eksistere returneres en sandhedsværdi.
bool SkemaKontrol::HentLektion(lektion& Ptr, const SkemaPtr& s, const koord& k)
{
    if(!s.Hskema->HentLektion(Ptr, k.col, k.row))
      if(!s.Lskema->HentLektion(Ptr, k.col, k.row))
        if(!s.LOskema->HentLektion(Ptr, k.col, k.row))
          return false;
    return true;
}//
///Funktionen vurdere om en bestemt lektion kan placeres på 3 givne skemaer i et
///bestemt koordinat. Alt efter dette returneres en sandhedsværdi.
bool SkemaKontrol::VurderLektion(const lektion& ptr, const SkemaPtr& s, const koord& k,
                         int blok)
{
    bool ok = true;
    int i;
    for(i = 0; i < blok && ok; i++)
      ok = (s.Hskema->Vurder(ptr, k.col, k.row+i) &&
            s.Lskema->Vurder(k.col, k.row+i) &&
            s.LOskema->Vurder(k.col, k.row+i));
    if(ok && i == blok)
      return true;
    return false;
}//
///Funktionen henter en lektions skema pointere ind i den private variabel s.
bool SkemaKontrol::HentSkemaPtr(const lektion& ptr)
{
    return LOS.HentSkema(ptr.LokaleID, s.LOskema) &&
           LS.HentSkema(ptr.LaererID, s.Lskema) &&
           HS.HentSkema(ptr.HoldID, s.Hskema);
}//
///Funktionen lægger en bestemt lektion på 3 givne skemaer, i et bestemt koordinat
///i et bestemt antal der svarere til blok størrelsen af denne.
void SkemaKontrol::LaegLektion(const lektion& ptr, const SkemaPtr& s,
                       const koord& k, int blok)
{
    for(int i = 0; i < blok; i++)
      s.Hskema->LaegLektion(ptr, *s.Lskema, *s.LOskema, k.col, k.row+i);
}//
///Funktionen sletter en lektion på 3 givne skemaer i et bestemt koordinat.
void SkemaKontrol::SletLektion(const SkemaPtr& s, const koord& k, int blok)
{

    for(int i = 0; i < blok; i++)
    {
      s.Hskema->SletLektion(k.col, k.row+i);
      s.Lskema->SletLektion(k.col, k.row+i);
      s.LOskema->SletLektion(k.col, k.row+i);
    }
}//
//-----------------------Optællingsberegnings funktioner----------------------//
///Funktionen beregner og returnere det totale antal af lagte lektioner på alle
///hold skemaerne.
int SkemaKontrol::BeregnTotaleLagteLektioner()
{
	int sum(0);
    HS.reset(); //hold listen resettes.
    while(HS.HentNaesteSkema(s.Hskema))
      sum += s.Hskema->OptaelAlleLektioner();
    return sum;
}//
///Funktionen beregner variansen for et givent skema.!
double SkemaKontrol::BeregnVariansFor(const string& ID, char type)
{
    switch(type)
    {
      case 'h':
        if(HS.HentSkema(ID, s.Hskema))
          return s.Hskema->BeregnVarians();
        break;
      case 'l':
        if(LS.HentSkema(ID, s.Lskema))
          return s.Lskema->BeregnVarians();
        break;
      case 'k':
        if(LOS.HentSkema(ID, s.LOskema))
          return s.LOskema->BeregnVarians();
        break;
    }
    return 0;
}//
/*
double SkemaKontrol::TotaleVarians()
{
    Varians V;
    V.Nulstil();
    HS.reset();
    while(HS.HentNaesteSkema(s.Hskema))
      V.Indsaet(s.Hskema->BeregnVarians());
    return V.BeregnVarians();
} */
///Funktionen optæller det totale antal af mellem lektioner på alle hold skemaer
int SkemaKontrol::AntalMellemLektioner()
{
    int sum(0);
    HS.reset();
    while(HS.HentNaesteSkema(s.Hskema))
      sum += s.Hskema->AntalMellemLektioner();
    return sum;
}//
///Funktionen beregner og returnere antallet af lagte lektioner for et givent
///skema.
int SkemaKontrol::SkemalagteLektioner(string ID, char type)
{
	switch(type)
    {
      case 'h': //Hold
        if(HS.HentSkema(ID, s.Hskema))
          return s.Hskema->OptaelAlleLektioner();
        break;
      case 'l': //Laerer
        if(LS.HentSkema(ID, s.Lskema))
          return s.Lskema->OptaelAlleLektioner();
        break;
      case 'k': //lokaler
        if(LOS.HentSkema(ID, s.LOskema))
          return s.LOskema->OptaelAlleLektioner();
        break;
    }
    return 0;
}//
///Funktionen beregner antallet af lagte fag lektioner for et givent hold.
int SkemaKontrol::LagteFagLektioner(string HoldID, string FagID)
{
	if(HS.HentSkema(HoldID, s.Hskema))
      return s.Hskema->OptaelFagLektion(FagID);
	return 0;
}//
///Funktionen beregner antallet af prioriteter på -3 på et bestemt lærer skema.
int SkemaKontrol::LagtePLektioner(string LaererID)
{
   if(LS.HentSkema(LaererID, s.Lskema))
      return s.Lskema->OptaelPrioriteredeLektioner();
    return 0;
}//
//---------------------------Kontrol af Koordinater---------------------------//
///Funktionen konstrollere koordinatsættet, om de ligger inden for de ydre grænser.
bool SkemaKontrol::KontrollerKoordinat(const koord& k, const int& blok)
{
    bool ok = true;
    int i;
    for(i = 0; ok && i < blok; i++)
	 ok = (k.col >= 0 && k.col < user_max_col &&
           k.row+i >= 0 && k.row+i < user_max_row);

    if(ok && i == blok)
      return true;
    else
      return false;
}//
///Funktionen konstrollere koordinatsættet, om de ligger inden for de ydre grænser
inline bool SkemaKontrol::KontrollerKoordinat(const koord& k)
{
	return(k.col >= 0 && k.col < user_max_col && k.row >= 0 && k.row < user_max_row);
}//
///Funktionen konstrollere koordinatsættet, om de ligger inden for de ydre grænser
inline bool SkemaKontrol::KontrollerKoordinat(const int& col, const int& row)
{
	return(col >= 0 && col < user_max_col && row >= 0 && row < user_max_row);
}//
//------------------------------Udskrivs funktioner---------------------------//
///Funktionen udskriver alle skemaer til en konsol.
void SkemaKontrol::UdskrivAlleSkemaer()
{
	HS.Udskriv();
    getch();
    LS.Udskriv();
    getch();
    LOS.Udskriv();
}//
///Funktionen udskriver et bestemt skema til en konsol.
void SkemaKontrol::UdskrivSkema(const string& ID, char type)
{
    switch(type)
    {
      case 'h':
        if(HS.HentSkema(ID, s.Hskema))
          s.Hskema->Udskriv();
        break;
      case 'l':
        if(LS.HentSkema(ID, s.Lskema))
          s.Lskema->Udskriv();
        break;
      case 'k':
        if(LOS.HentSkema(ID, s.LOskema))
          s.LOskema->Udskriv();
        break;
    }
}//
///Funktionen udskriver en bestemt læreres prioriterings skema.
void SkemaKontrol::UdskrivPSkema(const string& ID)
{
	if(LS.HentSkema(ID, s.Lskema))
      s.Lskema->UdskrivPSkema();
}//
//----------------------------------------------------------------------------//
//konstruktør
SkemaKontrol::SkemaKontrol(int user_max_col_, int user_max_row_)
{
    if(user_max_col_ <= max_col && user_max_col_ >= 0 &&
       user_max_row_ <= max_row && user_max_row_ >= 0)
    {
	  user_max_col = user_max_col_;
      user_max_row = user_max_row_;
    }
    else
    {
      user_max_col = max_col;
      user_max_row = max_row;
    }
}//
//----------------------------------------------------------------------------//












