Solved

Urgent: ASP Quiz Time Tracker - keeping track of the total time it takes a user to complete the quiz.

Posted on 2004-09-10
26
402 Views
Last Modified: 2012-06-27
I'm creating an ASP Quiz that dynamically gets questions from an SQL database.  I want to incorporate some kind of timer in this quiz, preferrably keep track of the total time it takes them to take the quiz.  This will help in determining if they looked the answers up on the internet.  I could do a countdown timer and skip to next question after so many seconds but it sounds a little more difficult and I'm on time constraints.

My problem:  I loop through the database until the question field is EOF.  Each multiple answer choice is considered a link so when they click on it, the next question appears along with a page refresh. So the ASP Timer() function doesn't work because it is constantly resetting every time it retrieves the next question.  I know using radio buttons for the quiz may be easier but I want one question to appear at a time.

Not sure if we are allowed to put code snippets on here but below is the part of my quiz that checks for the last question and either displays the results or displays the next question with appropriate choices.

Once they see the first question, how can I keep track of the length of time it takes for them to complete the entire quiz and see the results page?

Let me know if displaying a countdown timer (20 sec) and then going to the next question if they don't hit anything is easier.  I am up for either option.

Thank you ahead of time.
--------------------------- Code Snippet of Quiz
If Not bAbort Then

      ' Set NumberOfQuestions to a local variable to avoid accessing the collection each time
      iNumberOfQuestions = Session("NumberOfQuestions")

      ' Check to see if quiz is complete. If so, calculate and display results
      If iQuestionNumber > iNumberOfQuestions Then
      
      ' Set AnswerString to a local variable to avoid accessing the collection each time
      strAnswers = Session("AnswerString")

      ' Retrieve the correct answers and compare them to the entered ones
      Set rsQuiz = Server.CreateObject("ADODB.Recordset")
      rsQuiz.ActiveConnection = MM_DBConn_STRING
      rsQuiz.Source = "SELECT * FROM sk116062.Questions WHERE QuizID = 100 ORDER BY QuestionNumber"
      rsQuiz.CursorType = 0
      rsQuiz.CursorLocation = 2
      rsQuiz.LockType = 1
      rsQuiz.Open()
                        
      iScore = 0
      iGenericVariable = 1
      Do While Not rsQuiz.EOF
                      If UCase(CStr(rsQuiz.Fields("CorrectAnswer").Value)) = _
                      GetAnswerFromAnswerString(iGenericVariable, strAnswers) Then
            iScore = iScore + 1
            Else
            strResults = strResults & iGenericVariable & ", "
            End If
                        
            GenericVariable = iGenericVariable + 1
            rsQuiz.MoveNext
      Loop

      ' Close and dispose of our DB object
      rsQuiz.Close()
      Set rsQuiz = Nothing

      ' Convert score to a percentage rounded to the whole number
      iScore = Round((iScore / iNumberOfQuestions) * 100)
            
      %>
            
      <div align="center"><Font Size="+3"><B><%= Session("vQuizName") %></B></FONT></div><BR>
            
      <%
      If Len(strResults) <> 0 Then
      Response.Write "You missed the following questions: " & Left(strResults, Len(strResults) - 2)
      Response.Write "<BR>" & vbCrLf
      End If
      %>
            
      <p>&nbsp;</p>
      <form name="Continue" method="post" action="highscores.asp">
      <div align="center">
        <input type="submit" name="Submit" value="      Continue      ">
      </div>
      </form>
            
      <%
      Else
                  
      ' Retrieve question information from DB                        
      Set rsQuiz = Server.CreateObject("ADODB.Recordset")
      rsQuiz.ActiveConnection = MM_DBConn_STRING
      rsQuiz.Source = "SELECT * FROM sk116062.Questions WHERE QuizID = 100 AND QuestionNumber=" & iQuestionNumber & ";"
      rsQuiz.CursorType = 0
      rsQuiz.CursorLocation = 2
      rsQuiz.LockType = 1
      rsQuiz.Open()      
                        
      ' Set the question information
      strQuestionText = CStr(rsQuiz.Fields("QuestionText").Value)
                  
      ' Get an array of answers
      aAnswers = Array( _
      CStr(rsQuiz.Fields("AnswerA").Value & ""), _
      CStr(rsQuiz.Fields("AnswerB").Value & ""), _
      CStr(rsQuiz.Fields("AnswerC").Value & ""), _
      CStr(rsQuiz.Fields("AnswerD").Value & ""))
                        
      ' Calculates wrong and right answers
      For iGenericVariable = LBound(aAnswers) To UBound(aAnswers)
            If aAnswers(iGenericVariable) = "" Then
            ReDim Preserve aAnswers(iGenericVariable - 1)
            Exit For
            End If
      Next 'iGenericVariable

      ' Close and dispose of our DB object
      rsQuiz.Close()
      Set rsQuiz = Nothing
            
      ' Show the appropriate questions and answer choices
      %>
            
      <div align="center"><FONT SIZE="+3"><B><%= Session("vQuizName") %></B></FONT></div><BR>
            Question <%= iQuestionNumber %> of <%= iNumberOfQuestions %><BR>
      <BR>
      <STRONG><%= iQuestionNumber %>.</STRONG>&nbsp;&nbsp;<%= strQuestionText %><BR>
      <BR>
      <STRONG>Choices:</STRONG>
            
      <OL TYPE="A">
      <%
      For iGenericVariable = LBound(aAnswers) to UBound(aAnswers)
            Response.Write "<LI><A HREF=""" & Request.ServerVariables("URL")
            Response.Write "?QuizID=" & iQuestionNumber & "&LastQuestion=" & iGenericVariable & """>"
            Response.Write aAnswers(iGenericVariable) & "</A></LI>" & vbCrLf
      Next 'iGenericVariable
      %>
      </OL>
            
      <%                  
      End If
End If
%>
0
Comment
Question by:kruegerste
  • 11
  • 10
  • 3
  • +2
26 Comments
 
LVL 63

Expert Comment

by:Zvonko
ID: 12030997
You could autosubmit the form after some predefined amount of time.
If the the form is submitted befor the timeout, then is the timer gone anyway.

Like this:
<form name="Continue" method="post" action="highscores.asp">
<script>setTimeout("document.Continue.submit()", 20000)</script>



0
 
LVL 19

Expert Comment

by:peh803
ID: 12031033
You could have a javascript function that executes on pageload that increments a hidden form field counter every second.  Then, when you answer a question, you post this value to the next page in the quiz and continue counting from there.  

If you like the idea, let me know...I could probably put together a working example for you.

regards,
peh803
0
 
LVL 4

Author Comment

by:kruegerste
ID: 12031154
Zvonko,
The form you are referencing in the quiz is only displayed on the results page after currentQuestion# > total#Questions.  

Peh803,

I think this is what I'm looking for.  I thought the easiest way would be on the client-side with javascript which I have no problem with but I have difficulty understanding how ASP (vbscript - server side) interacts with javascript (client side).  Here are my two biggest questions pertaining to this because I have tried javascript already and failed:

1. How do I tell the jscript function to stop when the last question is answered becuase they don't go to a new page when the quiz is over, the results are just shown and then they click a "continue" button that writes all the information to the DB and displays the high scores?

2. How do I pass a variable (total time) from jscript to a ASP page where I can write it to the database with the other information (#correct, score % and username)?  Are there session variables in javascript that ASP can access?

I would very much appreciate it if you could write something up for me.  This is the way I was sort of leaning but I encountered the above road blocks.

Thanks
0
 
LVL 19

Expert Comment

by:peh803
ID: 12031235
I'd be happy to come up with an example for you, but unfortunately I don't have the time right now to do it.  Would it be too late if I put something together for you tomorrow?

An overview of the structure might help you see where I'm going with this:

Program Flow
--------------------------
1.) Display a question from the database
2.) start a javascript counter in the background for this question.  This counter increments a value in a hidden form field (called "currentQuestionTime") every second.
3.) the form contains another hidden form field called "totalTime" which has a value set to 0 initially.
4.) every time the user answers a question, the form gets posted to the new question (the form would now contain the number of seconds the user spent on this question, the total number of seconds so far, as well as the question number and the answer he has provided for the question).  You can take this information and stick it into the db for each question as you like.  
5.) As far as how to handle the end of the quiz, this shouldn't be a problem.  Sure, you'll want to disable the javascript counter, but you don't need to worry about this until the results page comes up.  Once you finish the last question (user answers it and you post to the results page), you can code some specific flag into your querystring that tells the ASP that renders the JS to not load the timer() function.  
6.) At the end of the quiz, your results page will have the final question's form posted to it.  The form will contain the question number, the number of seconds it took the user to answer the question, the answer provided, as well as the cumulative number of seconds the user took on the other questions in the quiz.

Hope this helps for now.  I *Should* be able to provide a basic working example tomorrow.

cheers,
peh803
0
 
LVL 4

Author Comment

by:kruegerste
ID: 12031321
Sounds good, I do have a few questions about the functionality but I'm sure those will get cleared up after I see some of the code.  I put urgent on the heading because I wasn't sure how long it takes to get responses.  Never would have thought they were this quick.  Tomorrow is fine.

Thank you.
0
 
LVL 46

Expert Comment

by:fritz_the_blank
ID: 12031585
One other option would be to set a session variable when the first page loads. Then you can grab the time when the quiz is over and use the DateDiff() method to calculate the expired time. The advantage of this approach is that you don't need all of the hidden fields, nor do you need to rely on client-side JavaScript.

Fritz the Blank
0
 
LVL 46

Expert Comment

by:fritz_the_blank
ID: 12031600
So on page 1 when it loads:

dim datTimeStart
Session("datTimeStart") = Now()

and then when the final question is submitted:

dim datTimeFinish
datTimeFinish  = Now()

dim numMinutes
numMinutes = DateDiff("n",datTimeStart,datTimeFinish)

Response.write("You took " & numMinutes & " to complete this quiz!")


Fritz the Blank
0
 
LVL 19

Expert Comment

by:peh803
ID: 12031642
@@Fritz -- I like your solution.  

You can still get the number of seconds per question (if you want) and I'm always a fan of the path of least resistance (or at least, number of lines of code!).

@@kruegerste: let me know if you'd like me to come up with a working prototype of my plan that I outlined.  

Obviously, Fritz has you on the right track if you like his solution.

Either way, let me know what you'd like from me.

regards,
peh803
0
 
LVL 46

Expert Comment

by:fritz_the_blank
ID: 12031667
If you want to force the user to move on after a certain amount of time, you can always use the meta refesh to force a move to the next page.

FtB
0
 
LVL 4

Author Comment

by:kruegerste
ID: 12031886
FtB,

I tried this way already but I forgot to set datTimeStart to a Session variable so it started over every time a new question was displayed.  I put in your code in the quiz but it displays this:

You took 55066716 to complete this quiz!

Is this the correct syntax to dispaly the difference between session variable datTimeStart and datTimeFinish.  

dim numMinutes
numMinutes = DateDiff("n",datTimeStart,datTimeFinish)

I put a response.write datTimeStart in the questions loop and it did display the current time every time a new question was displayed and I also added response.write datTimeFinish at the end and it displayed the correct end time.  Something looks wrong with the DateDiff function.  Please advise.

One problem I did notice is that if I refresh the page when the results are finally displayed, the datTimeFinish changes to the current time.  Is there anyway to prevent them from hitting the back button or refreshing the page so the time doesn't change or the data isn't inserted twice into the DB?

Thanks.
0
 
LVL 4

Author Comment

by:kruegerste
ID: 12031899
peh803,

Wait a minute on your write up until I can see if Fritz can help me with his idea.  I'm a little more familar with what he suggested.  I will let you know if this doesn't work.

Thanks for your ideas.
0
 
LVL 46

Expert Comment

by:fritz_the_blank
ID: 12031926
Okay, let's take a quick look at this.

What do you get if you put this on the last page of your quiz?

Response.write("Start: " & Session("datTimeStart") & "<P>")
Response.write("End: " & Session("datTimeFinish") & "<P>")

FtB
0
 
LVL 4

Author Comment

by:kruegerste
ID: 12032016
I just put this in and this is what I got.  I changed datTimeFinish to a session variable because you didn't have it as that in the first post.

Start: 9/10/2004 7:11:34 PM
End: 9/10/2004 7:11:34 PM

After running it a couple times I started to get 0 minutes as the answer and I see why now.  

Keep in mind that my whole quiz (from displaying every question to displaying the results) are all done on the same page (quiz1.asp).  I just have them displayed as I move through a control loop so the quiz1.asp is refreshed everytime the next question is retrieved but it is still the same page.  Not sure if this has anything to do with it.

Where do I put the first session variable (datTimeStart) in my page?  Maybe I'm putting this part of the code in the wrong spot.  I know where the datTimeFinish has to go because there is a small part of the quiz that is executed if the questions run out.
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
LVL 46

Expert Comment

by:fritz_the_blank
ID: 12032058
Okay, now that explains a lot!


Let's try this on the first page:

if Session("datTimeStart") ="" or IsEmpty(Session("datTimeStart")) or isNull(Session("datTimeStart")) then
     Session("datTimeStart") = Now()
end if

Now we will need to figure out how to populate the end variable, perhaps if we have .eof on your recordset?

FtB
0
 
LVL 46

Expert Comment

by:fritz_the_blank
ID: 12032066
So with the above, the start variable will not be reset.

Now what we need to do is figure out how to set the Session("datTimeFinish") variable. Again, we should use the same logic:

if Session("datTimeFinish") ="" or IsEmpty(Session("datTimeFinish")) or isNull(Session("datTimeFinish")) then
     Session("datTimeFinish") = Now()
end if


That way, a refresh won't repopulate the variable.

FtB
0
 
LVL 4

Author Comment

by:kruegerste
ID: 12032146
That works with respect to the value of the two session variables.  I got this:

Start: 9/10/2004 7:50:49 PM
End: 9/10/2004 7:51:27 PM

The only problem is that I'm still getting this output for the DateDiff function as:

You took 0  to complete this quiz!

Is this for sure the correct syntax to display the difference for the two or do I need to put session or something in there?  I have tried a couple different ways but nothing has worked.

numMinutes = DateDiff("n",datTimeStart,datTimeFinish)

Since the session variables don't change on refresh, when I go to the quiz homepage and take a different quiz, the session variables are stuck on the previous values and won't take the new time.  Do I just create three different session variables for each quiz or is there a better way?
0
 
LVL 4

Author Comment

by:kruegerste
ID: 12032185
I found the other problem.  I was using "n" in the DateDiff function for minutes but I was completing my testing quiz in under 1 minute so the result was 0.  Would I use some kind of IF THEN loop to determine what length to use?  Not sure how to do this.

If user completes in 45 seconds I need it to display 45 seconds.
If user completes in 90 seconds I need it to display 1 minute 30 seconds
If user completes in 120 seconds I need it to display 2 minutes

How can I do this?
0
 
LVL 4

Author Comment

by:kruegerste
ID: 12032206
Pertaining to my last post, if I use "n" for minutes and the following is true:

Start Time:  8:10:59
End Time:    8:13:01

It considers this as three minutes (13-10) even though it is actually 2 minutes and 2 seconds.  It obviously just looks at the minute values.  Do I have to use multiple DateDiff functions to find seconds and minutes and then display accordingly?

0
 
LVL 46

Expert Comment

by:fritz_the_blank
ID: 12032257
If you would like seconds, you just need to change the parameter for the DateDiff() method:

numSeconds = DateDiff("s",datTimeStart,datTimeFinish)

FtB
0
 
LVL 46

Expert Comment

by:fritz_the_blank
ID: 12032259
From there, of course, you would have to use some Mod 60 arithmetic.

Please let me know if you need help with that...

FtB
0
 
LVL 4

Author Comment

by:kruegerste
ID: 12033054
FtB,

Thanks for all the help but I have a couple last questions for this post and I promise I will be done for here.

Did you see my last question by chance.  With your method here, what do I do if the user wants to take the same quiz over while in the same session?  I can't make the user logout after every quiz (there are about 20 different quizzes).  I think I can use different session variables for each different quiz but I'm not sure what to do about taking the same quiz twice in a row.  I need to somehow clear the session variable when the page is initially loaded but not sure how.  

Also, I tried this below for the Mod 60 arithmetic but it isn't working:

If NumSeconds > 59 Then
       Dim xMinutes = (Fix(NumSeconds/60))
       Dim xSeconds = NumSeconds mod 60
       Response.Write ("The quiz took " & xMinutes & " minutes and " & xSeconds & " seconds.")
Else
       Response.Write ("The quiz took " & xSeconds & " seconds.")
End If

What am I doing wrong here?

Thanks again.
0
 
LVL 1

Expert Comment

by:Webby_
ID: 12033850
Here's a nice javascript that displays a live seconds countdown ... just replace the refresh action when it reaches zero for a previous mentioned action here like submit to next page without answer selected..

http://dynamicdrive.com/dynamicindex6/refresh.htm
0
 
LVL 46

Accepted Solution

by:
fritz_the_blank earned 500 total points
ID: 12034068
Okay, what you want to do when you start a new quiz is to call the session.abandon method. That will clear out all session variables so that you can start fresh. The syntax is simply:

Session.Abandon


As for the mod 60 arithmetic, there is no built in MOD function, so you just need to do this yourself. So you start of with numSeconds:

numMinutes = Int(numSeconds/60)
numSeconds = numSeconds - 60*numMinutes

("The quiz took " & numMinutes & " minutes and " & numSeconds & " seconds.")

Fritz the Blank
0
 
LVL 46

Expert Comment

by:fritz_the_blank
ID: 12034071
BTW, you are very welcoime.

FtB
0
 
LVL 4

Author Comment

by:kruegerste
ID: 12034491
FtB,

About the Session.Abandon,  if they take the same quiz again - it obviously abandons the whole session so they get redirected to the login page and must login again.  Is there any other way to do this so the user doesn't have to login a million times?

Thanks.
0
 
LVL 46

Expert Comment

by:fritz_the_blank
ID: 12034519
Sure, you can also do the remove contents method of the session like this:

Session.Contents.Remove("datTimeStart")
Session.Contents.Remove("datTimeFinish")

That way, you don't need to call the session.abandon--you can just clear out those values.

FtB
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

I recently decide that I needed a way to make my pages scream on the net.   While searching around how I can accomplish this I stumbled across a great article that stated "minimize the server requests." I got to thinking, hey, I use more than one…
I was asked about the differences between classic ASP and ASP.NET, so let me put them down here, for reference: Let's make the introductions... Classic ASP was launched by Microsoft in 1998 and dynamically generate web pages upon user interact…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now