//***********************************************************
//*
//* File:           PlayerSpecificResults.java
//* Author:         Srikant Krishna
//* Contact:        srikant@cs.columbia.edu
//* Update:         9.14.2002
//*
//* Description:    Opponent-matchup results analysis class.
//*
//***********************************************************

package ui;

import java.util.*;
import javax.swing.event.*;
import javax.swing.table.*;
import java.text.NumberFormat;

public final class PlayerSpecificResults implements IFCTournamentResults {

    ArrayList       _listeners;
    Class           _cellclass;
    final String    _CNULL_STRING = "[Null]";
    IFCGameRecord[] _games;
    String[][]      _table;
    NumberFormat    _nf;
    String[]        _names;
    static final String _CNAME = "Opponent Matchups";
    static final String _CSELF_STRING = "0.00|0.00|0.00";
    static final String _CSEPARATOR = "|";

    public PlayerSpecificResults(IFCGameRecord[] __games) throws Exception {
        HashMap hash;
        Class[] keys;
        Class[] players;
        String[] toks;
        double[] scores;
        int[] winners;
        double[][] win;
        double[][] loss;
        double[][] tie;
        double[][] total;
        int _MAXI;
        int _MAXJ;
        int _MAXK;
        boolean firstwon;
        boolean secondwon;
        int firstindex;
        int secondindex;


        _listeners = new ArrayList();
        _cellclass = new String().getClass();
        _games = __games;

        hash = new HashMap();
        _MAXI = _games.length;
        for (int i=0; i < _MAXI; i++) {
            players = _games[i].players();
            _MAXJ = players.length;

            for (int j=0; j < _MAXJ; j++) {
                if (hash.get(players[j]) == null) {
                    hash.put(players[j], null);
                }
            }
        }

        keys = (Class[]) hash.keySet().toArray(new Class[0]);
        Arrays.sort(keys, new Util.ClassSorter());
        _MAXJ = keys.length;
        hash.clear();
        for (int j=0; j < _MAXJ; j++) {
            hash.put(keys[j], new Integer(j));
        }
        total = new double[_MAXJ][_MAXJ];
        win = new double[_MAXJ][_MAXJ];
        loss = new double[_MAXJ][_MAXJ];
        tie = new double[_MAXJ][_MAXJ];
        for (int i=0; i < _MAXI; i++) {
            players = _games[i].players();
            _MAXJ = players.length;
            scores = _games[i].scores();
            winners = Util.maxIndex(scores);
            for (int j=0; j < _MAXJ; j++) {
                firstwon = in(j, winners);
                firstindex = ((Integer) hash.get(players[j])).intValue();
                for (int k=0; k < _MAXJ; k++) {
                    if (j == k) {
                        continue;
                    }
                    secondwon = in(k, winners);
                    secondindex = ((Integer) hash.get(players[k])).intValue();

                    if (firstwon && secondwon) {
                        tie[firstindex][secondindex]++;
                        tie[secondindex][firstindex]++;
                    }
                    if (firstwon && !secondwon) {
                        win[firstindex][secondindex]++;
                        loss[secondindex][firstindex]++;
                    }
                    if (!firstwon && secondwon) {
                        win[secondindex][firstindex]++;
                        loss[firstindex][secondindex]++;
                    }
                    total[firstindex][secondindex]++;
                    total[secondindex][firstindex]++;
                }
            }
        }
        _MAXI = keys.length;
        for (int i=0; i < _MAXI; i++) {
            for (int j=0; j < _MAXI; j++) {
                if (i == j) {
                    continue;
                }

                if (total[i][j] == 0) {
                    continue;
                }

                win[i][j] /= total[i][j];
                tie[i][j] /= total[i][j];
                loss[i][j] /= total[i][j];
            }
        }
        
        _nf = NumberFormat.getInstance();
        _nf.setMaximumFractionDigits(2);
        _nf.setMinimumFractionDigits(2);
        _names = new String[_MAXI];
        _table = new String[_MAXI][_MAXI];
        for (int i=0; i < _MAXI; i++) {
            toks = Util.split(".", keys[i].toString());
            _names[((Integer) hash.get(keys[i])).intValue()] = toks[toks.length-1];
            for (int j=0; j < _MAXI; j++) {
                if (i == j) {
                    _table[i][j] = _CSELF_STRING;
                    continue;
                }
                _table[i][j] = _nf.format(win[i][j])+_CSEPARATOR;
                _table[i][j] += _nf.format(tie[i][j])+_CSEPARATOR;
                _table[i][j] += _nf.format(loss[i][j]);
            }
        }
    }
    
    boolean in(int __val, int[] __array) {
        int _MAX = __array.length;
        for (int i=0; i < _MAX; i++) {
            if (__val == __array[i]) {
                return true;
            }
        }
        return false;
    }

    public String name() throws Exception {
        return _CNAME;
    }

	public void Print()
	{
		int x = getRowCount();
		int y = getColumnCount();
		
		System.out.print("\t\t");
		for(int i=0;i < y;i++)
			System.out.print(_names[i] + "\t");
		System.out.println();
		for(int i=0;i < x;i++)
		{
			System.out.print(_names[i] + "\t");
			for(int j=0;j < y;j++)
			{
				System.out.print((String)getValueAt(i, j) + "\t");
			}
			System.out.println();
		}
	}

    public void addTableModelListener(TableModelListener __listener) {
        if (!_listeners.contains(__listener)) {
            _listeners.add(__listener);
        }
    }

    public void removeTableModelListener(TableModelListener __listener) {
        _listeners.remove(__listener);
    }

    public Class getColumnClass(int __col) {
        return _cellclass;
    }

    public int getColumnCount() {
        return _names == null ? 0 : _names.length;
    }

    public String getColumnName(int __col) {
        return _names == null ? _CNULL_STRING : _names[__col];
    }

    public int getRowCount() {
        return _names == null ? 0 : _names.length;
    }

    public Object getValueAt(int __row, int __col) {
        return _table[__row][__col];
    }

    public boolean isCellEditable(int __row, int __col) {
        return false;
    }

    public void setValueAt(Object __obj, int __row, int __col)
    { }
    
    public void columnAdded(TableColumnModelEvent __event) 
    { }

    public void columnMarginChanged(ChangeEvent __event)
    { }

    public void columnMoved(TableColumnModelEvent __event)
    { }

    public void columnRemoved(TableColumnModelEvent __event)
    { }

    public void columnSelectionChanged(ListSelectionEvent __event) 
    { }
}
