PDA

View Full Version : anyone want to help me with a program?




twoodcc
Apr 11, 2007, 11:57 AM
ok, i want to make a mac program that keeps track of your computer's uptime, keep a record uptime, and maybe average uptime and more statistics if possible.

i have taken a few programming courses, but only matlab, visual basic, and C#, so they don't really help me with this one.

i have gone through a few mac tutorials, but they weren't like the program i want.

i know there is a widget called "show-off" that basically does this, but i have computers on panther, and i just want to make my own program

if anyone could help me get started, i'd really appreciate it. i don't really know how to start this

thanks in advance



Eraserhead
Apr 11, 2007, 12:02 PM
Have you had a look at one of the Cocoa books like the hiligass one?

twoodcc
Apr 11, 2007, 12:18 PM
Have you had a look at one of the Cocoa books like the hiligass one?

i don't think i have. do you have a link to it? all i've done with Cocoa is a few tutorials

Eraserhead
Apr 11, 2007, 01:16 PM
i don't think i have. do you have a link to it? all i've done with Cocoa is a few tutorials

Sure

Amazon (US) (http://www.amazon.com/Cocoa-Programming-Mac-OS-2nd/dp/0321213149/ref=pd_bbs_1/103-4182780-7314252?ie=UTF8&s=books&qid=1176315336&sr=8-1)

MongoTheGeek
Apr 11, 2007, 01:19 PM
ok, i want to make a mac program that keeps track of your computer's uptime, keep a record uptime, and maybe average uptime and more statistics if possible.

The easiest way to do it is with an AppleScriptStudio application.

inside of the idle handler say

set timewords to every word of (do shell script "uptime")
set timewords to every word of (do shell script "uptime")
set uptime to (item 4 of timewords) * days + (item 6 of timewords) * hours + (item 7 of timewords) * minutes

Eraserhead
Apr 11, 2007, 01:22 PM
The easiest way to do it is with an AppleScriptStudio application.

inside of the idle handler say

set timewords to every word of (do shell script "uptime")
set timewords to every word of (do shell script "uptime")
set uptime to (item 4 of timewords) * days + (item 6 of timewords) * hours + (item 7 of timewords) * minutes

A simple obj-C application will use less CPU resource than applescript, but assuming you have a modern Mac (fast G4/G5/Intel) you'll be OK, from experience an applescript application (on an iMac G5) uses about 0.3% CPU while sleeping.

twoodcc
Apr 11, 2007, 02:06 PM
Sure

Amazon (US) (http://www.amazon.com/Cocoa-Programming-Mac-OS-2nd/dp/0321213149/ref=pd_bbs_1/103-4182780-7314252?ie=UTF8&s=books&qid=1176315336&sr=8-1)

thanks for the link. have you used this book before yourself?

The easiest way to do it is with an AppleScriptStudio application.

inside of the idle handler say

set timewords to every word of (do shell script "uptime")
set timewords to every word of (do shell script "uptime")
set uptime to (item 4 of timewords) * days + (item 6 of timewords) * hours + (item 7 of timewords) * minutes

thanks. so if i copy and paste this into an AppleScriptStudio application, it will work? or do i need to change it some?

A simple obj-C application will use less CPU resource than applescript, but assuming you have a modern Mac (fast G4/G5/Intel) you'll be OK, from experience an applescript application (on an iMac G5) uses about 0.3% CPU while sleeping.

well i would be running this on a G4 mac mini.....so any help in speed would be nice

Eraserhead
Apr 11, 2007, 02:09 PM
thanks for the link. have you used this book before yourself?

Yep, it's excellent.

twoodcc
Apr 11, 2007, 02:15 PM
Yep, it's excellent.

thanks, i'll check it out

MongoTheGeek
Apr 11, 2007, 02:53 PM
thanks. so if i copy and paste this into an AppleScriptStudio application, it will work? or do i need to change it some?


The code I gave will generate the uptime as seconds but won't do anything useful with it. You will need code to store it some place and calculate useful information with it.

A straight cocoa solution would be much more efficient but not easier.

twoodcc
Apr 11, 2007, 02:57 PM
The code I gave will generate the uptime as seconds but won't do anything useful with it. You will need code to store it some place and calculate useful information with it.

A straight cocoa solution would be much more efficient but not easier.

ok thanks. i'll see what i can come up with

twoodcc
Apr 11, 2007, 06:16 PM
The code I gave will generate the uptime as seconds but won't do anything useful with it. You will need code to store it some place and calculate useful information with it.

A straight cocoa solution would be much more efficient but not easier.

well i got it working. but it doesn't do anything yet. what do you think would be the best way to display the uptime on the screen?

MongoTheGeek
Apr 12, 2007, 01:31 PM
well i got it working. but it doesn't do anything yet. what do you think would be the best way to display the uptime on the screen?

Have a text field that you update.

twoodcc
Apr 12, 2007, 04:19 PM
Have a text field that you update.

thanks. i'm not really sure how to do that, but i'll give it a try

twoodcc
Jun 17, 2007, 03:05 PM
Have a text field that you update.

well i'm gonna be honest here, i've tried to do this, but i'm not really sure how to go about it. could you help me out with it?


thanks in advance

MongoTheGeek
Jun 17, 2007, 07:38 PM
well i'm gonna be honest here, i've tried to do this, but i'm not really sure how to go about it. could you help me out with it?


thanks in advance

I was away at WWDC and not watching the forums.

Did you end up with the Cocoa solution or the AS solution.

For AS
set contents of text field "Foo" to timewords

The text field has to be named "Foo" in Applescript in Interface Builder for this to work.



For Cocoa
[myTextField setStringValue:timeWords];

The text field has to be connected to an IBOutlet on the class you are working on.

twoodcc
Jun 17, 2007, 09:01 PM
I was away at WWDC and not watching the forums.

Did you end up with the Cocoa solution or the AS solution.

For AS
set contents of text field "Foo" to timewords

The text field has to be named "Foo" in Applescript in Interface Builder for this to work.



For Cocoa
[myTextField setStringValue:timeWords];

The text field has to be connected to an IBOutlet on the class you are working on.

thanks. i'm trying the AS version.

i did what you said, but nothing is showing up in the text box. i set it to uneditable. is that a problem? i don't want to be able to type in the box

Eraserhead
Jun 18, 2007, 07:57 AM
thanks. i'm trying the AS version.

i did what you said, but nothing is showing up in the text box. i set it to uneditable. is that a problem? i don't want to be able to type in the box

Uneditable is fine, you have to make sure the box is being pointed too correctly from the code.

twoodcc
Jun 18, 2007, 03:01 PM
Uneditable is fine, you have to make sure the box is being pointed too correctly from the code.

i guess i'm having trouble with that.

twoodcc
Jun 19, 2007, 06:04 PM
well i need some help here. first, i tried to use the code that was given to me in this thread in applescript studio, but i couldn't figure out how to put it in a textbox.

the last 2 nights i've been working with a few other members on a cocoa application that does the same thing, and none of us can figure out how to get the uptime. we tried this, but it doesn't work right:

double newVar = currentTimeAsDuration;

NSString *Astring = [NSString stringWithFormat:@"%f", newVar];

double value = [Astring intValue];

double inSeconds = value * .0001; //mili-sec
double inMinutes = inSeconds / 60; //sec-min
double inHours = inMinutes / 60; //min-hour

NSString *string = [NSString stringWithFormat:@"%f", inHours];

NSString *hoursExtract = [string substringToIndex:1];
NSString *minutesExtract = [string substringWithRange:NSMakeRange(2,2)];
NSString *secondsExtract = [string substringWithRange:NSMakeRange(4,2)];

NSString *finalString = [NSString stringWithFormat:@"%@h %@m %@s", hoursExtract, minutesExtract, secondsExtract];


[textField setStringValue:finalString]

so if anyone can help, that would be great.

thanks

twoodcc
Jun 19, 2007, 10:19 PM
well me and rev316 got it to display your uptime correctly.

now the next step is to keep a record of your best (longest) uptime.

can anyone help us out with that? storing data is a little over my head right now

thanks

Nutter
Jun 20, 2007, 03:36 AM
Could you post your whole Xcode project here? I can't really see from the snippet above what is going on...

Also, do you only want to store the longest uptime, or do you want more detailed stats?

twoodcc
Jun 20, 2007, 07:21 AM
Could you post your whole Xcode project here? I can't really see from the snippet above what is going on...

Also, do you only want to store the longest uptime, or do you want more detailed stats?

here is the updated code:

#import "uptimeApp.h"

@implementation uptimeApp


- (IBAction)createTime:(id)sender
{
AbsoluteTime currTime;
currTime = UpTime();

float currentUptime = (float)AbsoluteToDuration(currTime);
if (0.0f > currentUptime) // negative means microseconds
currentUptime /= -1000000.0f;
else // positive means milliseconds
currentUptime /= 1000.0f;

int days = 0;

float currentUptimeinMinutes = currentUptime / 60;

int hours = (int)currentUptimeinMinutes / 60; //get hours
int diffHinMin = hours * 60; //find the minutes of the hours
int minutes = currentUptimeinMinutes - diffHinMin; //difference to get minutes

if (minutes > 59)
{
hours += 1;
minutes = 0;
}

if (hours > 23)
{
days = hours / 24;
hours = hours % 24;
}

NSString *string = [NSString stringWithFormat:@"%dd %dh %dm", days, hours, minutes];
[textField setStringValue:string]; // display it in our outlet
}
@end


thanks. well, eventually we would like to hold more stats if possible, like your last 10 uptimes or something.

MongoTheGeek
Jun 20, 2007, 09:43 AM
Take a look at NSUserDefaults. Very easy to use.


defaults = [NSUserDefaults standardUserDefaults];
if ([defaults floatForKey:@"MaxUptime"]< currentUptime)
[defaults setFloat: currentUptime ForKey:@"MaxUptime"];

Nutter
Jun 20, 2007, 10:48 AM
Here's my solution. I've changed the name of your class to AppController, because it makes more sense (and starts with a capital letter!).

AppController.h:


#import <Cocoa/Cocoa.h>


@interface AppController : NSObject
{
IBOutlet NSTextField *textField;
}

- (IBAction)createTime:(id)sender;

- (NSNumber *)longestRecordedUpTime;
- (NSArray *)lastTenRecordedUpTimes;
@end


AppController.m:

#import "AppController.h"

NSString *MBLongestRecordedUpTime = @"MBLongestRecordedUpTime";
NSString *MBLastTenRecordedUpTimes = @"MBLastTenRecordedUpTimes";


@interface NSNumber (MBUpTimeAdditions)

+ (id)currentUpTime;
- (NSString *)formattedUpTimeString;
@end


@implementation AppController

- (IBAction)createTime:(id)sender;
{
NSNumber *currentUpTime = [NSNumber currentUpTime];
[textField setStringValue:[currentUpTime formattedUpTimeString]];

if ([[NSUserDefaults standardUserDefaults] objectForKey:MBLongestRecordedUpTime] == nil || [currentUpTime compare:[[NSUserDefaults standardUserDefaults] objectForKey:MBLongestRecordedUpTime]] == NSOrderedDescending)
[[NSUserDefaults standardUserDefaults] setObject:currentUpTime forKey:MBLongestRecordedUpTime];

NSMutableArray *lastTenUpTimes = [[[NSUserDefaults standardUserDefaults] objectForKey:MBLastTenRecordedUpTimes] mutableCopy];
if (lastTenUpTimes == nil)
lastTenUpTimes = [[NSMutableArray alloc] initWithCapacity:10];
[lastTenUpTimes insertObject:currentUpTime atIndex:0];
if ([lastTenUpTimes count] > 10)
[lastTenUpTimes removeLastObject];
[[NSUserDefaults standardUserDefaults] setObject:lastTenUpTimes forKey:MBLastTenRecordedUpTimes];
[lastTenUpTimes release];
}

- (NSNumber *)longestRecordedUpTime;
{
return [[NSUserDefaults standardUserDefaults] objectForKey:MBLongestRecordedUpTime];
}

- (NSArray *)lastTenRecordedUpTimes;
{
return [[NSUserDefaults standardUserDefaults] objectForKey:MBLastTenRecordedUpTimes];
}

@end


@implementation NSNumber (MBUpTimeAdditions)

+ (id)currentUpTime;
{
return [self numberWithUnsignedLongLong:UnsignedWideToUInt64(AbsoluteToNanoseconds(UpTime())) / 1000000000]; // UpTime in seconds
}

- (NSString *)formattedUpTimeString;
{
unsigned days = [self unsignedLongLongValue] / (60 * 60 * 24);
unsigned hours = ([self unsignedLongLongValue] / (60 * 60)) % 24;
unsigned minutes = ([self unsignedLongLongValue] / 60) % 60;

return [NSString stringWithFormat:@"%ud %uh %um", days, hours, minutes];
}

@end

twoodcc
Jun 20, 2007, 02:35 PM
Here's my solution. I've changed the name of your class to AppController, because it makes more sense (and starts with a capital letter!).

AppController.h:


#import <Cocoa/Cocoa.h>


@interface AppController : NSObject
{
IBOutlet NSTextField *textField;
}

- (IBAction)createTime:(id)sender;

- (NSNumber *)longestRecordedUpTime;
- (NSArray *)lastTenRecordedUpTimes;
@end


AppController.m:

#import "AppController.h"

NSString *MBLongestRecordedUpTime = @"MBLongestRecordedUpTime";
NSString *MBLastTenRecordedUpTimes = @"MBLastTenRecordedUpTimes";


@interface NSNumber (MBUpTimeAdditions)

+ (id)currentUpTime;
- (NSString *)formattedUpTimeString;
@end


@implementation AppController

- (IBAction)createTime:(id)sender;
{
NSNumber *currentUpTime = [NSNumber currentUpTime];
[textField setStringValue:[currentUpTime formattedUpTimeString]];

if ([[NSUserDefaults standardUserDefaults] objectForKey:MBLongestRecordedUpTime] == nil || [currentUpTime compare:[[NSUserDefaults standardUserDefaults] objectForKey:MBLongestRecordedUpTime]] == NSOrderedDescending)
[[NSUserDefaults standardUserDefaults] setObject:currentUpTime forKey:MBLongestRecordedUpTime];

NSMutableArray *lastTenUpTimes = [[[NSUserDefaults standardUserDefaults] objectForKey:MBLastTenRecordedUpTimes] mutableCopy];
if (lastTenUpTimes == nil)
lastTenUpTimes = [[NSMutableArray alloc] initWithCapacity:10];
[lastTenUpTimes insertObject:currentUpTime atIndex:0];
if ([lastTenUpTimes count] > 10)
[lastTenUpTimes removeLastObject];
[[NSUserDefaults standardUserDefaults] setObject:lastTenUpTimes forKey:MBLastTenRecordedUpTimes];
[lastTenUpTimes release];
}

- (NSNumber *)longestRecordedUpTime;
{
return [[NSUserDefaults standardUserDefaults] objectForKey:MBLongestRecordedUpTime];
}

- (NSArray *)lastTenRecordedUpTimes;
{
return [[NSUserDefaults standardUserDefaults] objectForKey:MBLastTenRecordedUpTimes];
}

@end


@implementation NSNumber (MBUpTimeAdditions)

+ (id)currentUpTime;
{
return [self numberWithUnsignedLongLong:UnsignedWideToUInt64(AbsoluteToNanoseconds(UpTime())) / 1000000000]; // UpTime in seconds
}

- (NSString *)formattedUpTimeString;
{
unsigned days = [self unsignedLongLongValue] / (60 * 60 * 24);
unsigned hours = ([self unsignedLongLongValue] / (60 * 60)) % 24;
unsigned minutes = ([self unsignedLongLongValue] / 60) % 60;

return [NSString stringWithFormat:@"%ud %uh %um", days, hours, minutes];
}

@end


thanks. i ran your code, and it compiled, but i don't think it works with our current user interface.

did you make your own user interface?

Nutter
Jun 21, 2007, 05:45 AM
Er, yes, I had to as you didn't post your whole project.

To get that code working with your existing interface, you would have to drag the header file into Interface Builder for parsing, create an instance of AppController in the nib, and make the outlet and target/action connections between the instance of AppController and your text field.

In any case, I've made some adjustments - the full project is attached.

twoodcc
Jun 21, 2007, 08:33 PM
Er, yes, I had to as you didn't post your whole project.

To get that code working with your existing interface, you would have to drag the header file into Interface Builder for parsing, create an instance of AppController in the nib, and make the outlet and target/action connections between the instance of AppController and your text field.

In any case, I've made some adjustments - the full project is attached.

thanks, that really helps. i'll try yours, and i'll try to use that code with my existing interface to see if i can get it to work.

thanks

twoodcc
Jun 21, 2007, 08:41 PM
well, your program works great. but when you click "get uptime" is puts a new uptime in the last 10 uptimes.

is there any way to keep track of your real uptime in that box, not just the last 10 times you clicked that button?

Nutter
Jun 25, 2007, 02:24 PM
My example contains everything you need to get started - if you want to change the way the app behaves I'm afraid you will have to work on it yourself.

PS. If you're looking for a way to check whether or not the Mac has been restarted since the uptime was last measured, I don't know how to do that.

twoodcc
Jun 25, 2007, 07:55 PM
My example contains everything you need to get started - if you want to change the way the app behaves I'm afraid you will have to work on it yourself.

PS. If you're looking for a way to check whether or not the Mac has been restarted since the uptime was last measured, I don't know how to do that.

thanks for all you've done. it works great. i don't know how to check to see if the mac has been restarted, and stuff like that.

but maybe it's better like it is though. it's not bad. i like it. i just need to try to figure out how to change the interface though.

thanks again :)

Nutter
Jun 26, 2007, 06:23 AM
No problem ... My perfectionism got the better of me and I decided to fix it up after all.

The new version now automatically updates the current uptime every minute, and only places an uptime into the list of last ten uptimes after a restart.

EDIT: Oops, bug. Fixed.

twoodcc
Jun 26, 2007, 08:17 PM
No problem ... My perfectionism got the better of me and I decided to fix it up after all.

The new version now automatically updates the current uptime every minute, and only places an uptime into the list of last ten uptimes after a restart.

EDIT: Oops, bug. Fixed.

wow, thanks! you really didn't have to do that, but i'm glad that you did. thank you.

now do you know how to make the interface look more like leopard? or itunes?

Nutter
Jun 27, 2007, 04:07 AM
Take a look at TunesWindow, on this page:
http://mattgemmell.com/source/

PS. Looks like my code isn't quite there, as the system's uptime counter seems to be suspended when the computer is asleep. (I didn't realise that.) Does anyone know how to get the time of the last restart?

Lixivial
Jun 28, 2007, 07:17 AM
I apologize in advance if this is of no help whatsoever, Nutter. :)

Does anyone know how to get the time of the last restart?

You may find some help by looking at the manpages for utmp (5) (http://developer.apple.com/documentation/Darwin/Reference/ManPages/man5/utmp.5.html). ut_name will contain reboot, and time_t contains the time it went down for reboot. For an example of how this information is parsed, the Terminal command "last" parses /private/var/log/wtmp. "last reboot" will give the list of restarts, while "last -1 reboot" will display just the previous reboot time.

Otherwise the very last post in cocoadev's FindingUptime (http://www.cocoadev.com/index.pl?FindingUptime) article may be of assistance. In that case it uses sysctl and gives you the time that the system (kernel) was booted this session.

Again, I don't know if that's of any assistance to you or not.

EDIT: Typo. Fixed "list -1 reboot".

Nutter
Jun 29, 2007, 08:11 PM
Thank you Lixivial, that was very helpful.

Here's my final final version. I am retiring. :)

twoodcc
Jun 30, 2007, 11:33 PM
Thank you Lixivial, that was very helpful.

Here's my final final version. I am retiring. :)

thanks again! :) and very good work! ;)

twoodcc
Jul 6, 2008, 10:10 AM
Thank you Lixivial, that was very helpful.

Here's my final final version. I am retiring. :)

sorry to bring back this old thread, but i stumbled upon something.

your uptime is held in '/usr/bin/uptime'.

i was thinking that this could help this program?