/* ======================================================================
   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.io.*;
import java.math.BigDecimal;
import java.text.*;

import org.bodington.server.BuildingServerException;
import org.bodington.database.PrimaryKey;
import org.bodington.statistics.*;

public class McqQuestionAnalysis
	{
	int n;
	int available;
	boolean item_analysis=true;
	boolean html_output = false;
	
	PrimaryKey qid;
	CorrelationTest cortest;
	AnoVaTest anovatest;
	AnoVaTest[] itemanovatest;
	boolean[] answers;
	
	public McqQuestionAnalysis( PrimaryKey qid, boolean item, boolean html )
		{
		this.qid = qid;
		
		item_analysis = item;
		html_output = html;
		
		cortest = new CorrelationTest();
		cortest.reset();
		anovatest = new AnoVaTest();
		anovatest.reset(2);
		
		if ( item_analysis )
			{
			McqQuestion question;
			try
				{
				question = McqQuestion.findMcqQuestion( qid );
				}
			catch ( Exception ex )
				{
				item_analysis=false;
				return;
				}
			
			answers = new boolean[5];
			
			itemanovatest = new AnoVaTest[5];
			for ( int a=0; a<5; a++ )
				{
				answers[a] = question.getAnswer( a );
				itemanovatest[a] = new AnoVaTest();
				itemanovatest[a].reset(2);
				}
			}
		}
		
	public PrimaryKey getMcqQuestionId()
		{
		return qid;
		}

	public void addMcqResponse( McqResult result, McqResponse response )
		throws BuildingServerException
		{
		n++;
		available = response.getAvailable();
		if ( available == 1 )
			anovatest.datum( result.mark().doubleValue(), response.getRight() - response.getDeductions() );
		else
			cortest.datum(  result.mark().doubleValue(), response.getRight() - response.getDeductions() );
			
		if ( item_analysis )
			{
			for ( int i=0; i<5; i++ )
                            if ( response.getResponse( i ) != McqResponse.RESPONSE_DONT_KNOW )
				itemanovatest[i].datum( result.mark().doubleValue(), 
                                    (response.getResponse( i ) == McqResponse.RESPONSE_TRUE)?0:1 );
			}
		}
		
	public static void dumpAnalysisHeadings( PrintWriter out )
		{
		out.println( "Number of Students Responding." );
		}
		
	public void dumpAnalysis( PrintWriter out )
		{
		String sep;
		double dif, p, r;
                DecimalFormat format = new DecimalFormat();
                DecimalFormatSymbols symbols = new DecimalFormatSymbols();
                symbols.setNaN( "N/A" );
                format.applyPattern( "##0.###" );
                format.setDecimalFormatSymbols( symbols );

		if ( available == 1 )
			{
			dif = anovatest.getMean( 1 )-anovatest.getMean( 0 );
			try
				{
				anovatest.compute();
				p = anovatest.getP();
				}
			catch ( ArithmeticException aex )
				{
				p=-1;
				}

                        if ( html_output )
				out.print( "<h3>" );
			out.println( "Analysis of Question Performance by AnoVa" );
			if ( html_output )
				out.print( "</h3>" );

                        if ( html_output )
				out.print( "<p style=\"text-align: center\"><strong>" );
        		if ( p<0 )
				out.print( "Not enough data to reach conclusions." );
			else
				{
				if ( p<0.01 )
					{
					if ( dif<0 )
						out.print( "The more able students performed very significantly WORSE on this question!!!" );
					else
						out.print( "The more able students performed very significantly better on this question." );
					}
				else
					{
					if ( p<0.05 )
						{
						if ( dif<0 )
							out.print( "The more able students performed significantly WORSE on this question!!!" );
						else
							out.print( "The more able students performed significantly better on this question." );
						}
					else
						{
						if ( p<0.1 )
							{
							if ( dif<0 )
								out.print( "The more able students may have performed worse on this question." );
							else
								out.print( "The more able students may have performed better on this question." );
							}
						else
							{
							out.print( "There is no evidence that performance on this question relates to ability." );
							}
						}
					}
				}
                        if ( html_output )
				out.println( "</strong></p>" );
                        else
                            out.println();

                        sep = html_output?"</th><th>":"\t";
			
			if ( html_output )
				out.println( "<TABLE ALIGN=CENTER BORDER=1><tr><th>" );
			
			out.print( "Group"				);
			out.print( sep					);
			out.print( "Count"				);
			out.print( sep					);
			out.print( "Ability"			);
			out.print( sep					);
			out.print( "Ability Difference" );

			if ( html_output )
				out.println( "</th></tr><tr><td>" );
				
                        sep = html_output?"</td><td>":"\t";
				
			out.print( "Scored 0" );
			out.print( sep );
			out.print( format.format( anovatest.getN( 0 ) ) );
			out.print( sep );
			out.print( format.format( anovatest.getMean( 0 ) ) );
			out.print( sep );
			out.print( format.format( dif ) );

			if ( html_output )
				out.println( "</td></tr><tr><td>" );

			out.print( "Scored 1" );
			out.print( sep );
			out.print( format.format( anovatest.getN( 1 ) ) );
			out.print( sep );
			out.print( format.format( anovatest.getMean( 1 ) ) );

			if ( html_output )
				out.println( "</td></tr></TABLE>" );
			}
		else
			{
			try
				{
				cortest.compute();
				p = cortest.getP();
                                r = cortest.getR();
				}
			catch ( ArithmeticException aex )
				{
				p=-1;
                                r=0;
				}

			if ( html_output )
				out.print( "<h3>" );
			out.println( "Analysis of Question Performance by Correlation" );
			if ( html_output )
				out.print( "</h3>" );

			if ( html_output )
				out.println( "<p style=\"text-align: center\"><strong>" );
			
			
			if ( p<0 )
				out.print( "Not enough data to reach conclusions." );
			else
				{
				if ( p<0.01 )
					{
					if ( r<0 )
						out.print( "The more able students performed very significantly WORSE on this question!!!" );
					else
						out.print( "The more able students performed very significantly better on this question." );
					}
				else
					{
					if ( p<0.05 )
						{
						if ( r<0 )
							out.print( "The more able students performed significantly WORSE on this question!!!" );
						else
							out.print( "The more able students performed significantly better on this question." );
						}
					else
						{
						if ( p<0.1 )
							{
							if ( r<0 )
								out.print( "The more able students may have performed worse on this question." );
							else
								out.print( "The more able students may have performed better on this question." );
							}
						else
							{
							out.print( "There is no evidence that performance on this question relates to ability." );
							}
						}
					}
				}

                        
			if ( html_output )
                            out.print( "</strong></p><p>" );
                        out.print( "Correlation Coefficient: \t" );
                        out.print( format.format( r ) );
			if ( html_output )
                            out.println( "</p>" );
                        else
                            out.println();
			}


		if ( !item_analysis )
			return;
			
		for ( int i=0; i<5; i++ )
			{
			dif = itemanovatest[i].getMean( 1 )-itemanovatest[i].getMean( 0 );
			if ( answers[i] )
				dif = -dif;
			try
				{
				itemanovatest[i].compute();
				p = itemanovatest[i].getP();
				}
			catch ( ArithmeticException aex )
				{
				p=-1;
				}
                        
			if ( html_output )
				out.print( "<h3>" );
			out.print( "AnoVa Analysis of " );
			out.println( "Item " + (char)('a' + i) );
			if ( html_output )
				out.println( "</h3>" );

			if ( html_output )
                            out.println( "<p style=\"text-align: center\"><strong>" );
			if ( p<0 )
				out.print( "Not enough data to reach conclusions." );
			else
				{
				if ( p<0.01 )
					{
					if ( dif<0 )
						out.print( "The more able students performed very significantly WORSE on this item!!!" );
					else
						out.print( "The more able students performed very significantly better on this item." );
					}
				else
					{
					if ( p<0.05 )
						{
						if ( dif<0 )
							out.print( "The more able students performed significantly WORSE on this item!!!" );
						else
							out.print( "The more able students performed significantly better on this item." );
						}
					else
						{
						if ( p<0.1 )
							{
							if ( dif<0 )
								out.print( "The more able students may have performed worse on this item." );
							else
								out.print( "The more able students may have performed better on this item." );
							}
						else
							{
							out.print( "There is no evidence that performance on this item relates to ability." );
							}
						}
					}
				}
			if ( html_output )
                            out.println( "</strong></p>" );
                        else
                            out.println( "" );

                        sep = html_output?"</th><th>":"\t";
			
			if ( html_output )
				out.println( "<TABLE ALIGN=CENTER BORDER=1><tr><th>" );
			
			out.print( "Group"				);
			out.print( sep					);
			out.print( "Count"				);
			out.print( sep					);
			out.print( "Ability"			);
			out.print( sep					);
			out.print( "Ability Difference" );

			if ( html_output )
				out.println( "</th></tr><tr><td>" );
                        sep = html_output?"</td><td>":"\t";
				
				
			out.print( "Selected TRUE." );
			out.print( sep );
			out.print( format.format( itemanovatest[i].getN( 0 ) ) );
			out.print( sep );
			out.print( format.format( itemanovatest[i].getMean( 0 ) ) );
			out.print( sep );
			out.print( format.format( dif ) );

			if ( html_output )
				out.println( "</td></tr><tr><td>" );

			out.print( "Selected FALSE." );
			out.print( sep );
			out.print( format.format( itemanovatest[i].getN( 1 ) ) );
			out.print( sep );
			out.print( format.format( itemanovatest[i].getMean( 1 ) ) );

			if ( html_output )
				out.println( "</td></tr></TABLE>" );
			
			}
		}
	}
