ios: refactor the code of the after-game statistics display using delegates
authorkoda
Mon, 09 Apr 2012 04:43:30 +0200
changeset 6870 f72cac290325
parent 6869 a187c280dd3d
child 6871 5aadbfe02613
ios: refactor the code of the after-game statistics display using delegates
project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.h
project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.m
project_files/HedgewarsMobile/Classes/GameInterfaceBridge.h
project_files/HedgewarsMobile/Classes/GameInterfaceBridge.m
--- a/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.h	Mon Apr 09 03:25:17 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.h	Mon Apr 09 04:43:30 2012 +0200
@@ -21,19 +21,27 @@
 #import "SDL_net.h"
 
 
+@protocol EngineProtocolDelegate <NSObject>
+
+-(void) gameEndedWithStatistics:(NSArray *)stats;
+
+@end
+
+
 @interface EngineProtocolNetwork : NSObject {
-    NSMutableArray *statsArray;
+    id<EngineProtocolDelegate> delegate;
     NSOutputStream *stream;
     TCPsocket csd;
     NSInteger enginePort;
 }
 
-@property (nonatomic,assign) NSMutableArray *statsArray;
+@property (nonatomic,assign) id<EngineProtocolDelegate> delegate;
 @property (nonatomic,retain) NSOutputStream *stream;
 @property (assign) TCPsocket csd;
 @property (assign) NSInteger enginePort;
 
 -(id)   init;
+-(id)   initWithPort:(NSInteger) port;
 -(void) spawnThread:(NSString *)onSaveFile withOptions:(NSDictionary *)dictionary;
 -(void) engineProtocol:(id) object;
 
--- a/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.m	Mon Apr 09 03:25:17 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.m	Mon Apr 09 04:43:30 2012 +0200
@@ -23,20 +23,24 @@
 #define BUFFER_SIZE 255     // like in original frontend
 
 @implementation EngineProtocolNetwork
-@synthesize statsArray, stream, csd, enginePort;
+@synthesize delegate, stream, csd, enginePort;
 
--(id) init {
+-(id) initWithPort:(NSInteger) port {
     if (self = [super init]) {
-        self.statsArray = nil;
+        self.delegate = nil;
         self.csd = NULL;
         self.stream = nil;
-        self.enginePort = [HWUtils randomPort];
+        self.enginePort = port;
     }
     return self;
 }
 
+-(id) init {
+    return [self initWithPort:[HWUtils randomPort]];
+}
+
 -(void) dealloc {
-    releaseAndNil(statsArray);
+    self.delegate = nil;
     releaseAndNil(stream);
     [super dealloc];
 }
@@ -212,6 +216,7 @@
 -(void) engineProtocol:(id) object {
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
     NSDictionary *gameConfig = (NSDictionary *)object;
+    NSMutableArray *statsArray = nil;
     TCPsocket sd;
     IPaddress ip;
     int eProto;
@@ -326,10 +331,10 @@
                 }
                 break;
             case 'i':
-                if (self.statsArray == nil) {
-                    self.statsArray = [[NSMutableArray alloc] initWithCapacity:10 - 2];
+                if (statsArray == nil) {
+                    statsArray = [[NSMutableArray alloc] initWithCapacity:10 - 2];
                     NSMutableArray *ranking = [[NSMutableArray alloc] initWithCapacity:4];
-                    [self.statsArray insertObject:ranking atIndex:0];
+                    [statsArray insertObject:ranking atIndex:0];
                     [ranking release];
                 }
                 NSString *tempStr = [NSString stringWithUTF8String:&buffer[2]];
@@ -338,16 +343,16 @@
                 int index = [arg length] + 3;
                 switch (buffer[1]) {
                     case 'r':           // winning team
-                        [self.statsArray insertObject:[NSString stringWithUTF8String:&buffer[2]] atIndex:1];
+                        [statsArray insertObject:[NSString stringWithUTF8String:&buffer[2]] atIndex:1];
                         break;
                     case 'D':           // best shot
-                        [self.statsArray addObject:[NSString stringWithFormat:@"The best shot award won by %s (with %@ points)", &buffer[index], arg]];
+                        [statsArray addObject:[NSString stringWithFormat:@"The best shot award won by %s (with %@ points)", &buffer[index], arg]];
                         break;
                     case 'k':           // best hedgehog
-                        [self.statsArray addObject:[NSString stringWithFormat:@"The best killer is %s with %@ kill(s) in a turn", &buffer[index], arg]];
+                        [statsArray addObject:[NSString stringWithFormat:@"The best killer is %s with %@ kill(s) in a turn", &buffer[index], arg]];
                         break;
                     case 'K':           // number of hogs killed
-                        [self.statsArray addObject:[NSString stringWithFormat:@"%@ hedgehog(s) were killed during this round", arg]];
+                        [statsArray addObject:[NSString stringWithFormat:@"%@ hedgehog(s) were killed during this round", arg]];
                         break;
                     case 'H':           // team health/graph
                         break;
@@ -355,16 +360,16 @@
                         // still WIP in statsPage.cpp
                         break;
                     case 'P':           // teams ranking
-                        [[self.statsArray objectAtIndex:0] addObject:tempStr];
+                        [[statsArray objectAtIndex:0] addObject:tempStr];
                         break;
                     case 's':           // self damage
-                        [self.statsArray addObject:[NSString stringWithFormat:@"%s thought it's good to shoot his own hedgehogs with %@ points", &buffer[index], arg]];
+                        [statsArray addObject:[NSString stringWithFormat:@"%s thought it's good to shoot his own hedgehogs with %@ points", &buffer[index], arg]];
                         break;
                     case 'S':           // friendly fire
-                        [self.statsArray addObject:[NSString stringWithFormat:@"%s killed %@ of his own hedgehogs", &buffer[index], arg]];
+                        [statsArray addObject:[NSString stringWithFormat:@"%s killed %@ of his own hedgehogs", &buffer[index], arg]];
                         break;
                     case 'B':           // turn skipped
-                        [self.statsArray addObject:[NSString stringWithFormat:@"%s was scared and skipped turn %@ times", &buffer[index], arg]];
+                        [statsArray addObject:[NSString stringWithFormat:@"%s was scared and skipped turn %@ times", &buffer[index], arg]];
                         break;
                     default:
                         DLog(@"Unhandled stat message, see statsPage.cpp");
@@ -373,6 +378,9 @@
                 break;
             case 'q':
                 // game ended and match finished, statsArray is full of delicious statistics
+                if (self.delegate != nil && [self.delegate respondsToSelector:@selector(gameEndedWithStatistics:)])
+                    [self.delegate gameEndedWithStatistics:statsArray];
+                [statsArray release];
                 [HWUtils setGameStatus:gsEnded];
                 // closing connection here would trigger a "IPC connection lost" error, so we have to wait until recv fails
                 break;
--- a/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.h	Mon Apr 09 03:25:17 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.h	Mon Apr 09 04:43:30 2012 +0200
@@ -18,19 +18,18 @@
 
 
 #import <Foundation/Foundation.h>
+#import "EngineProtocolNetwork.h"
 
 
-@class EngineProtocolNetwork;
-
-@interface GameInterfaceBridge : NSObject {
+@interface GameInterfaceBridge : NSObject <EngineProtocolDelegate> {
     UIView *blackView;
     NSString *savePath;
-    EngineProtocolNetwork *proto;
+    NSInteger port;
 }
 
 @property (nonatomic,retain) UIView *blackView;
 @property (nonatomic,retain) NSString *savePath;
-@property (nonatomic,retain) EngineProtocolNetwork *proto;
+@property (assign) NSInteger port;
 
 +(void) startLocalGame:(NSDictionary *)withOptions;
 +(void) startSaveGame:(NSString *)atPath;
--- a/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.m	Mon Apr 09 03:25:17 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.m	Mon Apr 09 04:43:30 2012 +0200
@@ -25,7 +25,7 @@
 static UIViewController *callingController;
 
 @implementation GameInterfaceBridge
-@synthesize blackView, savePath, proto;
+@synthesize blackView, savePath, port;
 
 #pragma mark -
 #pragma mark Instance methods for engine interaction
@@ -35,9 +35,10 @@
     [[AudioManagerController mainManager] fadeOutBackgroundMusic];
 
     EngineProtocolNetwork *engineProtocol = [[EngineProtocolNetwork alloc] init];
-    self.proto = engineProtocol;
+    self.port = engineProtocol.enginePort;
+    engineProtocol.delegate = self;
+    [engineProtocol spawnThread:self.savePath withOptions:optionsOrNil];
     [engineProtocol release];
-    [self.proto spawnThread:self.savePath withOptions:optionsOrNil];
 
     // add a black view hiding the background
     UIWindow *thisWindow = [[HedgewarsAppDelegate sharedAppDelegate] uiwindow];
@@ -82,20 +83,6 @@
     [UIView commitAnimations];
     [self.blackView performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:1];
 
-    // engine thread *should* be done by now
-    NSArray *stats = [[NSArray alloc] initWithArray:self.proto.statsArray copyItems:YES];
-    if ([HWUtils gameStatus] == gsEnded && stats != nil) {
-        StatsPageViewController *statsPage = [[StatsPageViewController alloc] init];
-        statsPage.statsArray = stats;
-        statsPage.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
-        if ([statsPage respondsToSelector:@selector(setModalPresentationStyle:)])
-            statsPage.modalPresentationStyle = UIModalPresentationPageSheet;
-
-        [callingController presentModalViewController:statsPage animated:YES];
-        [statsPage release];
-    }
-    [stats release];
-
     // can remove the savefile if the replay has ended
     if ([HWUtils gameType] == gtSave)
         [[NSFileManager defaultManager] removeItemAtPath:self.savePath error:nil];
@@ -111,9 +98,8 @@
 -(void) engineLaunch {
     const char *gameArgs[11];
     CGFloat width, height;
-    NSInteger enginePort = self.proto.enginePort;
     CGFloat screenScale = [[UIScreen mainScreen] safeScale];
-    NSString *ipcString = [[NSString alloc] initWithFormat:@"%d",enginePort];
+    NSString *ipcString = [[NSString alloc] initWithFormat:@"%d",self.port];
     NSString *localeString = [[NSString alloc] initWithFormat:@"%@.txt",[[NSLocale preferredLanguages] objectAtIndex:0]];
     NSUserDefaults *settings = [NSUserDefaults standardUserDefaults];
 
@@ -175,11 +161,23 @@
 -(void) dealloc {
     releaseAndNil(blackView);
     releaseAndNil(savePath);
-    releaseAndNil(proto);
     [super dealloc];
 }
 
 #pragma mark -
+#pragma mark EngineProtocolDelegate methods
+-(void) gameEndedWithStatistics:(NSArray *)stats {
+    if (stats != nil) {
+        StatsPageViewController *statsPage = [[StatsPageViewController alloc] init];
+        statsPage.statsArray = stats;
+        statsPage.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
+
+        [callingController presentModalViewController:statsPage animated:YES];
+        [statsPage release];
+    }
+}
+
+#pragma mark -
 #pragma mark Class methods for setting up the engine from outsite
 +(void) registerCallingController:(UIViewController *)controller {
     callingController = controller;