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:
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 (
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:
///
/// Retrive Question and its Choices from
/// XML file and render it to screen
///
/// 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 methodAfter that, the user reviews answers history and is allowed to go back or view score report Review():
///
/// generate Review Report
/// by retrive user answers from historyALst ArrayList
/// and Bookmarked Question(s) from bookmarkLst ArrayList
/// and do user descion
///
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 methodIf the user decides to go back, then ReAnswer():
///
/// generate a list of bookmarked questions
/// and fire ShowQuestion() for first one
/// according to some rules
///
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 methodIn the end, call the Score report: ShowResult()
///
/// generate Score Report
/// by some simple calculations
///
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()
+":"
+spentTime.Minutes.ToString()
+":"
+spentTime.Seconds.ToString()
+"Hr(s).";
//Success or ...!
if((score*100/totalQNumber)<50)
{
gradeLbl.ForeColor=Color.Red;
gradeLbl.Text="Failed";
}
else
{
gradeLbl.ForeColor=Color.Green;
gradeLbl.Text="Success";
}
}//end methodDone ..........!
No comments:
Post a Comment