http://www.adaconcept.com/programs/ontozorendszeres_szimulacio/szimulacio-ontozorendszer-terv.adb
with Ada.Text_IO;  -- "teszteleshez"
with Hiba_Kezelo;

package body Szimulacio.Ontozorendszer.Terv is


   function Cso_Csatlakozasok return Terv_Tipus is
   begin
      return P;
   end Cso_Csatlakozasok;


   function Gyokertol_Mert_Tavolsag(VR : Valodi_Reszletpont_Azonosito_Tipus) return Natural is
      akt : Reszletpont_Azonosito_Tipus;

      Vissza : Natural := 0;
   begin

      akt := Cso_Csatlakozasok(VR);
      while akt /= Reszletpont_Azonosito_Tipus'First loop
         akt := Cso_Csatlakozasok(akt);
         Vissza := Vissza + 1;
      end loop;

      return Vissza;
   end Gyokertol_Mert_Tavolsag;


   function Vizforrastol_Mert_Tavolsag(VR : Valodi_Reszletpont_Azonosito_Tipus) return Natural renames Gyokertol_Mert_Tavolsag;  -- ilyet is lehet


   function Kifok(VR : Valodi_Reszletpont_Azonosito_Tipus) return Natural is
      Csatlakozasok : constant Terv_Tipus := Cso_Csatlakozasok;

      Vissza :  Natural :=  0;
   begin

      for V in Csatlakozasok'Range loop
         if Csatlakozasok(V) = VR then
            Vissza := Vissza + 1;
         end if;
      end loop;

      return Vissza;
   end Kifok;



   function Cso_Csatlakozasok(VR : Valodi_Reszletpont_Azonosito_Tipus) return Cso_Csatlakozasok_Tomb_Tipus is
      Csatlakozasok : constant Terv_Tipus := Cso_Csatlakozasok;

      Vissza : Cso_Csatlakozasok_Tomb_Tipus(1 .. Kifok(VR)) := (others => Valodi_Reszletpont_Azonosito_Tipus'First);  -- ha kivetelt szeretnenk kezelni az ilyen hivasokat nagyon gondoljuk at
      vm : Natural range 0 .. Kifok(VR) := 0;
   begin

      for U in Csatlakozasok'Range loop
         if Csatlakozasok(U) = VR then
            Vissza(vm + 1) := U;
            vm := vm + 1;
         end if;
      end loop;

      return Vissza;
   end Cso_Csatlakozasok;


   procedure Szomszedsagi_Matrix_Inicializalasa(Szogpontok : Reszletpont_Tomb_Tipus) is

      function Szomszedos_Pontok(A, B : Reszletpont_Tipus) return Boolean is
         --   .....
         --   ..B..
         --   .BAB.
         --   ..B..
         --   -----
      begin
         return ( abs (A.Y_Koordinata - B.Y_Koordinata) = 1 and (A.X_Koordinata - B.X_Koordinata) = 0) xor
                ( abs (A.X_Koordinata - B.X_Koordinata) = 1 and (A.Y_Koordinata - B.Y_Koordinata) = 0);
      end Szomszedos_Pontok;

   begin

      for i in Szogpontok'First .. Szogpontok'Last - 1 loop

         for j in Szogpontok'First + 1 .. Szogpontok'Last loop
            if Szomszedos_Pontok(Szogpontok(i), Szogpontok(j)) then
               Szomszedsagi_Matrix(i, j) := 1;
               Szomszedsagi_Matrix(j, i) := 1;
            end if;
         end loop;

      end loop;

   end Szomszedsagi_Matrix_Inicializalasa;


   function Gyoker(Szogpontok : Reszletpont_Tomb_Tipus) return Valodi_Reszletpont_Azonosito_Tipus is
      use type Kert.Terv_Elemek_Tipus;
   begin

      for i in Szogpontok'Range loop
         if Kert.Terv(Szogpontok(i).X_Koordinata, Szogpontok(i).Y_Koordinata) = Kert.Vizforras then
            return i;
         end if;
      end loop;

      -- Ez nem lehetseges, mert biztosan van egy vizforras
      Hiba_Kezelo.Program_Leallitas("Tervezesi hiba!!!");
      return Szogpontok'First;
   end Gyoker;


   -- A vizforras helyetol fogjuk felepiteni majd a feszitofat
   function Vizforras(Szogpontok : Reszletpont_Tomb_Tipus) return Positive renames Gyoker;


   procedure Prim(Start_Csucs : Valodi_Reszletpont_Azonosito_Tipus) is

      function Van_Nem_Kesz_Csucs return Boolean is
      begin
         for i in Kesz_Tomb'Range loop
            if Kesz_Tomb(i) = False then
               return True;
            end if;
         end loop;

         return False;
      end Van_Nem_Kesz_Csucs;


      -- felteteles maximum kereses
      function Legkozelebbi_Meg_Nem_Kesz_Csucs return Valodi_Reszletpont_Azonosito_Tipus is
         Min : Reszletpont_Azonosito_Tipus := Reszletpont_Azonosito_Tipus'First;
         Voltmin : Boolean := False;
         Aktmin : Elsuly_Tipus := Vegtelen_Elsuly;
      begin

         for i in Valodi_Reszletpont_Azonosito_Tipus loop

            if Kesz_Tomb(i) = False then
               -- meg nincs kesz a csucs
               if not Voltmin then
                  aktmin := D(i);
                  Min := i;
                  Voltmin := True;
               else
                  if Aktmin > D(i) then
                     Aktmin := D(i);
                     Min := i;
                  end if;
               end if;
            end if;

         end loop;

         return Min;
      end Legkozelebbi_Meg_Nem_Kesz_Csucs;

      u : Valodi_Reszletpont_Azonosito_Tipus;

   begin

      Kesz_Tomb := (others => False);
      D := (others => Vegtelen_Elsuly);
      P := (others => Nincs_Szulo);

      D(Start_Csucs) := Elsuly_Tipus'First;


      while Van_Nem_Kesz_Csucs loop
         u := Legkozelebbi_Meg_Nem_Kesz_Csucs;
         Kesz_Tomb(u) := True;                                       -- kozelebb kerulunk a ciklus leallasanak idejehez

         for v in Valodi_Reszletpont_Azonosito_Tipus loop
            if Szomszedsagi_Matrix(u, v) /= Elsuly_Tipus'First then
               if Kesz_Tomb(v) = False then
                  if Szomszedsagi_Matrix(u, v) < D(v)  then
                     D(v) := Szomszedsagi_Matrix(u, v);
                     P(v) := Reszletpont_Azonosito_Tipus(u);
                  end if;
               end if;
            end if;
         end loop;

      end loop;


      -- Ha a graf nem osszefuggo megszakitjuk a szimulaciot!!!
      Osszefuggoseg_Ellenorzes:
      declare
         Szulo_Nelkuli_Csucsok_Szama : Natural := 0;
      begin
         for i in P'Range loop
            if P(i) = Nincs_Szulo then
               Szulo_Nelkuli_Csucsok_Szama := Szulo_Nelkuli_Csucsok_Szama + 1;
            end if;
         end loop;

         if Szulo_Nelkuli_Csucsok_Szama /= 1 then
            -- "csak a vizforrasnak nem lehet szuloje..."
            Hiba_Kezelo.Program_Leallitas("A vizforrastol nem lehet mindenhova eljutni.");
         end if;
      end Osszefuggoseg_Ellenorzes;



      -- "teszteleshez", (mar tudunk irni tesztelo gyerekcsomagot, ezert ettol most eltekintunk...)

      Ada.Text_IO.Put_Line("Kapcsolatok:");
      for v in Valodi_Reszletpont_Azonosito_Tipus loop
         Ada.Text_IO.Put_Line(Reszletpont_Azonosito_Tipus'Image(P(v)) & " -> " & Valodi_Reszletpont_Azonosito_Tipus'Image(v));
      end loop;

   end Prim;


begin

   -- elaboracios idoben kiszamoljuk a feszitofat
   Szomszedsagi_Matrix_Inicializalasa(Reszletpontok);
   Prim(Vizforras(Reszletpontok));

end Szimulacio.Ontozorendszer.Terv;