Director Scripts for Generic Quiz

| Movie Scripts | Parent Scripts |
NOTE: The character "¬" corresponds to the continuation mark for a long script line.

movie Scripts

-- Generic Quiz Movie version 0.9 (Aug 16, 1995)
-- This movie is an implementation of a generic quiz algorithm we've
-- used in HyperCard and Toolbook. The idea is to have a bank of multiple
-- choice questions that are presented each time in random order and for each view
-- the answers are also shuffled in order.

-- This movie uses a the parent script "quizMother" to child objects, each one
-- representing a question. Each pobject consists of a property list that holds 
-- the questions, answers, feedback, etc.

-- Another parent script "randMother" creates objects used for making the randomly
-- sorted lists needed.

on startMovie
  -- Generate the first quiz objects
  makeQuiz
end

on makeQuiz
  -- generate the whole quiz structure, called each time a new quiz is generated
  global gTotQuiz, gQuizList, gQuizOrder, gScore, gMissed
  
  -- initialize globals ->
  --    gScore:    users score
  --    gMissed:   list of topics missed
  --    gTotQuiz:  number of quiz questions
  set gScore = 0
  set gMissed = []
  set gTotQuiz = numberOfQuestions()
  
  -- first build a list of quiz objects; each child contains the info for
  -- an entire quiz question
  set gQuizList to []
  repeat with i = 1 to gTotQuiz
    add gQuizList, birth(script "quizMother", i)
  end repeat
  
  -- now generate a random list that determines the order in which quiz questionx
  -- are presented
  set gQuizOrder to birth(script "randmother", gTotQuiz)
end makeQuiz

on newQuiz
  --  called to set up wach question in the quiz
  global gTotQuiz, gQuizOrder, gFirstAnswer
  
  -- increment the counter by 1
  updateItemCounter(gQuizOrder)
  
  -- set flag for checking if user has attempted to answer
  set gFirstAnswer to TRUE
  
  -- move the arrow button off stage until user tries on answer
  set the locv of sprite 6 to 500
  
  -- update screen counter
  put the currentItem of gQuizOrder && "of" && gTotQuiz into field "counter"
  
  -- check to see if past the end of the list fo questions
  if the currentItem of gQuizOrder > gTotQuiz then 
    
    -- go to results screen
    goResults
    
  else
    -- display the new question and possible answers
    put getaProp( currQuestionInfo(),#ans1 ) into field "ans1"
    put getaProp( currQuestionInfo(),#ans2 ) into field "ans2"
    put getaProp( currQuestionInfo(),#ans3 ) into field "ans3"
    put getaProp( currQuestionInfo(),#ans4 ) into field "ans4"
    put getaProp( currQuestionInfo(),#question) into field "question"
    put getaProp( currQuestionInfo(),#topic) into field "topic"
    
    -- move feedback field off stage
    set the loch of sprite 10 to -500
    
    -- scramble the location of the answer fields
    shuffleAnswers
    updateStage
  end if  
end

on checkAnswer
  -- called by mouseUp on the answer fields
  global gTotQuiz, gQuizList, gQuizOrder, gFirstAnswer, gScore, gMissed
  
  -- identify which answer was clicked 
  --   (from names of fields "ans1" to "ans4"
  set clickedAnswer to char 4 of the name of cast (the castNum of sprite the clickOn)
  
  -- put the corresponding feedback into the display field and move on stage
  do "put getaprop( currQuestionInfo(), #fb" & value(clickedAnswer) & ") ¬
      into field" && QUOTE & "feedback" & QUOTE
  set the locH of sprite 10 to 265
  updateStage
  
  -- If this is the first attempt for this question, score it
  if gFirstAnswer then
    
    -- compare to the correct answer
    if clickedAnswer = getAProp( currQuestionInfo(), #correct) then
      
      -- correct, increment score
      set gScore = gScore + 1
      
    else    
      -- incorrect; add topic to list if not already there
      if getOne( gMissed, getAProp( currQuestionInfo(), #topic)) = 0 then
        add gMissed, getAProp( currQuestionInfo(), #topic)
      end if
    end if
    
    -- set answer flag 
    set gFirstAnswer to FALSE
    set the locV of sprite 6 to 223
    updateStage
  end if
end

on goResults
  -- construct the results field based on scores
  global gScore, gMissed, gTotQuiz
  
  -- precentage needed to pass
  put 80 into passingScore
  
  set cursor to 4
  
  -- calculate score as percentage
  put integer( gScore * 100 / gTotQuiz )  into userScore
  
  -- reset the field format
  put " " into field "results"
  set the textStyle of field "results" to "plain"
  set the textSize of field "results" to 12
  
  -- put the score results in display field
  put "Results" & return & return & "You scored" && gScore && "correct on the first try"¬
  && "out of a total of" && gTotQuiz && "questions, or" ¬
  && userScore & "%." & return & return into field "results"
  
  
  if userScore >= passingScore then
    
    -- user passed minimum
    put "Since you exceeded " & passingScore & "%, you have passed the requirements"¬
    && "for this quiz." & return & return¬
    & "CONGRATULATIONS!" & return & return¬
    & "Click on the arrow button to receive your certificate."¬
    after field "results"
  else
    -- user did not pass minimum
    
    put "Since you scored less than " & passingScore & "%, you should review the information"¬
    && "for this unit. You may now redo the self check (click on the arrow button)" & return ¬
    & "----------------" & return¬
    & "TOPICS to REVIEW" & return¬
    & "(You may wish to write down the topics you missed)" & return & return after field "results"
    
    -- construct the list of missed topics
    repeat with i in gMissed
      put "  *" && i & return after field "results"
    end repeat
  end if
  
  -- format the first line of text
  set the textStyle of line 1 of field "results" to "bold"
  set the textSize of line 1 of field "results" to 18
  
  set cursor to -1
  go to frame "results"
end

on shuffleAnswers
  -- used to shuffle the order in which answer fields are displayed
  
  -- generate a random list for number 1,2,3,4
  set answerOrder = the randomList of birth (script "randmother", 4 )
  
  -- set the positions of the answer fields (sprite 2 - 5)
  repeat with i= 1 to 4 
    set the locH of sprite getAt(answerOrder,i) + 1  to 5
    set the locV of sprite getAt(answerOrder,i) + 1 to 70 + 30 * value(i)
  end repeat
end shuffleAnswers

on numberOfQuestions
  -- used to count the number of questions, assumed to 
  -- reside in cast members "q1", "q2", .... "qn"
  
  repeat with i=1 to 100
    if the number of cast ("q" & i) = -1 then return i -1
  end repeat
  return 100
end


-- these two functions simplified the lingo used in the other handlers
on currQuestionInfo
  -- return the property list that contains info for current question
  global gQuizList
  return the quizParam of getAt( gQuizList,currQuestionNumber() )
end

on currQuestionNumber
  -- return the current postion in th elist of quiz questions
  global gQuizOrder  
  return getAt(the randomList of gQuizOrder,the currentItem of gQuizOrder)
end

| Movie Scripts | Parent Scripts |
This first script is used to generate an object that is a list of numbers that are randomly shuffled. The second script is used to generate the quiz.
--       script "RandMother"
--   random list generator
--   after "working with Lists and Objects", Lingo Users Journal
--   Aug 1995

property currentItem, listSize, randomList

on birth me, listLength
  -- creat a random list with the number of items = listlength
  set the listsize of me to listLength
  makeList me
  return me
end

on makeList me
  set the randomList of me to []
  
  -- insert each number 1,2,3,.. listSize to a random
  --    position in the list
  repeat with i=1 to the listsize of me
    addAt( the randomList of me, random(i), i )
  end repeat
  
  -- pointer to n item in the list
  set the currentItem of me to 0
end

on updateItemCounter me
  -- increment pointer
  set the currentItem of me to the currentItem of me + 1
end
this is the "quizmother" script. It creates an object that is a Director property list that contains all of the information for the current quiz.
property quizParam

on birth me, quizCast
  -- create temp variable to hold quiz info (reading from a variable is faster
  --   then reading from text cast member)
  put field ("q" & quizCast) into quizInfo
  
  -- create the quiz information as a property list
  set the quizParam of me to [ #question:line 1 of quizInfo]
  setaProp the quizParam of me, #correct, line 10 of quizInfo
  setaProp the quizParam of me, #topic, line 11 of quizInfo
  
  -- These loops set the answer text and feedback text
  repeat with i=2 to 5
    do "setaProp the quizParam of me, #ans" & i-1 && ", line" && i && "of quizInfo"
    do "setaProp the quizParam of me, #fb"  & i-1 && ", line" && i + 4 && "of quizInfo"
  end repeat
  return me
end