# Cube Timer



## jms_gears1 (Jul 14, 2009)

I am programming a cube timer in c#.net and was wondering how you average times. 

so as the timer ticks i format the time span into a string and then that string to a label:

imeSpan ts = stopWatch.Elapsed;
lblTime.Text = string.Format("{0:00}:{1:00}.{2:00}", ts.Minutes, ts.Seconds, ts.Milliseconds / 10);

after that i write it to a file and then its uploaded from that file and put on one of the seven labels that i have for times.

what i want to do is take the info from the labels and avg them however i dont know how to do that.. 

any suggestions would be fine and as i know i have not been very clear ask me any questions that you would find helpful thanks in advance


----------



## joey (Jul 14, 2009)

Why do you write it to a file first?


----------



## qqwref (Jul 14, 2009)

I'd suggest making a variable to store each time as a single integer, for instance:
double thisTime = 60 * ts.Minutes + ts.Seconds + .001 * ts.Milliseconds
Then you can keep those times in an array, and from there computing the average is easy because you're just finding the average of a bunch of floating point numbers.


----------



## jms_gears1 (Jul 14, 2009)

joey said:


> Why do you write it to a file first?





qqwref said:


> I'd suggest making a variable to store each time as a single integer, for instance:
> double thisTime = 60 * ts.Minutes + ts.Seconds + .001 * ts.Milliseconds
> Then you can keep those times in an array, and from there computing the average is easy because you're just finding the average of a bunch of floating point numbers.



i dont necessarily write it to a file first what i meant is that i want it to be able to use those times as well when the program is loaded again. making it so that i cant store the variable like qqwref said.. 
the only thing i can come up with is making a new file and storing the times in float format there but then that would mean making double the amounts of files and then things get really tedious


----------



## qqwref (Jul 14, 2009)

Just keep a database file in comma separated value format. You could put the scramble (as a string) and then the time on each line, for instance. (Can't you just use this file, though? What are you using the other one for?)


----------



## jms_gears1 (Jul 14, 2009)

hmmm that might work how i was doing the time storage was using a txt file and saving the times on a new line i figured that way would be easiest. gah i know what i shouldve done... i should save the times as a float instead of a formated string then i can format them from that to put in the label as its loaded


----------



## JBCM627 (Jul 14, 2009)

If you don't care about whether or not the user can easily read the times in the text file, you can just store a serialized array of numbers...


----------



## jms_gears1 (Jul 14, 2009)

serialized array of numbers? sorry im newish to programming


----------



## JBCM627 (Jul 14, 2009)

http://www.switchonthecode.com/tutorials/csharp-tutorial-serialize-objects-to-a-file
At a glance, seems like an ok tutorial

Or maybe:
http://www.devhood.com/Tutorials/tutorial_details.aspx?tutorial_id=236

Just google "C# serialize".


----------



## jms_gears1 (Jul 14, 2009)

hmm serializing seems kinda complicated well more so then what i have right now what are the advantages?


----------



## jms_gears1 (Jul 14, 2009)

k so for anyone else that needs this kind of help heres my solution

i store in the files qqwref's formula modified a bit:
double thisTime = 60 * ts.Minutes + ts.Seconds + .01 * (ts.Milliseconds/10)

then i made a function that formats them to a string
public string format(double i)
{
int min = 0;
string istr="";
string minstr="";
while (i >= 60)
{
i -= 60;
min++;
}
if (min <= 10)
{
minstr = "0" + Convert.ToString(min);
}
else
{
minstr = Convert.ToString(min);
}
if (i <= 10)
{
istr = "0" + Convert.ToString(i);
}
else
{
istr = Convert.ToString(i);
}
return (minstr + ":" + istr);
}
as i load the info from the file i added it to a list (1D array)

i made an average function that takes the average of any non zero values

double average(double[] t)
{
double avg=0;
int div = t.Length;
for (int i = 0; i < t.Length; i++)
{
if (t_ != 0)
{
avg += t;
}
else
{
div--;
}
}
if (div == 0)
{
return div;
}
avg /= div;
return avg;
}

the list of times gets put into there then i format it and truncate it to give me an average..

hope someone finds this useful_


----------



## qqwref (Jul 15, 2009)

jms_gears1 said:


> while (i >= 60)
> {
> i -= 60;
> min++;
> }


or you could just do
min = i % 60;
i = i - 60 * min;


jms_gears1 said:


> if (min <= 10)
> {
> minstr = "0" + Convert.ToString(min);
> }


Trust me, you don't wanna do this. Times don't look good if they have any 0's in front of them. At least for cubers, most people would much rather see 20.39 than 0:20.39. If it's under a minute don't even add the minutes, and don't add a 0 in front of the seconds unless the time is over a minute (i.e. do NOT put 0:07.08). You might need to add an extra zero, too, if the time is something like 1:00.28.


jms_gears1 said:


> minstr = "0" + Convert.ToString(min);


Doesn't C# convert integers to strings automatically? It would be a pretty terrible language if it didn't.


jms_gears1 said:


> i made an average function that takes the average of any non zero values


I wouldn't just go removing the zero values. I assume you're removing zeroes because they represent DNFs; it would be better to use a specific negative number for DNF (-1, say), and then deal with those separately. (The average should be DNF if there is more than one DNF, for instance.) That way, the user can still enter in a 0 time if they want. Most people using a timer won't expect that if they put in a 0 the time won't be counted.

Oh yeah, and if you're going to calculate an *average*, you have to remove the best and worst result and just take the mean of the remaining ones. The function you gave calculates a mean (going by cubing terminology).



jms_gears1 said:


> double avg=0;
> [...]avg /= div;


This is bad programming practice. Name the variable "sum" (or something similar) instead and then just return sum / div.


----------



## masterofthebass (Jul 15, 2009)

one word:

YAML! 

for data storage I just use a pre-built yaml module to store everything. It works great in python using yaml.dump() and yaml.load() and I get everything I need . I would look into using some pre-built storage module to store everything.


----------



## jms_gears1 (Jul 15, 2009)

qqwref said:


> jms_gears1 said:
> 
> 
> > while (i >= 60)
> ...


hmm with your way it doesnt take any for loops i just did it my way so i could see what i was trying to do at a glance.


qqwref said:


> jms_gears1 said:
> 
> 
> > if (min <= 10)
> ...


mk ill change that seems reasonable there was a reason i put it like that but i dont remember... i guess ill find out


qqwref said:


> jms_gears1 said:
> 
> 
> > minstr = "0" + Convert.ToString(min);
> ...


it doesnt explicitly typecast. and its not a terrible language.


qqwref said:


> [
> 
> 
> jms_gears1 said:
> ...


No how i ended up having to save it and everything when it loads it puts zero times so 00:00 in all the places that there were no times so i didnt average them.


qqwref said:


> Oh yeah, and if you're going to calculate an *average*, you have to remove the best and worst result and just take the mean of the remaining ones. The function you gave calculates a mean (going by cubing terminology).


ive done that already but average is all the times i did an average of 7 and took the two times out (seven are the number of times kept on screen the last seven solves)


qqwref said:


> jms_gears1 said:
> 
> 
> > double avg=0;
> ...


i didnt see anything wrong with it but i guess that makes sense because its not the average until it divided


----------



## Johannes91 (Jul 15, 2009)

qqwref said:


> Doesn't C# convert integers to strings automatically? It would be a pretty terrible language if it didn't.


Why is being explicit a bad thing?



qqwref said:


> I wouldn't just go removing the zero values. I assume you're removing zeroes because they represent DNFs; it would be better to use a specific negative number for DNF (-1, say)


IMHO, it would be even better to use non-number values for DNF, DNS, etc. because they obviously aren't numbers.


----------

