Announcement

Collapse
No announcement yet.

Parsing Milliseconds

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Parsing Milliseconds

    I'm tellin' ya Imma parse every damn thing you can parse. For anybody that cares, below is my method for parsing milliseconds to hh:mm:ss:ms

    Code:
    [color="MediumTurquoise"]public[/color] [color="RoyalBlue"]function[/color] millisecondConversion(_len:[color="PaleGreen"]uint[/color], cfg:[color="PaleGreen"]Array[/color] = [[color="DarkOrange"]1000[/color], [color="DarkOrange"]60[/color], [color="DarkOrange"]60[/color], [color="DarkOrange"]24[/color]]):[color="PaleGreen"]String[/color]
    {	
    	[color="RoyalBlue"]var[/color] time:[color="PaleGreen"]Array[/color] = [color="RoyalBlue"]new[/color] [color="PaleGreen"]Array[/color]();
    	[color="RoyalBlue"]var[/color] conversion:[color="PaleGreen"]uint[/color], temp:[color="PaleGreen"]uint[/color];
    
    	[color="RoyalBlue"]do[/color]
    	{
    		temp = (!temp) ? _len : temp/conversion;
    		conversion = cfg.shift();
    		time.unshift([color="#CC0000"]"0"[/color]+(temp % conversion));
    		temp -= [color="PaleGreen"]uint[/color](time[[color="DarkOrange"]0[/color]]);
    	} [color="RoyalBlue"]while[/color] (temp && cfg.length);
    
    	time.forEach([color="RoyalBlue"]function[/color](str:[color="PaleGreen"]String[/color], i:[color="PaleGreen"]uint[/color], arr:[color="PaleGreen"]Array[/color]) {
    		arr[i] = str.substr(-[color="DarkOrange"]2[/color]):
    	});
    
    	[color="RoyalBlue"]return[/color] time.join([color="#CC0000"]":"[/color]);
    }
    It's pretty simple but I'll run through it once anyway for people that don't understand what .shift()/unshift() is doing.

    1) we use a do/while loop because one condition of the while is that neither temp or cfg.length = 0. temp starts by equaling zero though. do/while loops work by running do once before checking while. This allows us to give temp a value. On the next iteration of the loop temp will already have a value so it gets converted to the next position of time (temp/conversion)

    2) shift() works to remove the first index of an array and return it's value. So after the first iteration cfg = [60,60,24] and the next cfg = [60,24]

    3) unshift() works to push something into the first array index. we start with milliseconds but on the next iteration seconds gets pushed into the beginning which pushes milliseconds up one.

    4)I convert what I'm unshifting into the array into a string preceded by a 0, this way if the result is < 9 I have a leading zero to display. It's entirely possible that the result of this will be 3 numbers, we fix that in the end.

    5) then I say ~ temp = all the time that's left ~ and the process starts over.

    6) I loop through every array index and tell it that it equals only the last 2 characters of itself, voila 3 digit possibility crushed

    7) finally, I use .join(":") to convert the entire array into a string with each index separated by ":"

    time[0] = "02"
    time[1] = "52"
    time[2] = "26"

    time.join(":");

    "02:52:26"

    There are 2 things that I believe make my method superior

    1) by setting the while condition to make sure that both remaining time and our cfg array have length, the time that is returned will never have 00 time. In other words, if there are no hours a position for it will never be created, in contrast if their are days they wont hold the loop in infinity due to the while never reaching 0

    2) this IS the algorithm for millisecond conversion. Which means all you ever have to do is add more conversion times to cfg to get more time

    ex: cfg = [1000, 60, 60, 24, 31]

    That would parse out even the days in the milliseconds leaving months as a hanging remainder. Of course to go this far is tricky cause the final index in the cfg array should be how many days are in the month that the milliseconds represent. You could of course just average it for a close enough result (365.3/12)

    .3 should more or less handle leap years. You can have up to 3 leap years in a decade so, this is in the pocket. round(365.3/12) might also be a good idea especially since everything is uint
    Last edited by MadGypsy; 04-30-2014, 11:36 AM.
    http://www.nextgenquake.com

  • #2
    ill have to post my ctf capture time code that breaks down to the millisecond
    so its quakeC useful
    www.quakeone.com/qrack | www.quakeone.com/cax| http://en.twitch.tv/sputnikutah

    Comment


    • #3
      Any real programmer could port this to QC pretty easy but, I'm still interested to see your code. IDK if QC supports (un)shift but if it doesn't that should be the only part of my code (other than syntax) that is different from QC. The forEach loop could easily be replaced with a regular for loop.

      hmmm, I seem to remember something about not being able to get an accurate length on an array in QC. That could be troublesome.
      Last edited by MadGypsy; 04-30-2014, 07:55 PM.
      http://www.nextgenquake.com

      Comment


      • #4
        Interesting.

        I remember reading somewhere that as the game time progressed in Quake, the global time float decreased in accuracy. Although I think it took a loooonng time to elapse before any noticeable differences occurred, to the point where it really doesn't matter. What's the skinny on that?
        'Replacement Player Models' Project

        Comment


        • #5
          #AltDevBlog Don&rsquo;t Store That in a Float
          some nice magnitude/precision tables in there.

          as a general rule, quake servers already internally use doubles for storing the current time. anything else resets to 0 on map changes, so as long as your server changes map at least once a day, it doesn't really present an issue.

          For QC (where timeval stores seconds and won't be read afterwards):
          days = floor(timeval/(60*60*24)); timeval -= 60*60*24*days;
          hours= floor(timeval/(60*60)); timeval -= 60*60*hours;
          minutes= floor(timeval/60); timeval -= 60*minutes;
          seconds= floor(timeval); timeval -= seconds;
          milliseconds = floor(timeval*1000);
          centerprint(self, sprintf("time is %gd %g:%g:%gs %gms\n", days, hours, minutes, seconds, milliseconds));

          obviously, sprintf is an extension (that 'prints' the formatted text into a string). Doing it with vanilla quake would require you to bprint or whatever the result of ftos in separate prints, to avoid issues with tempstring reuse/clobbering.
          Some Game Thing

          Comment


          • #6
            #AltDevBlog Don&rsquo;t Store That in a Float
            some nice magnitude/precision tables in there.

            as a general rule, quake servers already internally use doubles for storing the current time. anything else resets to 0 on map changes, so as long as your server changes map at least once a day, it doesn't really present an issue.
            That link just about summed it up, very informative. Thank you.
            'Replacement Player Models' Project

            Comment


            • #7
              I remember reading somewhere that as the game time progressed in Quake, the global time float decreased in accuracy.
              Dutch here's what i do to keep the server smooth.

              Code:
              float last_client_check;
              
              void() StartFrame =
              {
              	local entity anyonehome;
              
              	if (time > 21600)
              	{					
              		if (time > last_client_check)
              		{
              			anyonehome = find(world, classname, "player");
              			if (anyonehome == world)
              			{
              				localcmd (";restart;\n");
              			}
              		}
              		last_client_check = time + 600;
              	}
              	framecount  = framecount + 1;
              };
              Last edited by R00k; 05-02-2014, 08:45 AM.
              www.quakeone.com/qrack | www.quakeone.com/cax| http://en.twitch.tv/sputnikutah

              Comment


              • #8
                you can't do this in QC?

                ++framecount

                or

                framecount += 1
                http://www.nextgenquake.com

                Comment


                • #9
                  not vanilla qc, no.
                  Some Game Thing

                  Comment


                  • #10
                    Yeah after posting this I had a vague memory of me realizing it doesn't work, back when I was doing some project for summin or somebody. I haven't touched QC in almost a year (i think), so you can pretty much chalk it up that I don't know it anymore.

                    I mean, obviously, if I just picked it up again I could get right back where I was pretty quick but, as of right now there is no QC in my head. I'm fine with that. Right now my head is filled up with design patterns (particularly the command pattern).

                    I had this little epiphany last night that the way I was using switch/case statements was actually the entire roadmap for the design pattern of my scripts. I started breaking my cases down to classes, built an abstract interface a singleton and now Imma use the command pattern to invoke singletons of my return types. I think I also need to build a state machine to delegate types to the command pattern....IDK. I'm "going hard in the paints" but some of this stuff is not in my heat range yet. That's why I have books.

                    I've used design patterns before but what I am building right now is far more complex. I'll get it. I just need to make a lot of mistakes first.


                    @hard in paint - I know this means to be tatted up. Right now, it means to be excessive.
                    http://www.nextgenquake.com

                    Comment


                    • #11
                      @R00k: Nice, that's quick and clean.

                      @gypsy: The first time I read that I saw "I'm going hard in the pants." I had to do a double take on that lmao
                      'Replacement Player Models' Project

                      Comment


                      • #12
                        I had to do a double take from what you just wrote to make sure that I didn't put that as a typo. That would have been really embarrassing and totally possible cause this keyboard is garbage and that's about the level of my luck.
                        http://www.nextgenquake.com

                        Comment

                        Working...
                        X