with os2.jba; use os2.jba;
with Society; use Society;
with Calendar;
with Phil ;
with text_io; use text_io;
with builtin; use builtin;
pragma Elaborate (Phil);
package body Room is

  -- Dining Philosophers, Ada 95 edition
  -- A PM  version of the Room package
  -- Michael B. Feldman, The George Washington University,July, 1995.
  -- Leonid  B. Dulman ," Des" inc, Hadera Israel, April, 1997

  type Philosopher_Ptr is access all Phil.Philosopher;

  Phils      : array (1..Table_Size) of Philosopher_Ptr;
  Phil_Seats : array (1..Table_Size) of Unique_DNA_Codes ;
  Phil_Lines : array (1..Table_Size) of Unique_DNA_Codes := (others => 1);
  num,pos    :                          Unique_DNA_Codes ;
  temp       : str35;
  clean      : constant str35 := (others => '.');
  procedure Report_Line(num:in out Unique_DNA_Codes ) is
  begin
     num := (num  mod 3) + 1 ;
  end Report_Line;
  procedure Report_String(s:string) is
  len : integer ;
  begin
    len := s'length;
    if len > clean'length  then temp := left(s,temp'length);
                           else overlay(temp,1,s);
    end if;
  end;
  task body TMaitre_D is

  -- philosophers sign into dining room, giving Maitre_D their DNA code

    T          : Natural;
    Start_Time : Calendar.Time;

  begin
    accept Start_Serving;

    Start_Time := Calendar.Clock;

    -- now Maitre_D assigns phils to seats at the table

    Phils(1):= new phil.Philosopher; -- Dijkstra'Access;
    Phils(2):= new phil.Philosopher; --Anderson'Access;
    Phils(3):= new phil.Philosopher; --Taft'Access;
    Phils(4):= new phil.Philosopher; --Ichbiah'Access;
    Phils(5):= new phil.Philosopher; --Stroustrup'Access ;

    Phil_Seats   := (1, 3, 5, 4, 2);   -- which seat each phil occupies

    -- and assigns them their chopsticks.

    Phils ( 1).Start_Eating (1, 2);
    Phils ( 3).Start_Eating (3, 4);
    Phils ( 2).Start_Eating (2, 3);
    Phils ( 5).Start_Eating (1, 5);
    Phils ( 4).Start_Eating (4, 5);
    loop
      select
        accept Report_State (Which_Phil : in Society.Unique_DNA_Codes;
                             State      : in Phil.States;
                             How_Long   : in Natural := 0;
                             Which_Meal : in Natural := 0) do
    new_line;put(" Report_State ");
          T := Natural (Calendar."-" (Calendar.Clock, Start_Time));
          num  := Phil_Seats(Which_Phil);
          pos  := Phil_Lines(Which_Phil) ;
          temp := clean;
    put_edit(" philosoph ",num,2); put_edit(" pos", pos,2);

          case State is
            when Phil.Breathing =>
     put(" Breathing");
              Report_String( Integer'Image (T) & " Breathing...");
              society.common_write.writer(temp,num,pos);
              for i in pos+1..3 loop  society.common_write.writer(clean,num,i); end loop;
              Report_Line(Phil_Lines(Which_Phil));

            when Phil.Thinking =>
     put(" Thinking");
                Report_String(Integer'Image (T) & " Thinking"
                         & Integer'Image (How_Long) & " seconds.");
              society.common_write.writer(temp,num,pos);
              for i in pos+1..3 loop  society.common_write.writer(clean,num,i); end loop;
              Report_Line(Phil_Lines(Which_Phil));

            when Phil.Eating =>
     put(" Eating");
              Report_String(Integer'Image (T) & " Meal"
                       & Integer'Image (Which_Meal) & ","
                       & Integer'Image (How_Long) & " seconds.");
              society.common_write.writer(temp,num,pos);
              for i in pos+1..3 loop  society.common_write.writer(clean,num,i); end loop;
              Report_Line(Phil_Lines(Which_Phil));

            when Phil.Done_Eating =>
     put(" Done_Eating");
             Report_String( Integer'Image (T)  & " Yum-yum (burp)");
              society.common_write.writer(temp,num,pos);
              for i in pos+1..3 loop  society.common_write.writer(clean,num,i); end loop;
              Report_Line(Phil_Lines(Which_Phil));

            when Phil.Got_One_Stick =>
     put(" Got_One_Stick");
              Report_String(Integer'Image (T) & " First chopstick"
                      & Integer'Image (How_Long));
              society.common_write.writer(temp,num,pos);
              for i in pos+1..3 loop  society.common_write.writer(clean,num,i); end loop;
              Report_Line(Phil_Lines(Which_Phil));

            when Phil.Got_Other_Stick =>
     put(" Got_Other_Stick");
              Report_String(Integer'Image (T) & " Second chopstick"
                      & Integer'Image (How_Long));
              society.common_write.writer(temp,num,pos);
              for i in pos+1..3 loop  society.common_write.writer(clean,num,i); end loop;
              Report_Line(Phil_Lines(Which_Phil));

            when Phil.Dying =>
     put(" Dying");
              Report_String(Integer'Image (T) & " Croak");
              society.common_write.writer(temp,num,pos);
              for i in pos+1..3 loop  society.common_write.writer(clean,num,i); end loop;
              Report_Line(Phil_Lines(Which_Phil));
          end case; -- State

        end Report_State;
      or
        terminate;
      end select;
    end loop;
  end TMaitre_D;
end Room;
