/* ======================================================================
   Parts Copyright 2006 University of Leeds, Oxford University, University of the Highlands and Islands.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

====================================================================== */

package org.bodington.assessment;

import java.util.Enumeration;

import org.bodington.sqldatabase.*;
import org.bodington.database.*;
import org.bodington.server.BuildingServerException;
import org.bodington.util.PackedThreeOptionFlags;


public class McqResponse extends org.bodington.sqldatabase.SqlPersistentObject
	{
	private PrimaryKey mcq_response_id;
	private PrimaryKey mcq_result_id;
	private PrimaryKey mcq_question_id;
	private PackedThreeOptionFlags responses = new PackedThreeOptionFlags();
	
        public static final int RESPONSE_FALSE         = 0;
        public static final int RESPONSE_TRUE          = 1;
        public static final int RESPONSE_DONT_KNOW     = 2;
        
	// not stored...
	private boolean marked = false;
	private int available=0;
	private int right=0;
	private int deductions=0;
	private int wrong=0;



	public static McqResponse findMcqResponse( PrimaryKey key )
	    throws BuildingServerException
	    {
	    return (McqResponse)findPersistentObject( key, "org.bodington.server.assessment.McqResponse" );
	    }
	
	public static McqResponse findMcqResponse( String where )
	    throws BuildingServerException
	    {
	    return (McqResponse)findPersistentObject( where, "org.bodington.assessment.McqResponse" );
	    }
	
	public static Enumeration findMcqResponses( String where )
	    throws BuildingServerException
	    {
	    return findPersistentObjects( where, "org.bodington.assessment.McqResponse" );
	    }
	
	public static Enumeration findMcqResponses( String where, String order )
	    throws BuildingServerException
	    {
	    return findPersistentObjects( where, order, "org.bodington.assessment.McqResponse" );
	    }
	

	
	
    public PrimaryKey getPrimaryKey()
    	{
        return getMcqResponseId();
    	}

    public void setPrimaryKey(PrimaryKey key)
    	{
    	setMcqResponseId( key );
    	}

	
	public PrimaryKey getMcqResponseId()
		{
		return mcq_response_id;
		}
		
	public void setMcqResponseId( PrimaryKey id )
		{
		mcq_response_id = id;
		}


	public PrimaryKey getMcqResultId()
		{
		return mcq_result_id;
		}
		
	public void setMcqResultId( PrimaryKey id )
		{
		mcq_result_id = id;
		setUnsaved();
		}


	public PrimaryKey getMcqQuestionId()
		{
		return mcq_question_id;
		}
		
	public void setMcqQuestionId( PrimaryKey id )
		{
		mcq_question_id = id;
		setUnsaved();
		}


	public byte getResponses()
		{
		return responses.getPackedFlags();
		}
		
	public void setResponses( byte r )
		{
		if ( responses.getPackedFlags() == r )
			return;
		responses.setPackedFlags( r );
		setUnsaved();
		}
		
	public int getResponse( int n )
		{
                return responses.getFlag( n );
		}
		
	public void setResponse( int n, int r )
		{
                if ( r == getResponse( n ) ) return;
                responses.setFlag( n, r );
		setUnsaved();
		}

	public void mark( McqQuestion q )
	{
		// do the maths....
		available=0;
		right=0;
		wrong=0;
                deductions = 0;
                int j, r;
                boolean choice;
                byte type = q.getQuestionType();
                
                //need to do it differently for multiple TFD
                if ( type == McqQuestion.TYPE_MULTIPLE_TF || 
                     type == McqQuestion.TYPE_MULTIPLE_TFD  ||
                     type == McqQuestion.TYPE_STRICT_MULTIPLE_TF     )
                {
                    for (j=0; j<5; j++)
                    {
                        available++;
                        r = getResponse( j );
                        if ( r == RESPONSE_TRUE || r == RESPONSE_FALSE )
                        {
                            choice = (r==RESPONSE_TRUE)?true:false;
                            if ( q.getAnswer(j) == choice ) right++;
                            if ( type == McqQuestion.TYPE_MULTIPLE_TFD &&
                                 q.getAnswer(j) != choice ) wrong++;
                        }
                    }
                    if ( type == McqQuestion.TYPE_MULTIPLE_TFD )
                        // make sure final mark can't be negative
                        deductions = (wrong>right) ? right : wrong;
                    else if ( type == McqQuestion.TYPE_STRICT_MULTIPLE_TF )
                    {
                        // in strict marking you must get all the statements right
                        // otherwise the rest is deducted
                        if (right!=available)
                        {
                            right=0;
                            wrong=0;
                        }
                    }
                    else
                        deductions = 0;
                }
                else
                {    
                    for ( j=0; j<5; j++ )
                    {
                        r = getResponse( j );
			if ( q.getAnswer(j) )
			{
				available++;
				if ( r == RESPONSE_TRUE ) right++;
			}
                        else
                        {
                            if ( r == RESPONSE_TRUE )
                                wrong++;
                        }
                    }
                    if ( type == McqQuestion.TYPE_ONE_TRUE )
                        deductions = 0;
                    else
                        deductions=(wrong>right) ? right : wrong;
                }
		marked = true;
	}
		
	public int getAvailable()
		throws BuildingServerException
		{
		if ( !marked )
			throw new BuildingServerException( "Can't return mark yet." );
		return available;
		}
		
	public int getDeductions()
		throws BuildingServerException
		{
		if ( !marked )
			throw new BuildingServerException( "Can't return mark yet." );
		return deductions;
		}
		
	public int getRight()
		throws BuildingServerException
		{
		if ( !marked )
			throw new BuildingServerException( "Can't return mark yet." );
		return right;
		}

	public int getWrong()
		throws BuildingServerException
		{
		if ( !marked )
			throw new BuildingServerException( "Can't return mark yet." );
		return wrong;
		}
		
	}
