/**
     * Creates a starting proposal for a new negotiation of a need. In this implementation, the
     * mostly preferred value for each competence attribute is selected to compose the proposal.
     *
     * @param competence The competence being negotiated
     * @return A new proposal
     */
    public Proposal createStartingProposal(Need need, Competence competence) {
      Proposal proposal = new Proposal(myAgent.getAID());
      proposal.setNeedType(competence.getType());
      // fill attribute values
      for (int j = 0; j < competence.getNumberOfAttributes(); j++) {
        Attribute ownAttribute = (Attribute) competence.getAttributes().get(j);
        AttributeValue valueToPropose = new AttributeValue();
        valueToPropose.setName(ownAttribute.getName());
        valueToPropose.setType(ownAttribute.getType());

        Attribute askedAttribute = need.getAttribute(ownAttribute.getName());
        if (!ownAttribute.isDiscrete()) {
          float ownPreferredValue =
              checkAskedContinuousDomain(
                  askedAttribute, Float.parseFloat(ownAttribute.getPreferredValue().toString()));
          if (ownAttribute
              .getType()
              .equals("float")) { // check if this is really of type float, or integer
            valueToPropose.setValue(String.valueOf(ownPreferredValue));
          } else {
            valueToPropose.setValue(String.valueOf((int) ownPreferredValue));
          }
        } else {
          String ownPreferredValue =
              checkAskedDiscreteDomain(askedAttribute, ownAttribute.getPreferredValue().toString());
          valueToPropose.setValue(ownPreferredValue);
        }

        proposal.getAttributeValues().add(valueToPropose);
      }
      return proposal;
    }
    /**
     * Creates a counterproposal, based on qualitative feedback on the previous proposal. According
     * to the feedback received (on each AttributeValue of the Proposal), the enterpriseAgent
     * generates a new value for each proposal's attribute. Calculating a new value for an attribute
     * depends on the classification ("excellent", "sufficient", "bad", "very bad") and direction
     * ("up", "down") feedback elements at an AttributeValue. In this implementation:
     *
     * <ul>
     *   <li>For discrete attributes, a new random value is selected within the domain of values for
     *       this attribute.
     *   <li>For continuous attributes:
     *       <ul>
     *         <li>If classification = "very bad", the value is changed in 10% towards the indicated
     *             direction.
     *         <li>If classification = "bad", the value is changed in 5% towards the indicated
     *             direction.
     *         <li>If classification = "sufficient", the value is changed in 0.5% towards the
     *             indicated direction.
     *         <li>If classification = "excellent", the value is not changed.
     *       </ul>
     * </ul>
     */
    public Proposal createCounterProposal(
        ProposalEvaluation feedback, Need need, Competence competence) {
      //			final float DELTA_EXCELLENT = 0.0f;
      //			final float DELTA_SUFFICIENT = 0.005f;
      //			final float DELTA_BAD = 0.5f;
      //			final float DELTA_VERYBAD = 3f;

      final float DELTA_EXCELLENT = 0.0f;
      final float DELTA_SUFFICIENT = 0.5f;
      final float DELTA_BAD = 0.7f;
      final float DELTA_VERYBAD = 1.2f;

      //			final float DELTA_SUFFICIENT = 0.05f;
      //			final float DELTA_BAD = 0.5f;
      //			final float DELTA_VERYBAD = 1.5f;

      Proposal proposal = new Proposal(myAgent.getAID());
      proposal.setNeedType(feedback.getNeedType());

      for (int i = 0; i < feedback.getAttributeValueEvaluations().size(); i++) {
        AttributeValueEvaluation attributeValueEvaluation =
            (AttributeValueEvaluation) feedback.getAttributeValueEvaluations().get(i);
        Attribute askedAttribute = need.getAttribute(attributeValueEvaluation.getName());
        Attribute ownAttribute = competence.getAttribute(attributeValueEvaluation.getName());
        AttributeValue valueToPropose = new AttributeValue();
        valueToPropose.setName(attributeValueEvaluation.getName());
        valueToPropose.setType(attributeValueEvaluation.getType());

        if (attributeValueEvaluation.isDiscrete()) { // discrete attribute
          if (attributeValueEvaluation.getClassif()
                  == AttributeValueEvaluation.AttributeClassification.BAD
              || attributeValueEvaluation.getClassif()
                  == AttributeValueEvaluation.AttributeClassification.VERY_BAD) {
            // propose a new random value for this attribute
            List domain = ownAttribute.getDiscreteDomain();

            String proposedValue =
                (String)
                    domain.get(
                        (int)
                            (domain.size()
                                * Math
                                    .random())); // FIXME: may get the same value or a previously
                                                 // proposed one!
            valueToPropose.setValue(proposedValue);
          } else {
            // maintain previous value
            valueToPropose.setValue(attributeValueEvaluation.getValue());
          }
        } else { // continuous attribute
          float floatValue =
              Float.parseFloat(attributeValueEvaluation.getValue()); // treat as float
          float difToMaxEdge =
              Float.parseFloat((String) askedAttribute.getContinuousDomainMax()) - floatValue;
          float difToMinEdge =
              floatValue - Float.parseFloat((String) askedAttribute.getContinuousDomainMin());

          switch (attributeValueEvaluation.getClassif()) {
            case EXCELLENT:
              floatValue += DELTA_EXCELLENT * floatValue;
              break;
            case SUFFICIENT:
              if (attributeValueEvaluation.getDirection()
                  == AttributeValueEvaluation.AttributeDirection.UP) {
                floatValue += DELTA_SUFFICIENT * difToMaxEdge;
              } else {
                floatValue -= DELTA_SUFFICIENT * difToMinEdge;
              }
              break;
            case BAD:
              if (attributeValueEvaluation.getDirection()
                  == AttributeValueEvaluation.AttributeDirection.UP) {
                floatValue += DELTA_BAD * difToMaxEdge;
              } else if (attributeValueEvaluation.getDirection()
                  == AttributeValueEvaluation.AttributeDirection.DOWN) {
                floatValue -= DELTA_BAD * difToMinEdge;
              }
              break;
            case VERY_BAD:
              if (attributeValueEvaluation.getDirection()
                  == AttributeValueEvaluation.AttributeDirection.UP) {
                floatValue += DELTA_VERYBAD * difToMaxEdge;
              } else if (attributeValueEvaluation.getDirection()
                  == AttributeValueEvaluation.AttributeDirection.DOWN) {
                floatValue -= DELTA_VERYBAD * difToMinEdge;
              }
              break;
          }

          floatValue = checkOwnContinuousDomain(ownAttribute, floatValue);
          floatValue = checkAskedContinuousDomain(askedAttribute, floatValue);

          if (attributeValueEvaluation
              .getType()
              .equals("float")) { // check if this is really of type float, or integer
            valueToPropose.setValue(String.valueOf(floatValue));
          } else {
            valueToPropose.setValue(String.valueOf(Math.round(floatValue)));
          }
        }

        proposal.getAttributeValues().add(valueToPropose);
      }

      return proposal;
    }