//copyright (C) 2007 Mocanu Cristian Romeo

 

package balls;

 

import java.util.List;

import java.util.Collections;

import java.util.ArrayList;

 

/**

 * Describe class <code>BallsKnowledge</code> here.

 *

 * @author <a href="mailto:chrimeea@yahoo.com">Cristian Mocanu</a>

 * @version 1.0

 */

public class Knowledge implements Cloneable {

    private List<BallState> knowledge;

    private boolean strict = true;

 

    public Knowledge(int totalb) {

            knowledge = Collections.nCopies(totalb, BallState.UNKNOWN);

    }

 

    public void setStrict(boolean s) {

            strict = s;

    }

 

    public int getTotalBalls() {

            return knowledge.size();

    }

 

    public boolean isState(int p, BallState s) {

            return knowledge.get(p) == s;

    }

 

    public boolean isLegal() {

            return Collections.frequency(knowledge, BallState.EXCLUDED) < getTotalBalls();

    }

 

    public boolean isSolution() {

            int t = getTotalBalls();

            int f = Collections.frequency(knowledge, BallState.EXCLUDED);

            if (f < t - 1) {

                return false;

            }

            if (strict && f == t - 1 && isState(getSolution(), BallState.UNKNOWN)) {

                return false;

            }

            return true;

    }

 

    public int getSolution() {

            for (int b = 0; b < knowledge.size(); b++) {

                if (!isState(b, BallState.EXCLUDED)) {

                        return b;

                }

            }

            return -1;

    }

 

    public boolean isUnknown(int p) {

            return knowledge.get(p).isUnknown();

    }

 

    @Override

    public Knowledge clone() {

            Knowledge k = new Knowledge(knowledge.size());

            k.knowledge = new ArrayList<BallState>(knowledge);

            return k;

    }

 

    public Knowledge extractLightKnowledge(Transition transition) {

            Knowledge k = clone();

            for (int b: transition.getRemainingBalls()) {

                k.knowledge.set(b, BallState.EXCLUDED);

            }

            for (int b: transition.getLeftPan()) {

                if (isState(b, BallState.UNKNOWN_HEAVY)) {

                        k.knowledge.set(b, BallState.EXCLUDED);

                } else if (isState(b, BallState.UNKNOWN)) {

                        k.knowledge.set(b, BallState.UNKNOWN_LIGHT);

                }

 

            }

            for (int b: transition.getRightPan()) {

                if (isState(b, BallState.UNKNOWN_LIGHT)) {

                        k.knowledge.set(b, BallState.EXCLUDED);

                } else if (isState(b, BallState.UNKNOWN)) {

                        k.knowledge.set(b, BallState.UNKNOWN_HEAVY);

                }

            }

            return k;

    }

 

    public Knowledge extractHeavyKnowledge(Transition transition) {

            Knowledge k = clone();

            for (int b: transition.getRemainingBalls()) {

                k.knowledge.set(b, BallState.EXCLUDED);

            }

            for (int b: transition.getLeftPan()) {

                if (isState(b, BallState.UNKNOWN_LIGHT)) {

                        k.knowledge.set(b, BallState.EXCLUDED);

                } else if (isState(b, BallState.UNKNOWN)) {

                        k.knowledge.set(b, BallState.UNKNOWN_HEAVY);

                }

            }

            for (int b: transition.getRightPan()) {

                if (isState(b, BallState.UNKNOWN_HEAVY)) {

                        k.knowledge.set(b, BallState.EXCLUDED);

                } else if (isState(b, BallState.UNKNOWN)) {

                        k.knowledge.set(b, BallState.UNKNOWN_LIGHT);

                }

            }

            return k;

    }

 

    public Knowledge extractEqualKnowledge(Transition transition) {

            Knowledge k = clone();

            for (int b: transition.getComparedBalls()) {

                k.knowledge.set(b, BallState.EXCLUDED);

            }

            return k;

    }

 

    public int ballOfState(List<Integer> blist, BallState bstate) {

            for (int b: blist) {

                if (isState(b, bstate)) {

                        return b;

                }

            }

            return -1;

    }

 

    public boolean containState(List<Integer> blist, BallState bstate) {

            return (ballOfState(blist, bstate) >= 0);

    }

 

    public int countState(List<Integer> blist, BallState bstate) {

            int k = 0;

            for (int b: blist) {

                if (isState(b, bstate)) {

                        k++;

                }

            }

            return k;

    }

 

    public boolean isStateEqual(int p1, int p2) {

            assert p1 > 0 && p2 > 0;

            return (knowledge.get(p1) == knowledge.get(p2));

    }

 

    public BallState getState(int p) {

            return knowledge.get(p);

    }

 

    @Override

    public String toString() {

            return knowledge.toString();

    }

}