Payoff Matrix - Feedback Counter (Tidy up script)
David McFarlane
mcfarla9 at msu.edu
Tue Jan 11 17:02:33 UTC 2011
Caleb,
First the punchline: What I had in mind was that you might do this
with no If..Then or Select Case at all. Further comments in line below...
At 1/11/2011 02:46 AM Tuesday, you wrote:
>David,
>Thank you for your amazing advice. Please see below as I still have
>more questions. Also, if you keep reading past this, I will show you
>another solution I came to. I really really hope that this formatting
>thing has been fixed. I'm so sorry if it hasn't as this is a long
>reply and I spent a good 20 minutes trying to make the formatting to
>your specifications.
>
>Caleb
>
>On Monday, January 10, 2011 11:32:47 AM UTC-8, dkmcf wrote:
>Caleb,
>I commend you for taking an interest in improving your code, instead
>of simply settling for the first bit of code that gives the appearnce
>of working (and which almost always fails on close inspection). I
>hope my comments below don't seem too harsh, if so just consider that
>they come from a grouchy old man.
>
>Thank you. I appreciate constructive criticism.
>
>First, some style issues -- Your code appeared in my e-mail reader
>with indentations of *12* spaces! That is *way* too much
>indentation, it makes the code quickly run off the edge of the screen
>and makes it unreadable. Please learn to use the well-documented
>industry standard indentation of 4 spaces. Also, *please* resist the
>urge to double-space your code, that only reduces how much of your
>code will fit into view on my screen and does nothing to aid
>understanding. I had to take your code into my own text editor and
>edit it down to make it readable, do not expect me to do that again.
>
>This only happened because I had copied and pasted my post into Word
>in order to save a draft as I was typing so that in case I lost my
>post, I could retrieve it. This may have happened again. I'm sorry
>that Google Groups isn't so friendly with this.
This is why I edit my code in a professional text-editing program. I
like EditPadPro (http://www.editpadpro.com/ ), which you can get for
$50 or use the trial version for free, or you can find other programs
out there. Many of these, including EditPadPro even do syntax
highlighting for you, and with some tweaks it will properly highlight
syntax for VBA and E-Basic. I regular pull my E-Basic code into
EditPadPro for editing, documentation, and printout, then copy &
paste it back into E-Studio as needed, it is so much better than
editing in E-Studio.
(BTW, I am not just making up the "indent four spaces" convention --
lore has it that long ago a university study found that this was the
optimal indentation for program code, but I can't find the reference
offhand. In any case, you can search the web and find lots of
debates over these fine points.)
>Now, a few comments on the code itself. First, I wonder if you
>really need two different Slide objects? If they perform essentially
>the same function only with different content, then I would just use
>one Slide and change the content using attribute references. That
>could simplify the code right there.
>
>I took your advice and basically created script that changed the slide
>based upon the Test Type condition. This necessarily reduced the
>amount of code by half (and for your Array example, it decreases the
>array by one dimension).
Cool. Glad that suggestion did some good.
>Next, ignoring the MsgBox statements, it seems to me that all that
>changes in the various conditions is the number of points by which
>AccuracyDisplay changes. In that case, I would use a variable to
>hold the change amount, e.g., dAccuracyDisplay (i.e., "delta"
>AccuracyDisplay), so that the calculation becomes merely
>
>AccuracyDisplay = AccuracyDisplay + dAccuracyDisplay
>
>Yes, you might still need a mess of code to compute dAccuracyDisplay,
>but I like to separate the mess that computes dAccuracyDisplay from
>the operation that actually uses it, I find such separation aids my
>comprehension.
>
>I was not quite sure what you meant by this. From my understanding, I
>would declare a new variable "dAccuracyDisplay". dAccuracyDisplay
>would equal the change in point value between my Payoff conditions.
>For example, in Condition "A", let's say that for a Hit, the
>participant would receive 1 point and for a Correct rejection, the
>participant would receive 5 points. In Condition "B", Hit = 2 points;
>CR = 4 points. Thus, dAccuracyDisplay = 2-1; 5-4. The change in
>points would thus be 1 between A and B. This is my actual point
>system, by the way. Hit points increase by 1 each time and CR points
>decrease by 1 (from A to E). In this scenario, I'm not sure how to
>implement this variable because it seems unnecessary.
>
>Something like:
>************************************************************************************************************
>Dim dAccuracyDisplay as Integer ' Represents change in points between
>payoff conditions
> Select Case c.getattrib ("Payoff")
> Case "A"
> dAccuracyDisplay=AccuracyDisplay+1
> If c.getattrib("StatusOldNew")="Old" then
> If TestSlideOLDNEW.ACC = 1 then
> AccuracyDisplay=dAccuracyDisplay
>.
>.
>.
> Case "B"
> .
> .
> dAccuracyDisplay=AccuracyDisplay+2
>*******************************************************************************
>Doesn't doing this defeat the purpose of using a variable in the first
>place?
Depends on the purpose of using the variable. Here, for the purpose
of clarity (paving the way to further code improvement), I merely
meant to separate the "what" from the "how much", even if it meant
adding an extra line or two of code. Here the "what" means "sum
something into the AccuracyDisplay", and the "how much" means how
much to sum into the AccuracyDisplay. Your code combines those two
conceptually separate ideas, and sometime I find it helps to separate
these. It is the difference between
If in Michigan
go to Meijer and buy milk
Else if in Alabama
go to Winn Dixie and buy milk
Else if in Connecticut
go to A&P and buy milk
...
and
If in Michigan
go to Meijer
Else if in Alabama
go to Winn Dixie
Else if in Connecticut
go to A&P
...
Wherever you end up, now buy milk
So I guess it is still largely a matter of taste & style. And
admittedly, at another time I might have advised exactly the
opposite, but in this case, just making the mental leap of separating
"what" from "how much" then prepares us for the next steps...
>Next, once I have graduated to using a variable (instead of literal
>values) in the computation, I would consider using a
>multi-dimensional array to hold a table of the possible point values,
>and use numeric codes that will act as indices into the table for
>each condition. E.g., I might use 0 instead of "OldNew" for that
>TestType, 0 instead of "Old" for that StatusOldNew, etc. This
>admitedly adds a bit of indirection, but indirection that will could
>greatly simplify our computation. I would of course still need some
>code to set up the table at the start of the session, but with that
>done my computaton during the run might reduce to a single line, e.g.,
>
>AccuracyDisplay = AccuracyDisplay + PointTable( _
> CInt(c.getattrib ("TestType")), _
> CInt(MasterList.getattrib("StatusOldNew")), TestSlide.ACC )
>
>But I have probably missed something really obvious, so I hope
>someone else here will chime in and set me straight.
>
>Okay. This is where I get really confused. I understand that a
>multidimensional array can hold different values within each dimension
>(I did look over the VBA for Dummies Chapter on Arrays and Collections
>- Google Books). If I understand you correctly, you are saying that I
>should create such an array with three dimensions. The first
>dimension is my Test Type, the second is StatusOldNew, and the third
>is TestSlide.ACC.
That is pretty much correct, but just to express this accurately,
each element of the array would hold the point value for that
combination of TestType, StatusOldNew, and Accuracy. So,
PointSystem( 0, 0, 0 ) would hold the number of points for the case
of, say, TestType = OldNew, StatusOldNew = Old, and Accuracy = 0
(e.g., 0 points), and PointSystem( 0, 0, 1 ) would hold the number of
points for the case of, say, TestType = OldNew, StatusOldNew = Old,
and Accuracy = 1, etc. (e.g., 5 points), much as you show below.
> I should code each dimension with all of the
>possible values as integers. So for example, for TestType dimension:
>1 = "oldnew" and 0 = "PDP". This coding system can then be called
>upon later in the script (like you gave in your example). I get
>confused on how to set this up and implement it, but I think I
>understand it conceptually.
> For example (this is what I understand):
>**********************************************************************************
>dim PointSystem(1,1,1) as variant
>
>'do this for each of the other attributes (e.g. StatusOldNew)
>if c.getattrib("TestType") = "OldNew" then
> c.setattrib("TestType"), "0"
>Elseif c.getattrib("TestType") = "PDP" then
> c.setattrib("TestType"), "1"
>Else
> MsgBox "TestType attribute set error"
>End if
[For the sake of others who might stumble across this, I will just
correct the syntax of this code a little, should read
>if c.getattrib("TestType") = "OldNew" then
> c.setattrib "TestType", "0"
>Elseif c.getattrib("TestType") = "PDP" then
> c.setattrib "TestType", "1"
>Else
> MsgBox "TestType attribute set error"
>End if
]
>'I would set this to the actual and proper point values
>PointSystem(0,0 ,0 ) = 1
>PointSystem(0 ,1,0 ) = 2
>PointSystem( 0,0 ,1) = 3
>.
>.
>.
>PointSystem(1,1,1,) = 5
>
>'Then I would use your example and all I would need is this one line.
>AccuracyDisplay = AccuracyDisplay + PointSystem( _
> CInt(c.getattrib ("TestType")), _
> CInt(MasterList.getattrib("StatusOldNew")), TestSlide.ACC )
>*********************************************************************************
I think that is pretty close to what I had in mind, except that
instead of using the If..Then..ElseIf to reassign the TestType index
values, I would just go directly to whereever TestType gets defined
in the first place (your Startup Info, or some List or c.SetAttrib,
etc.) and put my index values there.
>The solution I came to:
>
>I added two attributes to my MasterList List object: Points_HR and
>Points_CR. For each trial, I input the proper point values. Then,
>for my payoff matrix, I simply referenced these point values.
>
>Script:
>**************************************************************************
>Select Case TestSlideOLDNEW.ACC
> Case "1"
> If c.getattrib("StatusOldNew") = "Old" then
>
>AccuracyDisplay=AccuracyDisplay+(c.getattrib("Points_HR"))'Hits
> Elseif c.getattrib("StatusOldNew") = "New" then
>
>AccuracyDisplay=AccuracyDisplay+(c.getattrib("Points_CR"))'Correct
>Rejection
> Else MsgBox "Accuracy display case 1 error"
> End if
> c.setattrib "Accuracy", AccuracyDisplay
> Set x =
>CSlideText(TestSlideOLDNEW.States(TestSlideOLDNEW.ActiveState).Objects("Text4"))
> If Not x Is Nothing Then
> x.Text = "Running Total: " & c.getattrib("Accuracy")
> End if
> Debug.Print "Debug Points_HR: " & c.getattrib("Accuracy")
> Case "0"
> AccuracyDisplay=AccuracyDisplay
> c.setattrib "Accuracy", AccuracyDisplay
> Set x =
>CSlideText(TestSlideOLDNEW.States(TestSlideOLDNEW.ActiveState).Objects("Text4"))
> If Not x Is Nothing Then
> x.Text = "Running Total: " & c.getattrib("Accuracy")
> End if
> Debug.Print "Debug Incorrect Accuracy: " &
> c.getattrib("Accuracy")
> Case Else
> MsgBox "TestSlideOLDNEW Accuracy Error"
>End Select
>***********************************************************************************
>Please also note that I am actually not deducting points anymore for
>incorrect answers so I do not need a counter for Misses and False
>Alarms.
>
>Although this is one solution I reached, I still want to understand
>what you meant by your suggestions. Once again, thank you!
I hope I made things a little clearer. Of course, I am assuming that
your point system remains static, if it becomes dynamic then you
could not use the array method. And sometimes you really do have to
settle for a cascade of If..Then and Select Case statements, and then
sometimes just applying some theorems from Boolean logic will help to
simplify this.
And for no particular reason, I will take this opportunity to close
with my previously unpublished "Heirarchy of Goals for Excellent Programs":
1) Works correctly (i.e., free of errors).
2) Works soon enough to be of use -- an ugly program that works now
is better than a beautiful program that works too late to be of use.
3) Efficiently uses time and resources.
4) Source code is readable, understandable, clear.
5) Source code is beautiful.
Personally, I find my quest to achieve goal #5 often interferes with
meeting the higher-priority goal #2, which is why I wrote this up as
a reminder to myself.
-- David McFarlane, Professional Faultfinder
--
You received this message because you are subscribed to the Google Groups "E-Prime" group.
To post to this group, send email to e-prime at googlegroups.com.
To unsubscribe from this group, send email to e-prime+unsubscribe at googlegroups.com.
For more options, visit this group at http://groups.google.com/group/e-prime?hl=en.
More information about the Eprime
mailing list