Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Integrated Quiz WebApp with Graphical Score Report

0.00/5 (No votes)
21 May 2005 1  
Integrated online quiz app with graphical score report. Users can bookmark questions in order to review in the end.

Background

The quiz application demonstrated here allows users to proceed with multi-choice questions like in an IQ Quiz. The database is a simple XML file. The application is a single web user control. The data holder between the pages is the Session bag (Viewstate[ data ]).There are three panels within our quiz user control. They are Quiz panel, Review panel and Score Report panel. I have used my own progress bar control within the Score Report...

Database

Our database is a simple XML file:

<?xml version="1.0" encoding="utf-8" ?> 
<quiz>
  <mc>
     <question correctAnsNo='1'>Which of the fol....?
     </question>
     <answer correct='No' ><![CDATA[  <img src="x...]]>
     </answer>
     <answer correct='No' ><![CDATA[  <img src="x...]]>
     </answer>
     <answer correct='Yes'><![CDATA[  <img src="x...]]>
     </answer>
     <answer correct='No' ><![CDATA[  I Don't Know  ]]>
     </answer>
  </mc>
</quiz>

Using the code

Our quiz user control has four methods:

  • ShowQuestion(int _qNo)
  • Review()
  • ReAnswer()
  • ShowResult()

The code

First, there are some common member variables:

    //create xmlDocument holder

    XmlDocument doc=new XmlDocument();
    //create empty navigator in order to navigate

    //through our XMLDocument 

    XPathNavigator nav;
    //to loop through 

    XPathNodeIterator nodeItrator;    
    //hold user Answers

    ArrayList historyALst=new ArrayList();
    //hold bookmarked Question(s)

    ArrayList bookmarkLst=new ArrayList();
    //used to replace index 1 by A and 2 by B ....etc

    char[] perfix=new char[10] {'A','B','C','D','F','G','H','J','K','L'};    
    int currentQNo; //current question number

    int totalQNumber; // total quiz question number

    int totalMarkedQuestion; // total marked questions number

        int currentMarkedQuestion; //current bookmarked question number

        int markLoop; // the res number of reanswered bookmarked questions

    DateTime startTime; // quiz start time

    TimeSpan spentTime; 
    bool isReview; // to indicate the status of current qustion

    bool wasChecked=false; //signed as marked Q within Review report.

In the page_load(....), do the following:

    private void Page_Load(object sender, System.EventArgs e)
    {    
        //load our XML DB

        doc.Load(Server.MapPath("quiz.xml"));
        //create navigator for loaded xml File

        nav=doc.CreateNavigator();
            
        //Is New Quiz?.

        if(!IsPostBack)
        {
            //Yes.

            quizPanal.Visible=true;// show quiz screen.

                
            //record start time

            startTime=DateTime.Now;
            currentQNo=1;
            //count and record Total questions Number

            //using our XmlDocumentnavigator by passing

            //XPath sring of question node ( <mc>...</mc>)

                totalQNumber=nav.Select("//mc").Count;
                //store our data in Session bag

                //simply,I use the same name for Sessionbag object

                //and member Field..

            ViewState["startTime"]=startTime;
            ViewState["totalQNumber"]=totalQNumber;
            ViewState["currentQNo"]=currentQNo;
            ViewState["score"]=0;
            //go to first Question

            ShowQuestion(currentQNo);
            }
        }

Let's render question number as currentQNo : ShowQuestion(currentQNo);

Render a specific multi-choice question. This method takes question number as parameter, and uses this number within different XPath strings to navigate through our XML nodes:

    /// <summary>

    /// Retrive Question and its Choices from

    /// XML file and render it to screen

    /// </summary>

    /// <param name="_qNo">Question Numberv/param>

    public void ShowQuestion(int _qNo)
    {
        quizPanal.Visible=true;

        //clear any selected radioList item

        answersRBL.Items.Clear();
        //retrieve Data from session bag and calculate spent time

        startTime=(DateTime)ViewState["startTime"];
        totalQNumber=Convert.ToInt32(ViewState["totalQNumber"]);
        spentTime=DateTime.Now.Subtract(startTime);
        //XPath String of current question node

        //quiz/mc[current question number] 

        string xPath="quiz/mc["+_qNo.ToString()+"]";
        
        int counter=1;
        string str;
        //read current Q Text by by using Select() method

        //of our navigator by set the XPath string 

        //as address of current Question text Node:

        //quiz/mc[current question number]/question

        nodeItrator=nav.Select(xPath+"/question");
        nodeItrator.MoveNext();
        //display some data

        qNoLbl.Text="Q: "+_qNo.ToString()+" / "+totalQNumber.ToString();
        questionLbl.Text=_qNo.ToString()+": "+nodeItrator.Current.Value;
        spentTimeLbl.Text=spentTime.Minutes.ToString()
                   +"~"+spentTime.Seconds.ToString();

        //answer nodes Xpath string quiz/mc[current question number]/answer

        nodeItrator=nav.Select(xPath+"/answer");
        
        while(nodeItrator.MoveNext())
        {    
            str=counter.ToString();
            //add  new radioBtn to Answers RadioList with perfix A, B..

            //with text o the current text node

            answersRBL.Items.Add(new ListItem(perfix[counter-1].ToString()
                           +":"+nodeItrator.Current.Value,str));
                
            //keep correct answer in mind

            if(nodeItrator.Current.GetAttribute("correct","")=="Yes")
            {
                ViewState["correctAnswer"]=counter;
            }
            counter++;//next

        }

There are some actions that take place when this method renders bookmarked questions:

        //retrieve current status from session bag 

        isReview=Convert.ToBoolean(ViewState["isReview"]);
        //Is Review Bookmarked questions Only? 

        if(isReview)
        {//yes

            //disable bookmark checkbox

            bookmarkCKBX.Enabled=false;
            //dispaly an image to notify user 

            Image1.Visible=true;
            qNoLbl.ForeColor=Color.Red;
            RequiredFieldValidator1.Text="Answer The Question !";
        }
        currentQNo++;//next

        ViewState["currentQNo"]=currentQNo;
    }//end method

After that, the user reviews answers history and is allowed to go back or view score report Review():

    /// <summary>

    /// generate Review Report

    /// by retrive user answers from historyALst ArrayList

    /// and Bookmarked Question(s) from bookmarkLst ArrayList

    /// and do user descion

    /// </summary>

    public void Review()
    {
        revisionPanal.Visible=true;
        
        int seqance=0;
        string _is="No";
        //retrieve marked Questions and answers List

        bookmarkLst=(ArrayList)ViewState["bookmarkLst"];
        historyALst=(ArrayList)ViewState["historyALst"];
        totalQNumber=Convert.ToInt32(ViewState["totalQNumber"]);

        wasChecked=Convert.ToBoolean(ViewState["wasChecked"]);
        //are you marked some questions for review ?

        if(!wasChecked){ /* No */ markBtn.Enabled=false;}

        //create Answers History report

        //            

        //table header

        TableCell c=new TableCell();
        TableCell cc=new TableCell();
        TableCell ccc=new TableCell();

        c.Text="Question No.";
        cc.Text="Your Answer";
        ccc.Text="Bookmark ?";
        
        TableRow hr=new TableRow();
        hr.Cells.Add(c);
        hr.Cells.Add(cc);
        hr.Cells.Add(ccc);

        hr.ForeColor=Color.White;
        hr.BackColor=Color.LightSlateGray;

        Table1.Rows.Add(hr);

        Table1.Font.Bold=true;
        //your records

        for(int i=1;i<=totalQNumber;i++)
        {    
            //Cell: Q Number

            TableCell c1=new TableCell();
            c1.Text=i.ToString();
            //Cell: your answer A,B, or C...

            TableCell c2=new TableCell();
            c2.HorizontalAlign=HorizontalAlign.Center;
            c2.Text=perfix[Convert.ToInt32(historyALst[i-1])-1].ToString();
            //Cell: bookmarked or not

            TableCell c3=new TableCell();
            for(int n=0;n < bookmarkLst.Count;n++)
            {    //Is this Q bookmarked ?

                if(Convert.ToInt32(bookmarkLst[n].ToString())==i)
                {//Yes

                    _is=" Yes ";
                }
            }

            c3.Text=_is;
            c3.HorizontalAlign=HorizontalAlign.Center;//align=center

            _is=" No ";//Re-Assign

            TableRow r=new TableRow();
            r.Cells.Add(c1);
            r.Cells.Add(c2);
            r.Cells.Add(c3);
            r.ForeColor=Color.SlateGray;
            //

            //Just, Table template

            if(seqance % 2 != 0)
            {
                r.BackColor=Color.Gainsboro;
            }
            
            //display it

            Table1.Rows.Add(r);
                
            eqance++;//next ..

        }//end for

    }//end method

If the user decides to go back, then ReAnswer():

    /// <summary>

    /// generate a list of bookmarked questions

    /// and fire ShowQuestion() for first one

    /// according to some rules

    /// </summary>

    public void ReAnswer()
    {
        quizPanal.Visible=true;

        isReview=true;
        //retrieve data    

        bookmarkLst=(ArrayList)ViewState["bookmarkLst"];
    
        totalMarkedQuestion=bookmarkLst.Count;
        currentMarkedQuestion=Convert.ToInt32(bookmarkLst[0]);
        //store data

        markLoop=1;
        ViewState["markLoop"]=markLoop;
        ViewState["isReview"]=isReview;
        ViewState["totalMarkedQuestion"]=totalMarkedQuestion;
        ViewState["currentMarkedQuestion"]=currentMarkedQuestion;
        //Show first marked question

        ShowQuestion(currentMarkedQuestion);
    }//end method

In the end, call the Score report: ShowResult()

    /// <summary>

    /// generate Score Report

    /// by some simple calculations

    /// </summary>

    public void ShowResult()
    {
        resultPanal.Visible=true;
        //retrieve data    

        int score=Convert.ToInt32(ViewState["score"]);
        totalQNumber=Convert.ToInt32(ViewState["totalQNumber"]);
        startTime=(DateTime)ViewState["startTime"];
        spentTime=DateTime.Now.Subtract(startTime);
        
        //set own Progress Bar Max. Value

        progressBar.Total=totalQNumber*100;
        //set your score as progressed value

        progressBar.Value=score*100;
        
        //display some data:

        //

        //date

        dateLbl.Text=DateTime.Now.ToUniversalTime().ToShortDateString();
        //total Q number

        totalQNoREsLbl.Text=totalQNumber.ToString();
        //Total Score (as Total Question number * 100 )

        totalScoreLbl.Text=(totalQNumber*100).ToString();
        //Your Score (as your correct answers * 100)

        scoreLbl.Text=(score*100).ToString();
        //number of correct answers

        correctAnswersLbl.Text=score.ToString();
        //passing score

        passingScoreLbl.Text=(totalQNumber*100/2).ToString();
        //Time Spent

        timeTakenLbl.Text=spentTime.Hours.ToString()
                +"<font color=\"#666699\">:</font>"
                +spentTime.Minutes.ToString()
                +"<font color=\"#666699\">:</font>"
                +spentTime.Seconds.ToString()
                +"<font color=\"#666699\" size=\"1\">Hr(s).</font>";


        //Success or ...!

        if((score*100/totalQNumber)<50)
        {
            gradeLbl.ForeColor=Color.Red;
            gradeLbl.Text="Failed";
        }
        else
        {
            gradeLbl.ForeColor=Color.Green;
            gradeLbl.Text="Success";
        }
    }//end method

Done ..........!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here