
// Agent.java
// Andrew Davison, ad@coe.psu.ac.th, May 2023

/* The Cigarette smokers problem:
  https://en.wikipedia.org/wiki/Cigarette_smokers_problem

  The agent allows the smokers to make 
  their cigarettes by arbitrarily placing
  two supplies to place on the table repeatedly. 

  This is implemented using a tuple of the form:
     ("SUPPLIES", supplyNo, ingredient1.value + ingredient2.value)

  Each ingredient has an integer value (see Supplies.java) which
  gives a unique single value when added to another ingredient value
       TOBACCO == 1
       PAPER == 2
       MATCHES == 4

  The 'supplyNo' argument isn't needed by the algorithm. It just
  records how many times the agent had put ingredients on the table.

  After placing ingredients on the table, the agent waits for a 
  smoker to finish by looking for a tuple:
          ("FIN", smoker name, supplyNo)

  Usage:
    > compile.bat Agent.java

    Part of the application made up of:
       * CigSmokers.java
       * Smoker.java
       * Agent.java
       * Supplies.java
*/


import java.util.*;

import org.jspace.*;


public class Agent implements Runnable
{
  private int pasID;
  private PrintAreas pas;
  private Space table;

  private Random rand = new Random();


  public Agent(PrintAreas pas, int pasID, Space s)
  {
    this.pasID = pasID;
    this.pas = pas;
    pas.setTitle(pasID, "Agent");
    table = s;
  }  // end of Agent()


  public void run()
  {
    int supplyNo = 1;  // no. of times agent has supplied ingredients 
    try {
      while (true) {
        /* randomly choose between three possible pairs of
           supplies to place on the table */
        int selector = rand.nextInt(3);
        if (selector == 0) {
          pas.println(pasID, "s" + supplyNo + ": " +
             Supplies.PAPER + ", " +  Supplies.TOBACCO);  // paper,tobacco
          table.put("SUPPLIES", supplyNo,
                                Supplies.PAPER.getValue() + 
                                Supplies.TOBACCO.getValue());
        }
        else if (selector == 1) {
          pas.println(pasID, "s" + supplyNo + ": " +
             Supplies.PAPER + ", " +  Supplies.MATCHES); //paper,matches
          table.put("SUPPLIES", supplyNo,
                                Supplies.PAPER.getValue() + 
                                Supplies.MATCHES.getValue());
        }
        else if (selector == 2) {
          pas.println(pasID, "s" + supplyNo + ": " +
             Supplies.MATCHES + ", " +  Supplies.TOBACCO); //matches,tobacco
          table.put("SUPPLIES", supplyNo,
                                Supplies.MATCHES.getValue() + 
                                Supplies.TOBACCO.getValue());
        }
        supplyNo++;

        // wait for a smoker to finish
        Object[] smokerObj = table.get( 
                              new ActualField("FIN"), 
                              new FormalField(String.class),
                              new FormalField(Integer.class));
        String smokerNm = (String)smokerObj[1];
        int supply = (int)smokerObj[2];
        pas.println(pasID, smokerNm + " done with s" + supply);
      }
    }
    catch (InterruptedException e) 
    {  pas.println(pasID, "Error: " + e);  }
  } /* run */


}  // end of Agent class
