/** The interesting stuff */
    public void action() {

      // increment number of attempts
      attempts++;

      // Don't enlist if adding a subject will exceed the allowed units
      if (schedule.getUnitsObtained() + 3 > (schedule.getWriteIn().getUnitsAllowed())) {
        done = true;
      }

      if (attempts > THRESH || done) {
        return;
      }

      logger.info(getLocalName() + ":" + "Attempting to enlist in " + sub.getName());
      // Search for the enlistor of the subject
      DFAgentDescription template = new DFAgentDescription();
      ServiceDescription sd = new ServiceDescription();
      sd.setType(sub.getName());
      template.addServices(sd);
      try {
        DFAgentDescription[] result = DFService.search(myAgent, template);
        // Ok we got the enlistor
        if (result.length != 0) {
          logger.info(getLocalName() + ": " + sub.getName() + " agent found.");
          enlistorAgent = result[0].getName();

          // Request for sections with available slots at this moment
          msg = new ACLMessage(ACLMessage.REQUEST);
          msg.setContentObject(new EnlistorMessage(ACTION_GET_SECTIONS_WITH_SLOTS, null));
          msg.addReceiver(enlistorAgent);
          send(msg);

          reply = blockingReceive(MessageTemplate.MatchPerformative(ACLMessage.INFORM));
          Vector sections = (Vector) reply.getContentObject();
          // Oops, all sections for this subject are full
          if (sections.size() == 0) {
            logger.info(getLocalName() + ":" + "No slots available for " + sub.getName());
          } else { // ok we have some sections
            // Randomize the sections.
            Collections.shuffle(sections);

            NoConflictConstraint constraint =
                new NoConflictConstraint(schedule.getSectionAssignments());
            // Look for the first section assignment that does not
            // conflict with the current form 5
            for (Iterator ite = sections.iterator(); ite.hasNext(); ) {
              SectionAssignment sectAss = (SectionAssignment) ite.next();
              if (!constraint.isSatisfied(sectAss.getLecture())) {
                // System.out.println(getLocalName()+":"+"Conflict in lecture of
                // "+sectAss.getLecture().getSectionName());
                continue;
              } else if ((sectAss.getLab() != null)
                  && (!constraint.isSatisfied(sectAss.getLab()))) {
                // System.out.println(getLocalName()+":"+"Conflict in lab of
                // "+sectAss.getLab().getSectionName());
                continue;
              } else {
                // Ok no conflict in lab or lecture
                // send message to enlist to this section assingment
                // msg.
                msg = new ACLMessage(ACLMessage.REQUEST);
                msg.setContentObject(new EnlistorMessage(ACTION_ENLIST, sectAss));
                msg.addReceiver(enlistorAgent);
                send(msg);
                reply = blockingReceive(MessageTemplate.MatchPerformative(ACLMessage.INFORM));
                if (reply != null && reply.getContent().equals(MSG_CONFIRM)) {
                  logger.info(
                      getLocalName()
                          + ":"
                          + "enlist to "
                          + sectAss.getSection().getSubject().getName()
                          + " "
                          + sectAss.getSection().getSectionName());
                  schedule.addSectionAssignment(sectAss);

                  done = true;
                }
                break;
              }
            }
          }
        }
      } catch (Exception fe) {
        fe.printStackTrace();
      }
    }
    public void action() {
      // TODO: Implement deliberation of for the next action
      // action=deliberate(Desire, Beliefs);

      switch (action) {
        case ACTION_SEARCH_MAIN_SCHEDULER:
          logger.info(getLocalName() + " searching for main scheduler...");
          DFAgentDescription template = new DFAgentDescription();
          ServiceDescription sd = new ServiceDescription();
          sd.setType("scheduler");
          template.addServices(sd);
          try {
            DFAgentDescription[] result = DFService.search(myAgent, template);
            if (result.length != 0) {
              logger.info(getLocalName() + ":scheduler agent found.");
              schedulerAgent = result[0].getName();
            }
          } catch (FIPAException fe) {
            fe.printStackTrace();
          }
          action = ACTION_GET_FORM5;
          break;
        case ACTION_GET_FORM5:
          try {
            logger.info(getLocalName() + " requesting for Form 5..");
            msg = new ACLMessage(ACLMessage.REQUEST);
            msg.setContent(MSG_GET_FORM5);
            msg.addReceiver(schedulerAgent);
            send(msg);
            reply = blockingReceive(MessageTemplate.MatchPerformative(ACLMessage.INFORM));
            if (reply != null) {
              schedule = (IForm5) reply.getContentObject();
              logger.info(
                  getLocalName()
                      + " schedule received, units obtained: "
                      + schedule.getUnitsObtained()
                      + ", units allowed: "
                      + schedule.getWriteIn().getUnitsAllowed());

              for (Iterator ite = schedule.getWriteIn().getSubjects().iterator(); ite.hasNext(); ) {
                ISubject sub = (ISubject) ite.next();
                SectionAssignment sectAss =
                    (SectionAssignment) schedule.getSectionAssignment(sub.getName());
                if (sectAss != null) {
                  logger.info(sub.getName() + " " + sectAss.getSection().getSectionName());
                  toCancel = sectAss;
                } else {
                  logger.info(sub.getName() + " NOT ENLISTED");
                }
              }
            }
          } catch (Exception ioe) {
            ioe.printStackTrace();
          }

          // action=ACTION_POST_SWAP_REQUEST;
          action = ACTION_ENLIST;

          break;
        case ACTION_ENLIST:
          List unassigned = schedule.getUnassigned();
          passCount++;
          if (unassigned.size() == 0) {
            action = ACTION_HAPPY;
            break;
          } else if (passCount == 1) {
            Map assignments = schedule.getSectionAssignments();
            List subjects = new ArrayList(assignments.keySet());
            if (subjects.size() > 1) {
              Collections.shuffle(subjects);
              for (int i = 0; i < (subjects.size() - 1); i++) {
                String subject = (String) subjects.get(i);
                SectionAssignment sectAss = schedule.getSectionAssignment(subject);
                myAgent.addBehaviour(new CancelSlotBehaviour(sectAss));
              }
            }
            /*
             for(Iterator ite2=assignments.keySet().iterator();ite2.hasNext();){
            	String subject=(String)ite2.next();
            	SectionAssignment sectAss=schedule.getSectionAssignment(subject);
            	myAgent.addBehaviour(new CancelSlotBehaviour(sectAss));
            }
            */
            // for each unassigned subject, attempt to enlist
            for (Iterator ite = unassigned.iterator(); ite.hasNext(); ) {
              ISubject sub = (ISubject) ite.next();
              myAgent.addBehaviour(new EnlistBehaviour(sub));
            }
          } else {
            action = ACTION_HAPPY;
          }
          break;
        case ACTION_CANCEL_SLOT:
          myAgent.addBehaviour(new CancelSlotBehaviour(toCancel));
          action = ACTION_END;
          break;
        case ACTION_POST_SWAP_REQUEST:
          SwapEntry entry = new SwapEntry(getLocalName(), toCancel.getSection(), null);
          myAgent.addBehaviour(new PostSwapRequestBehaviour(entry));
          action = ACTION_END;
          break;
        case ACTION_HAPPY:
          // At this point student agent submits his schedule
          /*
          System.out.println("HAPPY");

          for (Iterator ite=schedule.getSectionAssignments().keySet().iterator();ite.hasNext();){
          	String key=(String)ite.next();
          	SectionAssignment sectAss = schedule.getSectionAssignment(key);
          	String sectName=sectAss.getSection().getSectionName();
          	System.out.println(getLocalName()+":"+key+" "+sectName);
          }
          */
          try {
            msg = new ACLMessage(ACLMessage.REQUEST);
            msg.setContentObject(schedule);
            msg.addReceiver(schedulerAgent);
            send(msg);
          } catch (Exception e) {
            e.printStackTrace();
          }
          action = ACTION_END;
          myAgent.doDelete();
          break;
      }
    }
  /**
   * Enlist
   *
   * @param studentWI
   * @param subject
   */
  private void enlist(WriteIn studentWI, String subject) {
    // Get the schedule of the student
    Schedule sked = (Schedule) schedules.get(studentWI.getStudentNumber());

    /* guard to make sure units must not exceed allowed
     */
    ISubject temp = studentWI.getSubjectInfo(subject);
    int unt = temp.getUnitCredit() + sked.getUnitsObtained();
    if (unt > studentWI.getUnitsAllowed()) {
      return;
    }

    List lectures = offering.getLecSections(subject);

    // Collections.shuffle(lectures);
    rankLectureSections(lectures);

    // less slots first?
    // Collections.reverse(lectures);

    // For each lec section
    for (Iterator ite6 = lectures.iterator(); ite6.hasNext(); ) {
      Section lab = null;
      SectionAssignment sectAss = new SectionAssignment();
      Section lecture = (Section) ite6.next();

      // Create a classlist of the section if it does
      // not exist yet
      String clkey = lecture.getSubject().getName() + ":" + lecture.getSectionName();
      Classlist cl = (Classlist) classlists.get(clkey);

      if (cl == null) {
        cl = new Classlist(lecture, null);
      }

      // proceed to next section if this section full
      if (cl.full()) {
        continue;
      }

      // Create a sked node for it
      SkedNode lecnode = new SkedNode(lecture);

      // temporarily add the lecnode
      sked.addSection(lecnode);

      // proceed to next lecture section
      // since this lecture is in conflict
      // already,
      // there is no need to process its labs
      if (!sked.passed(lecnode)) {
        sked.removeLastSectionAdded();
        continue;
      }

      sectAss.setLecture(lecture);

      // ok the lec node was added, however, it is not
      // a guaranteed slot unless a lab is found

      // now we get the lab sections
      List labs = offering.getLabSections(lecture.getSubject().getName(), lecture.getSectionName());

      boolean labFound = false;

      // this lecture got labs!
      if (labs.size() > 0) {
        // rankLabSections(labs);

        // less slots first?
        // Collections.reverse(labs);

        // try to find a lab
        for (Iterator ite7 = labs.iterator(); ite7.hasNext(); ) {
          lab = (Section) ite7.next();

          // Create a classlist of the section if
          // it does not exist yet
          clkey = lab.getSubject().getName() + ":" + lab.getSectionName();

          cl = (Classlist) classlists.get(clkey);

          if (cl == null) {
            cl = new Classlist(lecture, lab);
          }

          // Create a node for the lab
          SkedNode labNode = new SkedNode(lab);

          // Add it to the sked
          sked.addSection(labNode);

          // Did it satisfy the constraint?
          if (!sked.passed(labNode)) {
            // remove this lab section from sked
            sked.removeLastSectionAdded();
          } else {
            if (cl.addStudent(studentWI.getStudentNumber())) {
              sectAss.setLab(lab);
              sked.addSectionAssignment(sectAss);
              classlists.put(clkey, cl);
              // We found a lab! great
              labFound = true;
              break;
            } else {
              sked.removeLastSectionAdded();
            }
          }
        }
        // got one
        if (labFound == true) {
          break;
        } else {
          // remove the lecture node
          sked.removeLastSectionAdded();
        }
      } else {
        if (cl.addStudent(studentWI.getStudentNumber())) {
          sked.addSectionAssignment(sectAss);
          classlists.put(clkey, cl);
          if (studentWI.getStudentNumber().equals(stdNum)) {
            log(2, "\t\t\t\tEnlisted!");
          }
        } else {
          if (studentWI.getStudentNumber().equals(stdNum)) {
            log(2, "\t\t\t\tSection is full!");
          }
          sked.removeLastSectionAdded();
          sked.removeLastSectionAdded();
        }
        break;
      }
    }
  }