00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #import "DataManager.h"
00011
00012 @interface DataManager()
00013
00014 -(int)calculateAverageFor:(NSString*)_object andType:(MachineLearningType)_learningType;
00015 -(void)saveGameData;
00016
00017 @end
00018
00019 @implementation DataManager
00020
00021 static DataManager* _instance = nil;
00022
00023 #pragma mark -
00024 #pragma mark Memory Allocation
00025
00026 -(void)dealloc
00027 {
00028 [reinforcementData release];
00029 [decisionTreeData release];
00030 [shortestRouteData release];
00031 [noLearningData release];
00032 [super dealloc];
00033 }
00034
00039 +(id)alloc
00040 {
00041 @synchronized([DataManager class])
00042 {
00043
00044 NSAssert(_instance == nil, @"There should only ever be one instance of DataManager");
00045 _instance = [super alloc];
00046 return _instance;
00047 }
00048
00049 return nil;
00050 }
00051
00052 #pragma mark -
00053 #pragma mark Initialisation
00054
00059 -(id)init
00060 {
00061 self = [super init];
00062
00063 if (self != nil)
00064 {
00065 reinforcementData = [[NSMutableDictionary alloc] init];
00066 decisionTreeData = [[NSMutableDictionary alloc] init];
00067 shortestRouteData = [[NSMutableDictionary alloc] init];
00068 noLearningData = [[NSMutableDictionary alloc] init];
00069
00070 [self loadGameData];
00071 }
00072
00073 return self;
00074 }
00075
00076 #pragma mark -
00077
00082 +(DataManager*)sharedDataManager
00083 {
00084 @synchronized([DataManager class])
00085 {
00086 if(!_instance) [[self alloc] init];
00087 return _instance;
00088 }
00089
00090 return nil;
00091 }
00092
00093 #pragma mark -
00094
00100 -(int)averageEpisodeTimeLearning:(MachineLearningType)_learningType
00101 {
00102 return [self calculateAverageFor:@"averageTimeLearning" andType:_learningType];
00103 }
00104
00105
00111 -(int)averageEpisodeTimeNonLearning:(MachineLearningType)_learningType
00112 {
00113 return [self calculateAverageFor:@"averageTimeNonLearning" andType:_learningType];
00114 }
00115
00121 -(int)averageActionsLearning:(MachineLearningType)_learningType
00122 {
00123 return [self calculateAverageFor:@"averageActionsLearning" andType:_learningType];
00124 }
00125
00131 -(int)averageActionsNonLearning:(MachineLearningType)_learningType
00132 {
00133 return [self calculateAverageFor:@"averageActionsNonLearning" andType:_learningType];
00134 }
00135
00141 -(float)averageAgentsSaved:(MachineLearningType)_learningType
00142 {
00143 int saved = [self calculateAverageFor:@"saved" andType:_learningType];
00144 int killed = [self calculateAverageFor:@"killed" andType:_learningType];
00145
00146 return (float)saved/((float)(saved+killed));
00147 }
00148
00155 -(int)calculateAverageFor:(NSString*)_object andType:(MachineLearningType)_learningType
00156 {
00157 NSMutableDictionary* learningData;
00158 float average = 0;
00159
00160 switch (_learningType)
00161 {
00162 case kLearningReinforcement:
00163 learningData = reinforcementData;
00164 break;
00165
00166 case kLearningTree:
00167 learningData = decisionTreeData;
00168 break;
00169
00170 case kLearningShortestRoute:
00171 learningData = shortestRouteData;
00172 break;
00173
00174 case kLearningNone:
00175 learningData = noLearningData;
00176 break;
00177
00178 default:
00179 break;
00180 }
00181
00182 for(NSString* item in learningData)
00183 {
00184 NSMutableDictionary* subDict = [learningData objectForKey:item];
00185 average += [[subDict objectForKey:_object] intValue];
00186 }
00187
00188 average /= [learningData count];
00189
00190 return average;
00191 }
00192
00193 #pragma mark -
00194 #pragma mark Data Manipulation
00195
00199 -(void)addCurrentGameData
00200 {
00201 CCLOG(@"%@.addCurrentGameData: %@", NSStringFromClass([self class]), [Utils getLearningTypeAsString:[LemmingManager sharedLemmingManager].learningType]);
00202
00203
00204 AgentStats* am = [AgentStats sharedAgentStats];
00205 GameManager* gm = [GameManager sharedGameManager];
00206 LemmingManager* lm = [LemmingManager sharedLemmingManager];
00207
00208 MachineLearningType learningType = lm.learningType;
00209
00210
00211 if(learningType == kLearningMixed) { CCLOG(@"%@.addCurrentGameData: Can't save data when mixing learning types", NSStringFromClass([self class])); return; }
00212
00213
00214 int saved = [lm lemmingsSaved];
00215 int killed = [lm lemmingsKilled];
00216 int time = [gm getGameTimeInSecs];
00217 int learningEpisodes = [lm learningEpisodes];
00218 int averageTimeLearning = [am averageTimeLearning];
00219 int averageTimeNonLearning = [am averageTimeNonLearning];
00220 int averageActionsLearning = [am averageActionsLearning];
00221 int averageActionsNonLearning = [am averageActionsNonLearning];
00222 GameRating rating = [lm calculateGameRating];
00223
00224
00225 NSDictionary* gameData = [NSMutableDictionary dictionaryWithObjectsAndKeys:
00226 [NSNumber numberWithInt:saved], @"saved",
00227 [NSNumber numberWithInt:killed], @"killed",
00228 [NSNumber numberWithInt:time], @"time",
00229 [NSNumber numberWithInt:learningEpisodes], @"learningEpisodes",
00230 [NSNumber numberWithInt:averageTimeLearning], @"averageTimeLearning",
00231 [NSNumber numberWithInt:averageTimeNonLearning], @"averageTimeNonLearning",
00232 [NSNumber numberWithInt:averageActionsLearning], @"averageActionsLearning",
00233 [NSNumber numberWithInt:averageActionsNonLearning], @"averageActionsNonLearning",
00234 [NSNumber numberWithInt:rating], @"rating", nil];
00235
00236
00237 NSString* timeStamp = [Utils getTimeStampWithFormat:@"yyyy-MM-dd [HH:mm:ss]"];
00238
00239
00240
00241 switch (learningType)
00242 {
00243 case kLearningReinforcement:
00244 [reinforcementData setObject:gameData forKey:[NSString stringWithFormat:@"%@ %@", [gm currentLevel].name, timeStamp]];
00245 break;
00246
00247 case kLearningTree:
00248 [decisionTreeData setObject:gameData forKey:timeStamp];
00249 break;
00250
00251 case kLearningShortestRoute:
00252 [shortestRouteData setObject:gameData forKey:timeStamp];
00253 break;
00254
00255 case kLearningNone:
00256 [noLearningData setObject:gameData forKey:timeStamp];
00257 break;
00258
00259 default:
00260 CCLOG(@"%@.addCurrentGameData: Unknown learning type (%i)", NSStringFromClass([self class]), learningType);
00261 break;
00262 }
00263
00264 CCLOG(@"Adding: saved: %i killed: %i time: %i avg time L: %i avg time: %i avg actions L: %i avg actions: %i rating: %i completed at: %@", saved, killed, time, averageTimeLearning, averageTimeNonLearning, averageActionsLearning, averageActionsNonLearning, rating, timeStamp);
00265 [self saveGameData];
00266 [self exportGameData];
00267 }
00268
00272 -(void)loadGameData
00273 {
00274 NSMutableDictionary* tempData = [[NSUserDefaults standardUserDefaults] objectForKey:kProjectName];
00275
00276 if(tempData != nil)
00277 {
00278 [reinforcementData addEntriesFromDictionary:[tempData objectForKey:@"reinforcement"]];
00279 [decisionTreeData addEntriesFromDictionary:[tempData objectForKey:@"decisionTree"]];
00280 [shortestRouteData addEntriesFromDictionary:[tempData objectForKey:@"shortestRoute"]];
00281 [noLearningData addEntriesFromDictionary:[tempData objectForKey:@"noLearning"]];
00282 }
00283 else CCLOG(@"No data to load");
00284 }
00285
00289 -(void)saveGameData
00290 {
00291
00292 [[NSUserDefaults standardUserDefaults] setObject:[NSMutableDictionary dictionaryWithObjectsAndKeys: reinforcementData, @"reinforcement", decisionTreeData, @"decisionTree", shortestRouteData, @"shortestRoute", noLearningData, @"noLearning", nil] forKey:kProjectName];
00293 [[NSUserDefaults standardUserDefaults] synchronize];
00294 }
00295
00299 -(void)clearGameData
00300 {
00301 [[NSUserDefaults standardUserDefaults] removeObjectForKey:kProjectName];
00302 [[NSUserDefaults standardUserDefaults] synchronize];
00303 }
00304
00308 -(void)exportGameData
00309 {
00310
00311 NSString* documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
00312 NSString* filePath = [documentsDirectory stringByAppendingPathComponent:kFilenameGameData];
00313
00314
00315 [[NSMutableDictionary dictionaryWithObjectsAndKeys: reinforcementData, @"reinforcement", decisionTreeData, @"decisionTree", shortestRouteData, @"shortestRoute", nil] writeToFile:filePath atomically:YES];
00316 }
00317
00321 -(void)printData
00322 {
00323 CCLOG(@"%@.printData", NSStringFromClass([self class]));
00324
00325 CCLOG(@" Reinforcement: ");
00326 for(NSString* item in reinforcementData) NSLog(@" [Key: %@ - Value: %@]", item, [reinforcementData valueForKey:item]);
00327
00328 CCLOG(@" Decision Tree: ");
00329 for(NSString* item in decisionTreeData) NSLog(@" [Key: %@ - Value: %@]", item, [decisionTreeData valueForKey:item]);
00330
00331 CCLOG(@" Shortest Route: ");
00332 for(NSString* item in shortestRouteData) NSLog(@" [Key: %@ - Value: %@]", item, [shortestRouteData valueForKey:item]);
00333
00334 CCLOG(@" No Learning: ");
00335 for(NSString* item in noLearningData) NSLog(@" [Key: %@ - Value: %@]", item, [noLearningData valueForKey:item]);
00336 }
00337
00338 @end