# Maplet coded by Adrian S. Laney and Hope Thomas with the wonderful help of Dr. Phil Yasskin # Coded December, 2002 # MATH 253 Section 201 # Adrian Laney # Hope Thomas restart: with(Maplets): with(Maplets[Tools]): with(Maplets[Elements]): with(plots): with(combinat, randperm): ## Setting the randomize seed to the system clock randomize(): StartEngine(); correctReply:=[ "Wow! You're super! How about another?", "You are so smart. Try another!", "Way to go! See if you can get the next one...", "That is correct. Try the next one.", "That's the way to do it. Keep it up.", "You survived elimination. Can you answer the next one though?", "Your mental strength is showing. Don't stop now!", "Good work. Try the next problem.", "Truly, you have a dizzying intellect. ", "Indeed, you are powerful, as the Emperor has forseen... " ]: randCorrect:= rand(1..nops(correctReply)): wrongReply:=[ "Please try again. ", "Not quite. ", "Incorrect. Maybe you should phone a friend. ", "You are the weakest link. ", "Maybe you should use a lifeline. ", "Not correct. Try again. You have at least a 75% chance, right? ", "Incorrect. You have been voted off of the show. ", "I'm sorry, but that is not correct. ", "Close, but no cigar. ", "Close only counts in horseshoes and hand grenades, so try again, because this is neither. ", "It can't be that hard, can it? Try one more time.", "What made you think that was the answer? Try again, you silly wabbit. ", "That answer was not correct. Try again. ", "You must be having a bad day... ", "Use the force, trust your feelings... " ]: randWrong:= rand(1..nops(wrongReply)): showCorrectReply:=[ "The correct plot has now been selected. ", "This shows you the correct plot. ", "The answer has been made known to you. ", "To be correct, one would choose this plot. ", "Come on, you could have guessed this. ", "You didn't really need me to show you, did you? ", "You must have pressed this by mistake, but I'll show you the correct plot anyway. " ]: randShowCorrect:= rand(1..nops(showCorrectReply)): nextQuestionReply:=[ "That's the spirit. ", "Keep it up. ", "Congratulations! You have a new challenge. ", "As you wish. A new question. ", "A new quest has been presented to you. ", "I knew you wouldn't bail out, now try this one! " ]: randNextReply:= rand(1..nops(nextQuestionReply)): ## Defining the possible random functions, the variables n, m, o, and p are random number generators. functions:= [ x-> x^m() + p()*x^n(), x-> sin(o()*x), x-> cos(o()*x), x-> tan(o()*x), x-> exp(x^m()), x-> ln(x^n()), x-> 1/x^o(), x-> sqrt(x^o()), x-> abs(x^o()) ]: ## Defining the random number ranges n:= rand(1..5): m:= rand(2..5): o:= rand(1..3): p:= rand(-1..1): randfunc:= rand(1..nops(functions)): ## THIS PROCEDURE IS FOR THE FIRST DERIVATIVE AND ONLY FUNCTION SECTIONS genFuncAndPlots:= proc() global currentFunction, correctAnswer, plot_f, plot_Df, plot_DDf, plot_negDf, plot_negf, plotAnswerArray, multChoiceOrder, plot_A, plot_B, plot_C, plot_D; local f, i; ## Generating the current random function currentFunction:= functions[randfunc()](x): while currentFunction = 0 do currentFunction:= functions[randfunc()](x): end do; f:= unapply(currentFunction, x); ## Assigning the plot of the current function plot_f:= plot(f, -5..5, y=-5..5, 'numpoints'=150, 'color'='blue', 'thickness'=3): ## Assigning the plots of the possible answers plot_Df:= plot(D(f), -5..5, y=-5..5, numpoints=150, 'color'='red', 'thickness'=3): plot_DDf:= plot(D(D(f)), -5..5, y=-5..5, numpoints=150, 'color'='red', 'thickness'=3): plot_negDf:= plot(-D(f), -5..5, y=-5..5, numpoints=150, 'color'='red', 'thickness'=3): plot_negf:= plot(-f, -5..5, y=-5..5, numpoints=150, 'color'='red', 'thickness'=3): ## This is the array of plots, which will be randomly ordered plotAnswerArray:= [plot_Df, plot_DDf, plot_negDf, plot_negf]: ## This is the random order for the plot choices A-D multChoiceOrder:= randperm([1,2,3,4]); ## Assigning all of the plots to a more useable name plot_A:= plotAnswerArray[multChoiceOrder[1]]: plot_B:= plotAnswerArray[multChoiceOrder[2]]: plot_C:= plotAnswerArray[multChoiceOrder[3]]: plot_D:= plotAnswerArray[multChoiceOrder[4]]: ## This will determine which plot, 1-4 (or A-B) is the correct answer ## Correct answer will be i when multChoiceOrder[i] = 1; if multChoiceOrder[1]=1 then correctAnswer:= 1 elif multChoiceOrder[2]=1 then correctAnswer:=2 elif multChoiceOrder[3]=1 then correctAnswer:=3 elif multChoiceOrder[4]=1 then correctAnswer:=4 else print("Program error, no correct answer found.") end if; ## This is going to be my attempt to update the questions window ## IT WORKED!!! Set('PlotOFf'::function = plots[display](plot_f)): Set('PlotA'::function = plots[display](plot_A)): Set('PlotB'::function = plots[display](plot_B)): Set('PlotC'::function = plots[display](plot_C)): Set('PlotD'::function = plots[display](plot_D)): Set('MML1' = MathML[Export](currentFunction)): ## Resetting the radio buttons all to false, in a tricky way! ## RadioButtonX is in the twilight zone! Set(thismaplet, 'RadioButtonX'('value') = 'true'); return end proc: ## THIS PROCEDURE IS FOR THE SECOND DERIVATIVE SECTION genFuncAndPlots2:= proc() global currentFunction, correctAnswer, plot_f, plot_Df, plot_DDf, plot_negDf, plot_negf, plotAnswerArray, multChoiceOrder, plot_A, plot_B, plot_C, plot_D; local f, i; ## Generating the current random function currentFunction:= functions[randfunc()](x): while currentFunction = 0 do currentFunction:= functions[randfunc()](x): end do; f:= unapply(currentFunction, x); ## Assigning the plot of the current function plot_f:= plot(f, -5..5, y=-5..5, 'numpoints'=150, 'color'='blue', 'thickness'=3): ## // Assigning the plots of the possible answers plot_Df:= plot(D(f), -5..5, y=-5..5, numpoints=150, 'color'='red', 'thickness'=3): plot_DDf:= plot(D(D(f)), -5..5, y=-5..5, numpoints=150, 'color'='red', 'thickness'=3): plot_negDf:= plot(-D(f), -5..5, y=-5..5, numpoints=150, 'color'='red', 'thickness'=3): plot_negf:= plot(-f, -5..5, y=-5..5, numpoints=150, 'color'='red', 'thickness'=3): ## This is the array of plots, which will be randomly ordered plotAnswerArray:= [plot_Df, plot_DDf, plot_negDf, plot_negf]: ## This is the random order for the plot choices A-D multChoiceOrder:= randperm([1,2,3,4]); ## Assigning all of the plots to a more useable name plot_A:= plotAnswerArray[multChoiceOrder[1]]: plot_B:= plotAnswerArray[multChoiceOrder[2]]: plot_C:= plotAnswerArray[multChoiceOrder[3]]: plot_D:= plotAnswerArray[multChoiceOrder[4]]: ## This will determine which plot, 1-4 (or A-B) is the correct answer ## Correct answer will be i when multChoiceOrder[i] = 2; if multChoiceOrder[1]=2 then correctAnswer:= 1 elif multChoiceOrder[2]=2 then correctAnswer:=2 elif multChoiceOrder[3]=2 then correctAnswer:=3 elif multChoiceOrder[4]=2 then correctAnswer:=4 else print("Program error, no correct answer found.") end if; ## This is going to be my attempt to update the questions window ## IT WORKED!!! Set('PlotOFf'::function = plots[display](plot_f)): Set('PlotA'::function = plots[display](plot_A)): Set('PlotB'::function = plots[display](plot_B)): Set('PlotC'::function = plots[display](plot_C)): Set('PlotD'::function = plots[display](plot_D)): Set('MML1' = MathML[Export](currentFunction)): ## Resetting the radio buttons all to false, in a tricky way! ## RadioButtonX is in the twilight zone! Set(thismaplet, 'RadioButtonX'('value') = 'true'); return end proc: checkMultChoice := proc() global correctAnswer, correctReply, randCorrect, wrongReply, randWrong; local userAnswer; if parse(Get(thismaplet, 'RadioButtonA')) then userAnswer:=1 end if; if parse(Get(thismaplet, 'RadioButtonB')) then userAnswer:=2 end if; if parse(Get(thismaplet, 'RadioButtonC')) then userAnswer:=3 end if; if parse(Get(thismaplet, 'RadioButtonD')) then userAnswer:=4 end if; if correctAnswer = userAnswer then Set('responseArea'::string = correctReply[randCorrect()] ): else Set('responseArea'::string = wrongReply[randWrong()] ): end if; end proc: showCorrectAns:= proc() global correctAnswer, showCorrectReply, randShowCorrect; if correctAnswer = 1 then Set(thismaplet, 'RadioButtonA'('value') = 'true') elif correctAnswer = 2 then Set(thismaplet, 'RadioButtonB'('value') = 'true') elif correctAnswer = 3 then Set(thismaplet, 'RadioButtonC'('value') = 'true') elif correctAnswer = 4 then Set(thismaplet, 'RadioButtonD'('value') = 'true') else print("Program error, no correct answer found.") end if; Set('responseArea'::string = showCorrectReply[randShowCorrect()] ): return end proc: genNextReply:= proc() ## This procedure will update the reply area each time next question is clicked global randNextReply, nextQuestionReply; Set('responseArea'::string = nextQuestionReply[randNextReply()]); end proc: ## THIS PROCEDURE CLEARS THE RESPONSE AREA WHEN EACH WINDOW IS CLOSED clearResponseArea:= proc() Set('responseArea'::string = " "): end proc: sampleplot:=proc() ###Plot on first window local F, G, sp; F:=plot(sin(2*x), x=-2*Pi..2*Pi, y=-2.5..2.5, 'color'='red', 'thickness'=3, 'legend'="A Function"): G:=plot(2*cos(2*x), x=-2*Pi..2*Pi, y=-2.5..2.5, 'color'='blue', 'thickness'=2, 'legend'="The Derivative of the Function"): sp:=display({G,F}): Set('sampleplot'= sp); end proc: RecognizingDerivatives:= Maplet(onstartup = StartUp, #################### BEGIN MAIN WINDOW #################### Window[MAIN]('defaultbutton'='InstrButton', 'title'="Recognizing Derivative Plots", [ [ Button("First Derivative", 'onclick'='BeginQuestions'), Button("Function Only", 'onclick'='OnlyFunction'), Button("Second Derivative", 'onclick'='SecondDerivative') ], [ " ", Plotter['sampleplot']('width'=300,'height'=400), " " ], [ Button("Instructions", 'reference'='InstrButton', 'onclick'='Instructions'), Button("Hints", 'onclick'='Hints'), Button("Exit", Shutdown()) ] ] ), #################### END MAIN WINDOW #################### #################### BEGIN INSTRUCTIONS WINDOW #################### Window[InstrWindow]('title'="Instructions", [ [ TextBox['InstrBox']("This program is designed to help teach the concept of recognizing the graph of a derivative of a function, as well as the second derivative, with and without the aid of a plot of the original function. The program is rather self-explanatory, but we will outline its basic functionality here. \n\nThere are three different sections in this program. \n\n\"First Derivative\" Section:\n * The first section may be accessed by clicking \"First Derivative\". This will bring up a window that contains a plot of a function on the left, and four plots on the right. Only one of these is the plot of the derivative of the function on the left. Select the correct answer with the mouse by clicking on one of the radio buttons labeled A through D. \n * To check that your answer is correct, press the \"Check Answer\" button. A message will appear telling you whether or not you answered correctly. If you did not, you will be given the opportunity to try again.\n * If you cannot figure out the correct answer, press \"Show Answer\". This will automatically select the radio button corresponding to the correct plot choice. \n * Once you have the correct answer, you can go on to the next question by pressing \"Next Question\". There are many possible functions, so try as many as you like. \n * If you need help recognizing the graph of the first or second derivative, press \"Hints\".\n * To return to the Main window, press \"Close\". \n\n\"Function Only\" Section \n * To access the second section, press \"Function Only\" in the Main window.\n * This section is essentially the same as the first. The difference is that you are not given the plot of the function, you are only given the function itself.\n * It is recommended that you try a few problems from the first section before you access this section. \n * The rest of this section has the same functionality as the first.\n\n\"Second Derivative\" Section\n * The third section is again very similar to the first, in that it supplies you with both the function and its plot, but instead of asking for the first derivative, it asks for the correct plot of the second derivative. \n * Once again, the rest of this section has the same functionality as the first.\n\nTo get help with first and second derivatives, press \"Hints\" in the Main window.\n\nTo exit this program completely, press \"Exit\" in the Main window. \n\nNOTE: Only one section in the program can be opened at one time. \n\nAny questions or known problems with this software should be sent to: \nAdrian S. Laney . \n\nThank you for using this software. It is free and uncopywrited, use the source code in any way you wish, as long as it is not for profit. If you like this program, please e-mail me at the address above and let me know! ", 'editable'='false', 'background'='wheat', 'width'=60, 'height'=2, 'wrapped'='true', 'font' = Font("helvetica", bold, 14), 'height'=22 ) ], [ Button("Return To Main Window", CloseWindow('InstrWindow')) ] ] ), #################### END INSTRUCTIONS WINDOW #################### #################### BEGIN HINTS WINDOW #################### Window[HintWindow]('title'="Hints", [ [ TextBox['HintBox']("Determining what the plot of the first derivative will look like:\n\n * Is the original function increasing or decreasing on a certain region? What would this imply about the derivative on that region?\n * If the plot is not given, try differentiating the function, and imagining what the plot would look like.\n * The derivative is the slope of the tangent line to the curve at any given point, so try to imagine where the slope of the original function is positive, and where it is negative.\n\nDetermining what the plot of the second derivative will look like:\n\n * Is the graph of the original function concave up or concave down on a given region? What would this imply about the graph of its second derivative? \n * In terms of the slope of the original function, is it increasing or decreasing over a region, and what would this tell you about the graph of the second derivative in that region?", 'editable'='false', 'background'='wheat', 'width'=60, 'wrapped'='true', 'font' = Font("helvetica", bold, 14), 'height'=15 ) ], [ Button("Return To Main Window", CloseWindow('HintWindow')) ] ] ), #################### END HINTS WINDOW #################### #################### BEGIN MULTIPLE CHOICE FROM A GRAPH OF F WINDOW #################### Window['MultChoicePlots']('title'="Which is the plot of the derivative of f?", [[[ [ " " ], [ " " ], [[ [Label("Below is a plot", 'font' = Font("helvetica", bold, 17), 'foreground'='navy')], [Label("of a function f:", 'font' = Font("helvetica", bold, 17), 'foreground'='navy')] ]], [ " " ], MathMLViewer[MML1]('value'=MathML[Export](currentFunction), 'background'='wheat', 'width'=150, 'height'=70), [ " " ], [ " " ], ## PLOT OF f [ [Plotter['PlotOFf'](plot_f, 'width'=250, 'height'=250)] ], RadioButton['RadioButtonX']("", 'value'='false', 'enabled'='false', 'visible'='false', 'group'='RadioGroup1'), [ " " ], [ " " ], [ " " ] ], [[ Label("Which of these is the plot of the derivative of f?", 'font' = Font("helvetica", bold, 15), 'foreground'='navy') ], ## MULTIPLE CHOICE AREA [ [ RadioButton['RadioButtonA'](" A", 'value'='false', 'group'='RadioGroup1'), Plotter['PlotA'](plot_A, 'width'=200, 'height'=200) ], [ RadioButton['RadioButtonB'](" B", 'value'='false', 'group'='RadioGroup1'), Plotter['PlotB'](plot_B, 'width'=200, 'height'=200) ] ], [ [ RadioButton['RadioButtonC'](" C", 'value'='false', 'group'='RadioGroup1'), Plotter['PlotC'](plot_C, 'width'=200, 'height'=200) ], [ RadioButton['RadioButtonD'](" D", 'value'='false', 'group'='RadioGroup1'), Plotter['PlotD'](plot_D, 'width'=200, 'height'=200) ] ], [ Button("Check Answer", Evaluate('function' = "checkMultChoice")), Button("Show Answer", Evaluate('function' = "showCorrectAns")), Button("Next Question", 'onclick'='NextQuestion'), Button("Hints", 'onclick'='Hints'), Button("Close", 'onclick'='CloseWindMultChoicePlots') ], [ TextBox['responseArea']("Let's get started! Select the correct choice with the mouse and press \"Check Answer\". Once you have completed the current question, press \"Next Question\" to continue. ", 'editable'='false', 'background'='wheat', 'width'=45, 'height'=3, 'wrapped'='true', 'font' = Font("helvetica", 13) ) ] ]]] ), #################### END MultChoicePlots WINDOW #################### #################### BEGIN ONLY THE FUNCTION, NO PLOT WINDOW #################### Window['JustFunc']('title'="Knowing the function f, which is the plot of the derivative of f?", [[[ [ " " ], [ " " ], [[ [Label("Below is the function f:", 'font' = Font("helvetica", bold, 17), 'foreground'='navy')] ]], [ " " ], MathMLViewer[MML1]('value'=MathML[Export](currentFunction), 'background'='wheat', 'width'=150, 'height'=70), RadioButton['RadioButtonX']("", 'value'='false', 'enabled'='false', 'visible'='false', 'group'='RadioGroup1'), [ " " ], [ " " ], [ " " ] ], [[ Label("Which of these is the plot of the derivative of f?", 'font' = Font("helvetica", bold, 15), 'foreground'='navy') ], ## MULTIPLE CHOICE AREA [ [ RadioButton['RadioButtonA'](" A", 'value'='false', 'group'='RadioGroup1'), Plotter['PlotA'](plot_A, 'width'=200, 'height'=200) ], [ RadioButton['RadioButtonB'](" B", 'value'='false', 'group'='RadioGroup1'), Plotter['PlotB'](plot_B, 'width'=200, 'height'=200) ] ], [ [ RadioButton['RadioButtonC'](" C", 'value'='false', 'group'='RadioGroup1'), Plotter['PlotC'](plot_C, 'width'=200, 'height'=200) ], [ RadioButton['RadioButtonD'](" D", 'value'='false', 'group'='RadioGroup1'), Plotter['PlotD'](plot_D, 'width'=200, 'height'=200) ] ], [ Button("Check Answer", Evaluate('function' = "checkMultChoice")), Button("Show Answer", Evaluate('function' = "showCorrectAns")), Button("Next Question", 'onclick'='NextQuestion'), Button("Hints", 'onclick'='Hints'), Button("Close", 'onclick'='CloseWindJustFunc') ], [ TextBox['responseArea']("Let's get started! Select the correct choice with the mouse and press \"Check Answer\". Once you have completed the current question, press \"Next Question\" to continue. ", 'editable'='false', 'background'='wheat', 'width'=45, 'height'=3, 'wrapped'='true', 'font' = Font("helvetica", 13) ) ] ]]] ), #################### END ONLY FUNCTION, NO PLOT WINDOW #################### #################### BEGIN SECOND DERIVATIVE CHOICE FROM A GRAPH OF F WINDOW #################### Window['SecDeriv']('title'="Which is the plot of the second derivative of f?", [[[ [ " " ], [ " " ], [[ [Label("Below is a plot", 'font' = Font("helvetica", bold, 17), 'foreground'='navy')], [Label("of a function f:", 'font' = Font("helvetica", bold, 17), 'foreground'='navy')] ]], [ " " ], MathMLViewer[MML1]('value'=MathML[Export](currentFunction), 'background'='wheat', 'width'=150, 'height'=70), [ " " ], [ " " ], ## PLOT OF f [ [Plotter['PlotOFf'](plot_f, 'width'=250, 'height'=250)] ], RadioButton['RadioButtonX']("", 'value'='false', 'enabled'='false', 'visible'='false', 'group'='RadioGroup1'), [ " " ], [ " " ], [ " " ] ], [[ Label("Which of these is the plot of the second derivative of f?", 'font' = Font("helvetica", bold, 15), 'foreground'='navy') ], ## MULTIPLE CHOICE AREA [ [ RadioButton['RadioButtonA'](" A", 'value'='false', 'group'='RadioGroup1'), Plotter['PlotA'](plot_A, 'width'=200, 'height'=200) ], [ RadioButton['RadioButtonB'](" B", 'value'='false', 'group'='RadioGroup1'), Plotter['PlotB'](plot_B, 'width'=200, 'height'=200) ] ], [ [ RadioButton['RadioButtonC'](" C", 'value'='false', 'group'='RadioGroup1'), Plotter['PlotC'](plot_C, 'width'=200, 'height'=200) ], [ RadioButton['RadioButtonD'](" D", 'value'='false', 'group'='RadioGroup1'), Plotter['PlotD'](plot_D, 'width'=200, 'height'=200) ] ], [ Button("Check Answer", Evaluate('function' = "checkMultChoice")), Button("Show Answer", Evaluate('function' = "showCorrectAns")), Button("Next Question", 'onclick'='NextQuestion2'), Button("Hints", 'onclick'='Hints'), Button("Close", 'onclick'='CloseWindSecDeriv') ], [ TextBox['responseArea']("Let's get started! Select the correct choice with the mouse and press \"Check Answer\". Once you have completed the current question, press \"Next Question\" to continue. ", 'editable'='false', 'background'='wheat', 'width'=45, 'height'=3, 'wrapped'='true', 'font' = Font("helvetica", 13) ) ] ]]] ), #################### END SECOND DERIVATIVE CHOICE FROM A GRAPH OF F WINDOW #################### ButtonGroup['RadioGroup1'](), ## BEGIN ACTIONS Action['StartUp']( Evaluate('function' = "sampleplot"), RunWindow('MAIN') ), Action['BeginQuestions']( RunWindow('MultChoicePlots'), Evaluate('function' = "genFuncAndPlots") ), Action['OnlyFunction']( RunWindow('JustFunc'), Evaluate('function' = "genFuncAndPlots") ), Action['SecondDerivative']( RunWindow('SecDeriv'), Evaluate('function' = "genFuncAndPlots2") ), Action['CloseWindMultChoicePlots']( Evaluate('function' = "clearResponseArea"), CloseWindow('MultChoicePlots') ), Action['CloseWindJustFunc']( Evaluate('function' = "clearResponseArea"), CloseWindow('JustFunc') ), Action['CloseWindSecDeriv']( Evaluate('function' = "clearResponseArea"), CloseWindow('SecDeriv') ), Action['Instructions']( RunWindow('InstrWindow') ), Action['Hints']( RunWindow('HintWindow') ), ## This action generates another question in the same window Action['NextQuestion']( Evaluate('function' = "genFuncAndPlots"), Evaluate('function' = "genNextReply") ), Action['NextQuestion2']( Evaluate('function' = "genFuncAndPlots2"), Evaluate('function' = "genNextReply") ) ## END ACTIONS ): Display(RecognizingDerivatives);