6 Replies Latest reply on Jun 20, 2007 7:46 AM by mfallen

    Hourly Cookie

    mfallen
      I am working on trying to code a swf to play just once an hour using a Flash cookie
      The first time the swf plays needs to be automatic so I do not have a stop action on frame 1.
      See attached code which is on frame 1
      Frame 2 is labeled START

      The code I wrote is not working for me - do I have my action script written correctly?
      Are there any references for me to follow on how to write the code?
      Thanks.
        • 1. Re: Hourly Cookie
          Level 7
          mfallen,

          > CurrentTime = Now.getHours()+ ":" + Now.getMinutes();
          > HourUpTime = Now.getHours() + 1 + ":" + Now.getMinutes();

          With these two lines, you're creating string variables. Even though it
          may seem that these are numbers (more specifically, times), what you're
          actually getting are two strings, no different in principle from the strings
          "apples" and "oranges"; it happens that these mostly contain numerals, but
          it makes no difference. When you compare these later ...

          > if(Cookie.data.HourUpTime > CurrentTime)

          ... you're comparing the ASCII values of the characters that make up these
          strings. In your comparison, make sure you're comparing numbers to numbers.
          Fortunately, the SharedObject class will store whatever datatype you please,
          do you might, for example, store these ...

          Cookie.data.hourUpTime = Now.getHours() + 1;
          Cookie.data.minutesUpTime = Now.getMinutes();

          ... then compare them with the correlating current values.


          David Stiller
          Adobe Community Expert
          Dev blog, http://www.quip.net/blog/
          "Luck is the residue of good design."


          • 2. Re: Hourly Cookie
            mfallen Level 1
            Thanks David for explaining the problems with my code.
            I'm not sure if I understand fully how to distinguish when creating a variable, using data from the Date object , that I am using a number and not a string value. I'm guessing my use of ":" made it a string.
            I attempted to fix the code - see attached. ( I seperated the minutes cookie from the hours cookie - not sure if necessary or not ) But my script is still not working out.

            Also as I was thinking about this line of script:
            //Cookie1.data.hourUpTime = Now.getHours()+1;
            Adding one is not going to work right when I need it go from hour 23 to hour 0 since there is no hour 24 on up.
            Same problem I have with the minutes when I need the value to go from 59 minutes to 0 minutes, again there is no minute 60 on up.
            I tried incrementing ( which is the same thing as adding 1 -yes?) but got a script error
            //Cookie1.data.hourUpTime = Now.getHours()++;

            Maybe there is some type of math calulation that needs to be done? I'm a designer and veer to the creative side not the technical, so anything math related usually throws me. Hoping you can help me out some more.
            • 3. Re: Hourly Cookie
              Level 7
              mfallen,

              > Thanks David for explaining the problems with my code.

              Sure thing. :)

              > I'm not sure if I understand fully how to distinguish when
              > creating a variable, using data from the Date object , that I
              > am using a number and not a string value. I'm guessing my
              > use of ":" made it a string.

              Yes. Quoted items, even when concatenated with numbers, produce a
              string.

              > Also as I was thinking about this line of script:
              > //Cookie1.data.hourUpTime = Now.getHours()+1;

              Okay.

              > Adding one is not going to work right when I need it go from
              > hour 23 to hour 0 since there is no hour 24 on up.

              Heh, yup! This is the fun of programming (at least, to my thinking). I
              see dozens and dozens of posts every week that say, "Easy question," or some
              variation on that theme, but in actual practice, there is very little in
              programming that is truly easy. That isn't to say programming needs to be
              outrageously difficult -- sometimes yes, sometimes no -- but it's usually
              not a walk in the park.

              > Same problem I have with the minutes when I need the value to
              > go from 59 minutes to 0 minutes, again there is no minute 60 on up.

              That's right, but the good thing is, you can reason all this out in your
              head. It *is* right to increment hours and minutes in most cases, so you
              can check for the oddball circumstance and deal with that if adding one
              isn't going to work.

              > I tried incrementing ( which is the same thing as adding 1 -yes?) but
              > got a script error
              > //Cookie1.data.hourUpTime = Now.getHours()++;

              Well, the increment operator (++) adds one to the value its next to.
              The Date.getHours() method isn't a value itself; it *gets* you a value. You
              can get that value and pass it to something else, then increment *that* ...

              Cookie1.data.hourUpTime = Now.getHours();
              Cookie1.data.hourUpTime++;

              ... but you can't perform that operation on the method itself.

              > Maybe there is some type of math calulation that needs to
              > be done? I'm a designer and veer to the creative side not
              > the technical, so anything math related usually throws me.

              I hear you, but don't lose heart. The math in this scenario isn't
              especially difficult. If you're dealing with a 24-hour clock, then you
              already know that it only makes sense to add one in cases where the hours
              value is 23 or less (in other words, less than 24, or < 24). You can use an
              if() statement to check the value of something and act accordingly.

              var Now = new Date();
              var h = Now.getHours();
              if (h < 24) {
              h++;
              } else {
              h = 1;
              }

              In the above, an arbitrarily named variable, Now, is declared and set to
              an instance of the Date() class. This suddenly gives the Now variable
              access to all the properties, methods, and events available to the Date
              class (see the "Date class" entry of the ActionScript 2.0 Language Reference
              for details ... properties are characteristics the object has, methods are
              things it can do, and events are things it can react to; not all objects
              have all three categories).

              This is why Now.getHours() returns the "hours" value of the current
              time. In the second line, an arbitrarily named variable, h, is set to
              whatever value that method returns. Let's say it happens to be 20. An if()
              statement checks that value ... if h is less than 24, increment it by 1.
              That would happen in this case. If not (if it was already 24), set it to 1.

              Obviously, at this point it gets more complex, because now you have to
              consider the minutes, and if you check 1 against 24, it will show up as
              smaller. It turns out that the Date class handles some of this math for
              you. If you use optional parameters in the Date constructor, you can create
              an instance at an artificial time in the future or the past. The "Date
              class" entry will tell you all the details, but you can, for example, do
              this:

              var now:Date = new Date();
              var then:Date = new Date(
              now.getFullYear(),
              now.getMonth(),
              now.getDate(),
              now.getHours() + 1,
              now.getMinutes()
              );
              trace(now);
              trace(then);

              ... and see two fully qualified date/times, one an hour ahead of the other.
              It handles the rollover at midnight for you. In fact, you can then compare
              the two with comparison operators ...

              trace(now > then);
              trace(now < then);

              So I think this will give you a bit more to chew on. :)

              What are those :Date parts? There, I'm strongly typing my variables.
              It just means the "now" and "then" variables are being earmarked as Date
              variables (as opposed to numbers, strings, or anything else). It's not a
              strictly necessary step, but a good habit to get into.

              > Cookie1 = sharedObject.getLocal("hourUpTime");
              > Cookie2 = sharedObject.getLocal("minutesUpTime");

              At this point, you needed create two shared objects. Every SharedObject
              instance has a data property, and you only need one. Add as many properties
              of your own to the existing data property ...

              var Cookie1:SharedObject = sharedObject.getLocal("hourUpTime");
              Cookie1.data.hourUpTime = then.getHours();
              Cookie1.data.minutesUpTime = then.getMinutes();

              ... or, shoot, just save the whole Date instance, like this:

              Cookie1.data.hourUpTime = then;

              ... because when you retrieve that value later, it still *is* a Date
              instance. You can use the aforementioned properties, methods, and events
              (as they exist) on Cookie1.data.hourUpTime ...

              trace(Cookie1.data.hourUpTime.getHours());

              The crux of the matter is this, though: you want to know if the user
              has been away for longer than an hour. There really isn't even a need to
              artificially pump up a Date instance by one hour. When the user arrives --
              that is, when the SWF loads -- check to see if there's a cookie (a shared
              object). If there is, check its data property for your custom value. Let's
              call it timeLastVisit. If such a custom property exists (because you set it
              last time), compare it against a current Date instance and calculate the
              difference.

              var Cookie1:SharedObject = sharedObject.getLocal("hourUpTime");
              if (Cookie1.data.timeLastVisit) {
              var now:Date = new Date();
              var difference:Number = now - Cookie1.data.timeLastVisit;
              // more in a sec
              } else {
              Cookie1.data.timeLastVisit = new Date();
              Cookie1.flush();
              }

              See what's going on here? First, we reference the existing shared
              object, or create one if it doesn't exist. Nest, we check of our custom
              timeLastVisit property has a value. If it does, create a new date object,
              and subtract the existing one (timeListVisit) with the current one. Then we
              have that "more in a sec" comment, so ... more in a sec.

              If not -- that is, if the timeListVisit property has no value -- it
              means this shared object hasn't yet been set, so set it. Set it to an
              instance of the Date class, which will save the current time for the user's
              next visit.

              Now, back to our math. Using the subtraction (minus) operator, we've
              simply subtracted the old saved time from the current time. This results in
              a numeric value in milliseconds. That value gets stored in the arbitrarily
              named variable, difference.

              At this point, you can perform a tad more math. Milliseconds are
              one-thousandths of a second, so divide the number by 1,000. That gets you
              how many seconds have passed since the last visit. If you want minutes,
              divide that number by 60. If you want hours, divide that number further by
              60:

              difference = difference / 1000 / 60 / 60;

              Now you have how many hours have passed since last time. If that number
              is greater than 1, the visitor has been away for longer than an hour. If
              that number is less than 1, the user has been back pretty quickly.

              So ... see how far that gets you. I hope it's helpful. :) This was
              something of a goose chase answer, but I wanted to see how an answer can be
              honed in on.


              David Stiller
              Adobe Community Expert
              Dev blog, http://www.quip.net/blog/
              "Luck is the residue of good design."


              • 4. Re: Hourly Cookie
                mfallen Level 1
                Thanks David for going so in-depth about the Date class and my script, and action script advise in general.
                Very impressed by your knowledge - hopefully I can get to that level someday. I have a ways to go, for sure.
                Based on your help/script, I made additions/changes - see script attached.
                When I do traces to check my variables, all looks good.

                The problem is that the movie doesn't go to the frame labeled "END" when this part of script executes this if statement within the existing if statement-

                if (new_difference<1) {
                gotoAndPlay("END");
                }

                I tried some variations to this part of the script but to no avail.
                Also I think that I need some type of "reset/clear the cookie" script so that once an hour is past and the movie replays again then a new cookie is made to time for an hour, once again.
                Was thinking to add it to this as follows:
                if (new_difference<1) {
                gotoAndPlay("END");
                }else{
                gotoAndPlay("START");
                Cookie1.clear();
                }
                But not sure if this makes sense or will work.

                I left off the :Date parts because my boss wants to be able to use this Flash movie in older Flash players, but good to know about how variables should be written and makes lodgical sense. I'll use for future projects that can use ActionScript 2.0/ latest Player.

                I'm hoping you can help me out once again with this. Thanks much.
                • 5. Re: Hourly Cookie
                  Level 7
                  mfallen,

                  > Thanks David for going so in-depth about the Date class and
                  > my script, and action script advise in general.

                  Glad to help. :)

                  > Very impressed by your knowledge - hopefully I can get to
                  > that level someday.

                  I have no doubt you can; it's mainly a matter of experience and
                  interest, I think. That's partly why I try to encourage people to stick
                  with it ... we're all newbs at some point or another.

                  > The problem is that the movie doesn't go to the frame labeled "END" when
                  > this
                  > part of script executes this if statement within the existing if
                  > statement-
                  >
                  > if (new_difference<1) {
                  > gotoAndPlay("END");

                  Hmm. Well, I looked at your final code at the end, and I here's my take
                  on a few tweaks:

                  var Cookie1 = SharedObject.getLocal("hourUpTime");
                  if (Cookie1.data.timeLastVisit) {
                  var now = new Date();
                  var difference = now - Cookie1.data.timeLastVisit;
                  var new_difference = difference / 1000 / 60 / 60;
                  if (new_difference < 1) {
                  gotoAndPlay("END");
                  trace("less than an hour");
                  } else {
                  gotoAndPlay("START");
                  trace("an hour or more");
                  Cookie1.clear();
                  }
                  } else {
                  Cookie1.data.timeLastVisit = new Date();
                  Cookie1.flush();
                  }

                  When I test this, then change my clock manually to an hour (or more)
                  ahead, then test again, then change the clock back, everything works as
                  expected.

                  > I left off the :Date parts because my boss wants to be able to
                  > use this Flash movie in older Flash players, but good to know
                  > about how variables should be written and makes lodgical sense.

                  In ActionScript 3.0, the strong typing can actually improve performance,
                  but in AS2, you can least get helpful code hinting and compile-time
                  warnings -- but I understand the desire, too, to publish for older Flash
                  Players.

                  Just make sure to consult the Language Reference fairly regularly ...
                  the SharedObject class isn't supported before Flash Player 6, so you
                  couldn't use the above in Flash Player 5 anyway. And if you're using 6, you
                  can set your publish settings to ActionScript 2.0. Just something to think
                  about. :) The SharedObject.clear() method only works in Flash Player 7, so
                  if you wanted to do the equivalent in 6, you could set the value of
                  timeLastVisit to null instead.


                  David Stiller
                  Adobe Community Expert
                  Dev blog, http://www.quip.net/blog/
                  "Luck is the residue of good design."


                  • 6. Re: Hourly Cookie
                    mfallen Level 1
                    Hi David,
                    The revised code works!!!!! Excellent!
                    I changed the settings to Flash Player 7 and it worked fine after that - maybe it reset something.
                    You're help was invaluable. You & Adobe rock.

                    As a side question - not related to the topic. What is the best way to learn how to correctly determine the way to write actionscript - seems like my inital thought process for this project was flawed or went the wrong direction.
                    Is there an online article, documentation or class I could take to help me with this?
                    I'm sure as I work with Flash and ActionScript and get more experienced I will get better at it but I'm always looking for a more expeditious way.

                    Thanks again.