Project 3 - Sample code

By: Nicholas Duchon, July 13, 2014

Here is some code that you should find helpful in getting started with Project 3.



There are LOTS of issues still to be resolved, and for the most part, you cannot just copy this code, but you should try to understand what this code is doing, and how you might want to change it for your own project, and the requirements of Project 3.

// File: Cave2.java
// Date: Feb 12, 2012
// Author: Nicholas Duchon
// Semester project

// Date file formats:
// Parties format:
//    p:<index>:<name>
// Creatures format:
//    c:<index>:<type>:<name>:<party>:<empathy>:<fear>:<carrying capacity>
// Treasures format:
//    t:<index>:<type>:<creature>:<weight>:<value>
//       creature = 0 means noone is carrying that treasure at the moment
// Artifacts format:
//    a:<index>:<type>:<creature>[:<name>]
// Jobs for creatures format:
//    j:<index>:<name>:<creature index>:<time>[:<required artifact type>:<number>]*
//       measure time in seconds

import java.util.ArrayList;
import java.util.Scanner;
import java.util.HashMap;
import java.util.Random;
import java.io.File;
import java.io.FileNotFoundException;
import javax.swing.JProgressBar;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import javax.swing.SwingConstants;
import java.awt.GridLayout;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class Cave2 {
  ArrayList <Party>    parties = new ArrayList <Party>    (); // the parties
  ArrayList <Creature> loners  = new ArrayList <Creature> (); // creatures not in parties
  ArrayList <Treasure> drops   = new ArrayList <Treasure> (); // Treasures not carried
  ArrayList <Artifact> magics  = new ArrayList <Artifact> (); // Artifacts not carried
  ArrayList <Job>      jobs    = new ArrayList <Job>      (); // Jobs to be performed
 
  JFrame    jf   = new JFrame ();
  JPanel    jrun = new JPanel ();
  JTextArea jta  = new JTextArea (10, 10);

  // hashmap of everything by index
  HashMap <Integer, CaveElement> hmElements = new HashMap <Integer, CaveElement> ();
 
  public Cave2 () {
    Scanner sf = null;
    String fileName = "dataC.txt";
    try {
      //      sf = new Scanner (new File (fileName));
      // getResourceAsStream is the way to access a data file in a jar package file
      // this works in general, so leave it here as is.
      sf = new Scanner (getClass().getResourceAsStream (fileName));
    }
    catch (Exception e) {
      System.out.println (e + "\nFile bummer: " + fileName);
    } // end open file try/catch block
    if (sf == null)
      return;

    readFile (sf);

    jta.setText (toString ());
    jf.setTitle ("Cave2");
    jf.add (jrun, BorderLayout.PAGE_END);
    jrun.setLayout (new GridLayout (0, 5, 2, 5));
    jf.add (new JScrollPane (jta), BorderLayout.CENTER);
    jta.setFont (new Font ("Monospaced", 0, 12));
    jf.pack ();
    jf.setVisible (true);
    jf.setLocationRelativeTo (null);
  } // end no-parameter constructor
 
  public static void main (String args []) {
    Cave2 cv = new Cave2 ();
    cv.jf.add (new JLabel (" Close this window to end program "), BorderLayout.PAGE_START);
    cv.jf.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
//     System.out.println (cv);
  } // end main
 
  public String toString () {
    String sb = "";
    sb += toString (parties, "Party List");
    sb += toString (loners , "Unaligned Creatures");
    sb += toString (drops  , "Unheld Treasures");
    sb += toString (magics , "Unheld Artifacts");
    sb += toString (jobs   , "Jobs");
//     sb += toString (hmElements.values (), "HashMap");
    return sb;
 
} // end method dump
 
  String toString (Iterable <? extends CaveElement> it, String label) {
    String sb = "\n----- DUMP " + label + " -------";
    for (CaveElement c: it)
      sb += "\n" + c.toString ();
    return sb;
 
} // end method dump Iterable String
 
  void readFile (Scanner sf) {
    String inline;
    Scanner line;
    while (sf.hasNext()) {
      inline = sf.nextLine().trim();
      if (inline.length() == 0) continue;
      line = new Scanner (inline).useDelimiter ("\\s*:\\s*"); // compress white space also, else nextInt fails
      switch (inline.charAt (0)) {
        case 'p': addParty    (line); break;
        case 'c': addCreature (line); break;
        case 't': addTreasure (line); break;
        case 'a': addArtifact (line); break;
        case 'j': addJob      (line); break;
      } // end switch
    } // end while reading data file
    jf.pack ();
 
} // end readFile
 
  public void addJob (Scanner sc) {
    Job job = new Job (hmElements, jrun, sc);
//     (new Thread (job)).start();
//     jobs.add (job);
 
} // end method addJob
 
  public void addParty (Scanner sc){
    Party pt = new Party (sc);
    parties.add (pt);
    hmElements.put (pt.index, pt);
 
} // end method addParty
 
  public void addCreature  (Scanner sc) {
    Creature c = new Creature ();
    int target = c.makeCreature (sc);
    Party p = (Party)(hmElements.get (target));
    if (p == null)
      loners.add (c);
    else {
      p.addCreature (c);
      c.party = p;
    }
    hmElements.put (c.index, c);
 
} // end method addToParty
 
  public void addTreasure (Scanner sc) {
    Treasure t = new Treasure ();
    int target = t.makeTreasure (sc);
    Creature c = (Creature)(hmElements.get (target));
    if (c == null)
      drops.add (t);
    else {
      c.addTreasure (t);
      t.holder = c;
    }
    hmElements.put (t.index, t);
 
} // end method addTreasure
 
  public void addArtifact (Scanner sc) {
    Artifact a = new Artifact ();
    int target = a.makeArtifact (sc);
    Creature c = (Creature)(hmElements.get (target));
    if (a == null)
      magics.add (a);
    else {
      c.addArtifact (a);
      a.holder = c;
    }
    hmElements.put (a.index, a);
 
} // end method addArtifact

} // end class Cave

class CaveElement {}

// j:<index>:<name>:<creature index>:<time>[:<required artifact type>:<number>]*
class Job extends CaveElement implements Runnable {
  static Random rn = new Random ();
  JPanel parent;
  Creature worker = null;
  int jobIndex;
  long jobTime;
  String jobName = "";
  JProgressBar pm = new JProgressBar ();
  boolean goFlag = true, noKillFlag = true;
  JButton jbGo   = new JButton ("Stop");
  JButton jbKill = new JButton ("Cancel");
  Status status = Status.SUSPENDED;
 
  enum Status {RUNNING, SUSPENDED, WAITING, DONE};

  public Job (HashMap <Integer, CaveElement> hmElements, JPanel cv, Scanner sc) {
    parent = cv;
    sc.next (); // dump first field, j
    jobIndex = sc.nextInt ();
    jobName = sc.next ();
    int target = sc.nextInt ();
    worker = (Creature) (hmElements.get (target));
    jobTime = sc.nextInt ();
    pm = new JProgressBar ();
    pm.setStringPainted (true);
    parent.add (pm);
    parent.add (new JLabel (worker.name, SwingConstants.CENTER));
    parent.add (new JLabel (jobName    , SwingConstants.CENTER));
    
    parent.add (jbGo);
    parent.add (jbKill);
    
    jbGo.addActionListener (new ActionListener () {
      public void actionPerformed (ActionEvent e) {
        toggleGoFlag ();
      }
    });

    jbKill.addActionListener (new ActionListener () {
      public void actionPerformed (ActionEvent e) {
        setKillFlag ();
      }
    });
   
    new Thread (this).start();
 
} // end constructor

//     JLabel jln = new JLabel (worker.name);
//       following shows how to align text relative to icon
//     jln.setHorizontalTextPosition (SwingConstants.CENTER);
//     jln.setHorizontalAlignment (SwingConstants.CENTER);
//     parent.jrun.add (jln);
 
  public void toggleGoFlag () {
    goFlag = !goFlag;
 
} // end method toggleRunFlag
 
  public void setKillFlag () {
    noKillFlag = false;
    jbKill.setBackground (Color.red);
 
} // end setKillFlag
 
  void showStatus (Status st) {
    status = st;
    switch (status) {
      case RUNNING:
        jbGo.setBackground (Color.green);
        jbGo.setText ("Running");
        break;
      case SUSPENDED:
        jbGo.setBackground (Color.yellow);
        jbGo.setText ("Suspended");
        break;
      case WAITING:
        jbGo.setBackground (Color.orange);
        jbGo.setText ("Waiting turn");
        break;
      case DONE:
        jbGo.setBackground (Color.red);
        jbGo.setText ("Done");
        break;
    } // end switch on status
 
} // end showStatus

  public void run () {
    long time = System.currentTimeMillis();
    long startTime = time;
    long stopTime = time + 1000 * jobTime;
    double duration = stopTime - time;
    
    synchronized (worker.party) { // party since looking forward to P4 requirements
      while (worker.busyFlag) {
        showStatus (Status.WAITING);
        try {
          worker.party.wait();
        }
        catch (InterruptedException e) {
        } // end try/catch block
      } // end while waiting for worker to be free
      worker.busyFlag = true;
    } // end sychronized on worker


    while (time < stopTime && noKillFlag) {
      try {
        Thread.sleep (100);
      } catch (InterruptedException e) {}
      if (goFlag) {
        showStatus (Status.RUNNING);
        time += 100;
        pm.setValue ((int)(((time - startTime) / duration) * 100));
      } else {
        showStatus (Status.SUSPENDED);
      } // end if stepping
    } // end runninig

    pm.setValue (100);
    showStatus (Status.DONE);
    synchronized (worker.party) {
      worker.busyFlag = false;
      worker.party.notifyAll ();
    }


 
} // end method run - implements runnable
 
  public String toString () {
    String sr = String.format ("j:%7d:%15s:%7d:%5d", jobIndex, jobName, worker.index, jobTime);
    return sr;
 
} //end method toString
 
} // end class Job

//    p:<index>:<name>
class Party extends CaveElement {
  ArrayList <Creature> members = new ArrayList <Creature> ();
  int index;
  String name;
 
  public Party (Scanner s) {
    s.next (); // dump first field, p
    index = s.nextInt ();
    name  = s.next();
 
} // String constructor
 
  public void addCreature (Creature c) {
    members.add (c);
 
} // end method addCreature
 
  public String toString () {
    String sr = String.format ("p:%6d:%s", index, name);
    for (Creature c: members)
      sr += "\n   " + c;
    return sr;
 
} // end toString method
 
} // end class Party

//    c:<index>:<type>:<name>:<party>:<empathy>:<fear>:<carrying capacity>
class Creature extends CaveElement
// implements Runnable
{
  ArrayList <Treasure> treasures = new ArrayList <Treasure>  ();
  ArrayList <Artifact> artifacts = new ArrayList <Artifact> ();
  int index;
  String type, name;
  Party party = null;
  double empathy, fear, capacity;
  boolean busyFlag = false;
 
  public int makeCreature (Scanner s) {

    int partyInd;
    s.next (); // dump first field, c
    index    = s.nextInt ();
    type     = s.next ();
    name     = s.next ();
    partyInd = s.nextInt ();
    empathy  = s.nextDouble ();
    fear     = s.nextDouble ();
    capacity = s.nextDouble ();

    return partyInd;
 
} // Scanner Creature factory method
 
  public void addTreasure (Treasure t) {treasures.add (t);
}
  public void addArtifact (Artifact a) {artifacts.add (a);
}

//   public void addJob (long t, Scanner sc) {
//     jobTime = t;
//   } // end addJob
 
  public String toString () {
    String sb = "";
    if (party == null)
         sb += String.format ("c:%6d: %s : %s : %6d : %4.1f : %4.1f : %4.1f", index, type, name,           0, empathy, fear, capacity);
    else sb += String.format ("c:%6d: %s : %s : %6d : %4.1f : %4.1f : %4.1f", index, type, name, party.index, empathy, fear, capacity);
    for (Treasure t: treasures) sb += "\n        " + t;
    for (Artifact a: artifacts) sb += "\n        " + a;
    return sb;
 
} // end toString method
} // end class CaveElement

//    t:<index>:<type>:<creature>:<weight>:<value>
class Treasure extends CaveElement {
  int index;
  String type;
  double weight, value;
  Creature holder;
 
  public int makeTreasure (Scanner s) {
    int partyInd;
    s.next (); // dump first field, c
    index    = s.nextInt ();
    type     = s.next ();
    partyInd = s.nextInt ();
    weight   = s.nextDouble ();
    value    = s.nextDouble ();
    return partyInd;
 
} // Scanner Treasure factory method
 
  public String toString () {
    if (holder == null)
    return String.format ("t:%6d: %s : %6d : %4.1f : %4.1f", index, type,            0, weight, value);
    return String.format ("t:%6d: %s : %6d : %4.1f : %4.1f", index, type, holder.index, weight, value);
 
} // end toString method
} // end class Treasure

//    a:<index>:<type>:<creature>[:<name>]
class Artifact extends CaveElement {
  int index;
  String type, name = "";
  Creature holder;
 
  public int makeArtifact (Scanner s) {
    int partyInd;
    s.next (); // dump first field, c
    index    = s.nextInt ();
    type     = s.next ();
    partyInd = s.nextInt ();
    if (s.hasNext()) name     = s.next ();
    return partyInd;
  } // Scanner Artifact factory method
 
  public String toString () {
    if (holder == null)
    return String.format ("a:%6d: %s : %6d : %s", index, type,            0, name);
    return String.format ("a:%6d: %s : %6d : %s", index, type, holder.index, name);
  } // end toString method
} // end class Artifact


End page.