package negotiator.parties;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.JTextArea;
import javax.swing.table.AbstractTableModel;
import genius.core.Bid;
import genius.core.exceptions.Warning;
import genius.core.issue.Issue;
import genius.core.issue.IssueDiscrete;
import genius.core.issue.Value;
import genius.core.issue.ValueDiscrete;
import genius.core.utility.AdditiveUtilitySpace;
import genius.core.utility.EvaluatorDiscrete;
/**
* NegoInfo is the class that contains all the negotiation data, and handles the
* GUI, updating the JTable. This is the main interface to the actual JTable.
* This is usually called XXXModel but I dont like the 'model' in the name. We
* implement actionlistener to hear the combo box events that require
* re-rendering of the total cost and utility field. We are pretty hard-wired
* for a 3-column table, with column 0 the labels, column 1 the opponent bid and
* col2 our own bid.
*
*
* Many dialogs in negotiator.parties package use this.
*/
@SuppressWarnings("serial")
class NegoInfo extends AbstractTableModel implements ActionListener {
public Bid ourOldBid; // Bid is hashmap . Our current bid is
// only in the comboboxes,
// use getBid().
public Bid lastAccepted;
public AdditiveUtilitySpace utilitySpace; // WARNING: this may be null
public List issues = new ArrayList();
// the issues, in row order as in the GUI. Init to empty, to enable
// freshly initialized NegoInfo to give useful results to the GUI.
public ArrayList IDs; // the IDs/numbers of the issues, ordered to
// row number
public ArrayList comboBoxes; // the combo boxes for the second
// column, ordered to row number
NegoInfo(Bid our, Bid lastAccepted, AdditiveUtilitySpace us)
throws Exception {
// Wouter: just discovered that assert does nothing...........
// David@Wouter: Assert only works when assert compile flag is set to
// true
ourOldBid = our;
this.lastAccepted = lastAccepted;
utilitySpace = us;
issues = utilitySpace.getDomain().getIssues();
IDs = new ArrayList();
for (int i = 0; i < issues.size(); i++)
IDs.add(issues.get(i).getNumber());
makeComboBoxes();
}
@Override
public int getColumnCount() {
return 3;
}
@Override
public int getRowCount() {
// the extra row shows the utility of the bids.
return issues.size() + 1;
}
@Override
public boolean isCellEditable(int row, int col) {
return (col == 2 && row < issues.size());
}
private String[] colNames = { "Issue", "Last Accepted Bid", "Your bid" };
@Override
public String getColumnName(int col) {
return colNames[col];
}
public void setOurBid(Bid bid) throws Exception {
ourOldBid = bid;
if (bid == null)
try {
ourOldBid = utilitySpace.getMaxUtilityBid();
} catch (Exception e) {
System.out.println("error getting max utility first bid:"
+ e.getMessage());
e.printStackTrace();
}
makeComboBoxes(); // reset all
setComboBoxes(ourOldBid);
}
void makeComboBoxes() throws Exception {
comboBoxes = new ArrayList();
for (Issue issue : issues) {
if (!(issue instanceof IssueDiscrete))
throw new IllegalArgumentException("Not supported issue "
+ issue + ": not IssueDiscrete. ");
List values = ((IssueDiscrete) issue).getValues();
JComboBox cbox = new JComboBox();
EvaluatorDiscrete eval = null;
if (utilitySpace != null)
eval = (EvaluatorDiscrete) utilitySpace.getEvaluator(issue
.getNumber());
for (ValueDiscrete val : values) {
String utilinfo = "";
if (eval != null)
try {
// utilinfo="("+eval.getEvaluation(val)+")";
utilinfo = "(" + eval.getValue(val) + ")";
} catch (Exception e) {
System.out.println("no evaluator for " + val + "???");
}
cbox.addItem(val + utilinfo);
}
comboBoxes.add(cbox);
for (JComboBox b : comboBoxes)
b.addActionListener(this);
}
}
/**
* set the initial combo box selections according to ourOldBid Note, we can
* only handle Discrete evaluators right now.
*
* @throws if
* there is a problem with the issues and evaluators.
*/
void setComboBoxes(Bid bid) throws Exception {
for (int i = 0; i < issues.size(); i++) {
IssueDiscrete iss = (IssueDiscrete) issues.get(i);
ValueDiscrete val = (ValueDiscrete) bid.getValue(iss.getNumber());
comboBoxes.get(i).setSelectedIndex(
((IssueDiscrete) iss).getValueIndex(val));
}
}
/**
* get the currently chosen evaluation value of given row in the table.
*
* @param bid
* : which bid (the column in the table are for ourBid and
* opponentBid)
* @return the evaluation of the given row in the bid. returns null if the
* bid has no value in that row.
* @throws probablly
* if rownr is out of range 0...issues.size()-1
*/
Value getCurrentEval(Bid bid, int rownr) throws Exception {
if (bid == null)
return null;
Integer ID = IDs.get(rownr); // get ID of the issue in question.
return bid.getValue(ID); // get the current value for that issue in the
// bid
}
/**
* get a render component
*
* @return the Component that can be rendered to show this cell.
*/
@Override
public Component getValueAt(int row, int col) {
if (row == issues.size()) {
if (col == 0)
return new JLabel("Utility:");
if (utilitySpace == null)
return new JLabel("No UtilSpace");
Bid bid;
if (col == 1)
bid = lastAccepted;
else
try {
bid = getBid();
} catch (Exception e) {
bid = null;
System.out.println("Internal err with getBid:"
+ e.getMessage());
}
;
JProgressBar bar = new JProgressBar(0, 100);
bar.setStringPainted(true);
try {
bar.setValue((int) (0.5 + 100.0 * utilitySpace.getUtility(bid)));
bar.setIndeterminate(false);
} catch (Exception e) {
new Warning("Exception during cost calculation:"
+ e.getMessage(), false, 1);
bar.setIndeterminate(true);
}
return bar;
}
switch (col) {
case 0:
return new JTextArea(issues.get(row).getName());
case 1:
Value value = null;
try {
value = getCurrentEval(lastAccepted, row);
} catch (Exception e) {
System.out.println("Err EnterBidDialog2.getValueAt: "
+ e.getMessage());
}
if (value == null)
return new JTextArea("-");
return new JTextArea(value.toString());
case 2:
return comboBoxes.get(row);
}
return null;
}
Bid getBid() throws Exception {
HashMap values = new HashMap();
for (int i = 0; i < issues.size(); i++)
values.put(IDs.get(i), ((IssueDiscrete) issues.get(i))
.getValue(comboBoxes.get(i).getSelectedIndex()));
// values.put(IDs.get(i), (Value)comboBoxes.get(i).getSelectedItem());
return new Bid(utilitySpace.getDomain(), values);
}
public void actionPerformed(ActionEvent e) {
// System.out.println("event d!"+e);
// receiveMessage the cost and utility of our own bid.
fireTableCellUpdated(issues.size(), 2);
fireTableCellUpdated(issues.size() + 1, 2);
}
}