source: orbit/iOS/Orbit/Orbit/controllers/StatisticsViewController.m @ fc960da

Servo
Last change on this file since fc960da was fc960da, checked in by Steve Castellotti <sc@…>, 6 years ago
  • Property mode set to 100644
File size: 15.0 KB
Line 
1//
2//  StatisticsViewController.m
3//  orbit
4//
5//  Copyright (c) 2013 Puzzlebox Productions, LLC. All rights reserved.
6//
7//  With thanks to Ray Wenderlich
8//  http://www.raywenderlich.com/13271/how-to-draw-graphs-with-core-plot-part-2
9//
10//  This code is released under the GNU Public License (GPL) version 2
11//  For more information please refer to http://www.gnu.org/copyleft/gpl.html
12//
13
14#import "StatisticsViewController.h"
15#import "AppDelegate.h"
16
17#import "SignalConverter.h"
18
19#import "HistoryAppDataObject.h"
20#import "AppDelegateProtocol.h"
21
22@implementation StatisticsViewController
23
24@synthesize hostView = hostView_, hostViewBottom = hostViewBottom_;
25
26//- (void)viewDidLoad
27//{
28//   [super viewDidLoad];
29////   AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
30//}
31
32//#pragma mark -
33//#pragma mark instance methods
34
35- (HistoryAppDataObject*) theAppDataObject;
36{
37        id<AppDelegateProtocol> theDelegate = (id<AppDelegateProtocol>) [UIApplication sharedApplication].delegate;
38        HistoryAppDataObject* theDataObject;
39        theDataObject = (HistoryAppDataObject*) theDelegate.theAppDataObject;
40        return theDataObject;
41}
42
43- (void)didReceiveMemoryWarning
44{
45   [super didReceiveMemoryWarning];
46   // Dispose of any resources that can be recreated.
47}
48
49#pragma mark - UIViewController lifecycle methods
50-(void)viewDidAppear:(BOOL)animated {
51   [super viewDidAppear:animated];
52   [self initPlot];
53}
54
55//- (void)viewWillAppear:(BOOL)animated
56//{
57////    HistoryAppDataObject* theDataObject = [self theAppDataObject];
58////    theInputView.text = theDataObject.string1;
59////    theSlider.value = theDataObject.float1;
60//}
61
62#pragma mark - Chart behavior
63-(void)initPlot {
64   [self configureHost];
65   [self configureGraph];
66   [self configurePlots];
67   [self configureAxes];
68   // Block for .5 seconds
69   //   [NSThread sleepForTimeInterval:.5];
70   //   [self reloadData];
71}
72
73-(void)configureHost {
74        self.hostView = [(CPTGraphHostingView *) [CPTGraphHostingView alloc] initWithFrame:self.view.bounds];
75        self.hostView.allowPinchScaling = YES;
76   self.hostView.autoresizesSubviews = YES;
77   
78        self.hostViewBottom = [(CPTGraphHostingView *) [CPTGraphHostingView alloc] initWithFrame:self.view.bounds];
79        self.hostViewBottom.allowPinchScaling = YES;
80   self.hostViewBottom.autoresizesSubviews = YES;
81   
82        [self.view addSubview:self.hostView];
83        [self.view addSubview:self.hostViewBottom];
84}
85
86-(void)configureGraph {
87   
88        // 1 - Create the graphs
89   
90   // Top graph
91        CPTGraph *graphTop = [[CPTXYGraph alloc] initWithFrame:self.hostView.bounds];
92   
93   // Set the theme
94   //   [graphTop applyTheme:[CPTTheme themeNamed:kCPTDarkGradientTheme]];
95   //   [graphTop applyTheme:[CPTTheme themeNamed:kCPTPlainBlackTheme]];
96   //   [graphTop applyTheme:[CPTTheme themeNamed:kCPTPlainWhiteTheme]];
97   //   [graphTop applyTheme:[CPTTheme themeNamed:kCPTSlateTheme]];
98   [graphTop applyTheme:[CPTTheme themeNamed:kCPTStocksTheme]];
99   
100        self.hostView.hostedGraph = graphTop;
101   
102   
103        // Bottom graph
104        CPTGraph *graphBottom = [[CPTXYGraph alloc] initWithFrame:self.hostViewBottom.bounds];
105        self.hostViewBottom.hostedGraph = graphBottom;
106   
107   
108        // 2 - Set graph titles
109   NSString *title = @"Algorithms";
110   //   NSString *title = @"";
111   graphTop.title = title;
112   
113   
114        // 3 - Create and set text style
115        CPTMutableTextStyle *titleStyle = [CPTMutableTextStyle textStyle];
116        titleStyle.color = [CPTColor whiteColor];
117        titleStyle.fontName = @"Helvetica-Bold";
118        titleStyle.fontSize = 16.0f;
119   
120        graphTop.titleTextStyle = titleStyle;
121        graphTop.titlePlotAreaFrameAnchor = CPTRectAnchorTop;
122   graphTop.titleDisplacement = CGPointMake(0.0f, -15.0f);
123   
124   graphBottom.titleTextStyle = titleStyle;
125        graphBottom.titlePlotAreaFrameAnchor = CPTRectAnchorTop;
126        graphBottom.titleDisplacement = CGPointMake(0.0f, 10.0f);
127   
128   
129        // 4 - Set padding for plot area
130        [graphTop.plotAreaFrame setPaddingLeft:30.0f];
131        [graphTop.plotAreaFrame setPaddingBottom:240.0f];
132        [graphTop.plotAreaFrame setPaddingRight:30.0f];
133        [graphTop.plotAreaFrame setPaddingTop:30.0f];
134   
135   [graphBottom.plotAreaFrame setPaddingLeft:30.0f];
136        [graphBottom.plotAreaFrame setPaddingBottom:60.0f];
137        [graphBottom.plotAreaFrame setPaddingRight:30.0f];
138   [graphBottom.plotAreaFrame setPaddingTop:240.0f];
139   
140   
141        // 5 - Enable user interactions for plot space
142        CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *) graphTop.defaultPlotSpace;
143        plotSpace.allowsUserInteraction = YES;
144   
145   CPTXYPlotSpace *plotSpaceBottom = (CPTXYPlotSpace *) graphBottom.defaultPlotSpace;
146        plotSpaceBottom.allowsUserInteraction = YES;
147   
148}
149
150-(void)configurePlots {
151   
152        // 1 - Get graphs and plot space
153        CPTGraph *graphTop = self.hostView.hostedGraph;
154        CPTGraph *graphBottom = self.hostViewBottom.hostedGraph;
155   
156        CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *) graphTop.defaultPlotSpace;
157        CPTXYPlotSpace *plotSpaceBottom = (CPTXYPlotSpace *) graphBottom.defaultPlotSpace;
158   
159   
160        // 2 - Create the two plots
161   
162   // Attention
163        CPTScatterPlot *attentionPlot = [[CPTScatterPlot alloc] init];
164        attentionPlot.dataSource = self;
165   attentionPlot.identifier = @"Attention";
166        CPTColor *attentionColor = [CPTColor redColor];
167        [graphTop addPlot:attentionPlot toPlotSpace:plotSpace];
168   
169   // Meditation
170        CPTScatterPlot *meditationPlot = [[CPTScatterPlot alloc] init];
171        meditationPlot.dataSource = self;
172   meditationPlot.identifier = @"Meditation";
173        CPTColor *meditationColor = [CPTColor blueColor];
174        [graphTop addPlot:meditationPlot toPlotSpace:plotSpace];
175   
176   // Power
177        CPTScatterPlot *powerPlot = [[CPTScatterPlot alloc] init];
178        powerPlot.dataSource = self;
179   powerPlot.identifier = @"Power";
180        CPTColor *powerColor = [CPTColor yellowColor];
181   //   [graphTop addPlot:powerPlot toPlotSpace:plotSpaceBottom];
182        [graphBottom addPlot:powerPlot toPlotSpace:plotSpaceBottom];
183   
184   
185        // 3 - Set up plot space
186        [plotSpace scaleToFitPlots:[NSArray arrayWithObjects:attentionPlot, meditationPlot, nil, nil]];
187        CPTMutablePlotRange *xRange = [plotSpace.xRange mutableCopy];
188        [xRange expandRangeByFactor:CPTDecimalFromCGFloat(1.1f)];
189        plotSpace.xRange = xRange;
190        CPTMutablePlotRange *yRange = [plotSpace.yRange mutableCopy];
191        [yRange expandRangeByFactor:CPTDecimalFromCGFloat(1.2f)];
192        plotSpace.yRange = yRange;
193   
194   
195   [plotSpaceBottom scaleToFitPlots:[NSArray arrayWithObjects:powerPlot, nil, nil, nil]];
196        CPTMutablePlotRange *xRangeBottom = [plotSpaceBottom.xRange mutableCopy];
197        [xRangeBottom expandRangeByFactor:CPTDecimalFromCGFloat(1.1f)];
198        plotSpaceBottom.xRange = xRangeBottom;
199        CPTMutablePlotRange *yRangeBottom = [plotSpaceBottom.yRange mutableCopy];
200        [yRangeBottom expandRangeByFactor:CPTDecimalFromCGFloat(1.2f)];
201        plotSpaceBottom.yRange = yRangeBottom;
202   
203   
204        // 4 - Create styles and symbols
205   
206   //Attention
207        CPTMutableLineStyle *attentionLineStyle = [attentionPlot.dataLineStyle mutableCopy];
208        attentionLineStyle.lineWidth = 2.5;
209        attentionLineStyle.lineColor = attentionColor;
210        attentionPlot.dataLineStyle = attentionLineStyle;
211   
212        CPTMutableLineStyle *attentionSymbolLineStyle = [CPTMutableLineStyle lineStyle];
213        attentionSymbolLineStyle.lineColor = attentionColor;
214        CPTPlotSymbol *attentionSymbol = [CPTPlotSymbol ellipsePlotSymbol];
215        attentionSymbol.fill = [CPTFill fillWithColor:attentionColor];
216        attentionSymbol.lineStyle = attentionSymbolLineStyle;
217        attentionSymbol.size = CGSizeMake(3.0f, 3.0f);
218        attentionPlot.plotSymbol = attentionSymbol;
219   
220   // Meditation
221        CPTMutableLineStyle *meditationLineStyle = [meditationPlot.dataLineStyle mutableCopy];
222        meditationLineStyle.lineWidth = 2.5;
223        meditationLineStyle.lineColor = meditationColor;
224        meditationPlot.dataLineStyle = meditationLineStyle;
225   
226        CPTMutableLineStyle *meditationSymbolLineStyle = [CPTMutableLineStyle lineStyle];
227        meditationSymbolLineStyle.lineColor = meditationColor;
228        CPTPlotSymbol *meditationSymbol = [CPTPlotSymbol ellipsePlotSymbol];
229        meditationSymbol.fill = [CPTFill fillWithColor:meditationColor];
230        meditationSymbol.lineStyle = meditationSymbolLineStyle;
231        meditationSymbol.size = CGSizeMake(3.0f, 3.0f);
232        meditationPlot.plotSymbol = meditationSymbol;
233   
234   // Power
235        CPTMutableLineStyle *powerLineStyle = [powerPlot.dataLineStyle mutableCopy];
236        powerLineStyle.lineWidth = 1;
237        powerLineStyle.lineColor = powerColor;
238        powerPlot.dataLineStyle = powerLineStyle;
239   
240        CPTMutableLineStyle *powerSymbolLineStyle = [CPTMutableLineStyle lineStyle];
241        powerSymbolLineStyle.lineColor = powerColor;
242   //   CPTPlotSymbol *powerSymbol = [CPTPlotSymbol ellipsePlotSymbol];
243   //   powerSymbol.fill = [CPTFill fillWithColor:powerColor];
244   //   powerSymbol.lineStyle = powerSymbolLineStyle;
245   //   powerSymbol.size = CGSizeMake(3.0f, 3.0f);
246   //   powerPlot.plotSymbol = powerSymbol;
247   
248}
249
250-(void)configureAxes {
251   
252        // 1 - Create styles
253        CPTMutableTextStyle *axisTitleStyle = [CPTMutableTextStyle textStyle];
254        axisTitleStyle.color = [CPTColor whiteColor];
255        axisTitleStyle.fontName = @"Helvetica-Bold";
256        axisTitleStyle.fontSize = 12.0f;
257        CPTMutableLineStyle *axisLineStyle = [CPTMutableLineStyle lineStyle];
258        axisLineStyle.lineWidth = 2.0f;
259        axisLineStyle.lineColor = [CPTColor whiteColor];
260        CPTMutableTextStyle *axisTextStyle = [[CPTMutableTextStyle alloc] init];
261        axisTextStyle.color = [CPTColor whiteColor];
262        axisTextStyle.fontName = @"Helvetica-Bold";
263        axisTextStyle.fontSize = 11.0f;
264        CPTMutableLineStyle *tickLineStyle = [CPTMutableLineStyle lineStyle];
265        tickLineStyle.lineColor = [CPTColor whiteColor];
266        tickLineStyle.lineWidth = 2.0f;
267        CPTMutableLineStyle *gridLineStyle = [CPTMutableLineStyle lineStyle];
268        tickLineStyle.lineColor = [CPTColor blackColor];
269        tickLineStyle.lineWidth = 1.0f;
270   
271   
272        // 2 - Get axis set
273        CPTXYAxisSet *axisSet = (CPTXYAxisSet *) self.hostView.hostedGraph.axisSet;
274        CPTXYAxisSet *axisSetBottom = (CPTXYAxisSet *) self.hostViewBottom.hostedGraph.axisSet;
275   
276   
277        // 3 - Configure x-axis
278        CPTAxis *x = axisSet.xAxis;
279        CPTAxis *xBottom = axisSetBottom.xAxis;
280   
281        x.title = @"Last 30 Seconds";
282        x.titleTextStyle = axisTitleStyle;
283        x.titleOffset = 15.0f;
284        x.axisLineStyle = axisLineStyle;
285        x.labelingPolicy = CPTAxisLabelingPolicyNone;
286        x.labelTextStyle = axisTextStyle;
287        x.majorTickLineStyle = axisLineStyle;
288        x.majorTickLength = 4.0f;
289        x.tickDirection = CPTSignNegative;
290   
291   
292        xBottom.title = @"Brainwave (512 Hertz)";
293        xBottom.titleTextStyle = axisTitleStyle;
294        xBottom.titleOffset = 15.0f;
295        xBottom.axisLineStyle = axisLineStyle;
296        xBottom.labelingPolicy = CPTAxisLabelingPolicyNone;
297        xBottom.labelTextStyle = axisTextStyle;
298   //   xBottom.majorTickLineStyle = axisLineStyle;
299   //   xBottom.majorTickLength = 4.0f;
300   //   xBottom.tickDirection = CPTSignNegative;
301   
302   
303        CGFloat secondCount = [[self secondsInHistory] count];
304        NSMutableSet *xLabels = [NSMutableSet setWithCapacity:secondCount];
305        NSMutableSet *xLocations = [NSMutableSet setWithCapacity:secondCount];
306        NSInteger i = 0;
307   
308   for (NSString *second in [self secondsInHistory]) {
309     
310                CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithText:second  textStyle:x.labelTextStyle];
311                CGFloat location = i++;
312                label.tickLocation = CPTDecimalFromCGFloat(location);
313                label.offset = x.majorTickLength;
314                if (label) {
315                        [xLabels addObject:label];
316                        [xLocations addObject:[NSNumber numberWithFloat:location]];
317                }
318        }
319   
320   
321        x.axisLabels = xLabels;
322        x.majorTickLocations = xLocations;
323        xBottom.axisLabels = xLabels;
324        xBottom.majorTickLocations = xLocations;
325   
326   
327   //   // 4 - Configure y-axis
328        CPTAxis *y = axisSet.yAxis;
329        y.title = @"%";
330        y.titleTextStyle = axisTitleStyle;
331   //   y.titleOffset = -40.0f;
332        y.titleOffset = -20.0f;
333        y.axisLineStyle = axisLineStyle;
334        y.majorGridLineStyle = gridLineStyle;
335        y.labelingPolicy = CPTAxisLabelingPolicyNone;
336        y.labelTextStyle = axisTextStyle;
337        y.labelOffset = 16.0f;
338        y.majorTickLineStyle = axisLineStyle;
339        y.majorTickLength = 4.0f;
340        y.minorTickLength = 2.0f;
341        y.tickDirection = CPTSignPositive;
342   
343   
344        CPTAxis *yBottom = axisSetBottom.yAxis;
345   //   yBottom.title = @"Amplitude";
346   //   yBottom.titleTextStyle = axisTitleStyle;
347   //   yBottom.titleOffset = -20.0f;
348        yBottom.axisLineStyle = axisLineStyle;
349        yBottom.majorGridLineStyle = gridLineStyle;
350        yBottom.labelingPolicy = CPTAxisLabelingPolicyNone;
351        yBottom.labelTextStyle = axisTextStyle;
352        yBottom.labelOffset = 16.0f;
353        yBottom.majorTickLineStyle = axisLineStyle;
354        yBottom.majorTickLength = 4.0f;
355        yBottom.minorTickLength = 2.0f;
356        yBottom.tickDirection = CPTSignPositive;
357   
358   
359        NSInteger majorIncrement = 100;
360        NSInteger minorIncrement = 50;
361        CGFloat yMax = 700.0f;  // should determine dynamically based on max value
362        NSMutableSet *yLabels = [NSMutableSet set];
363        NSMutableSet *yMajorLocations = [NSMutableSet set];
364        NSMutableSet *yMinorLocations = [NSMutableSet set];
365        for (NSInteger j = minorIncrement; j <= yMax; j += minorIncrement) {
366                NSUInteger mod = j % majorIncrement;
367                if (mod == 0) {
368                        CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithText:[NSString stringWithFormat:@"%i", j] textStyle:y.labelTextStyle];
369                        NSDecimal location = CPTDecimalFromInteger(j);
370                        label.tickLocation = location;
371                        label.offset = -y.majorTickLength - y.labelOffset;
372                        if (label) {
373                                [yLabels addObject:label];
374                        }
375                        [yMajorLocations addObject:[NSDecimalNumber decimalNumberWithDecimal:location]];
376                } else {
377                        [yMinorLocations addObject:[NSDecimalNumber decimalNumberWithDecimal:CPTDecimalFromInteger(j)]];
378                }
379        }
380        y.axisLabels = yLabels;
381        y.majorTickLocations = yMajorLocations;
382        y.minorTickLocations = yMinorLocations;
383   
384}
385
386#pragma mark - Rotation
387-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
388   return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
389}
390
391#pragma mark - CPTPlotDataSource methods
392-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot {
393   return [[self secondsInHistory] count];
394}
395
396-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index {
397        NSInteger valueCount = [[self secondsInHistory] count];
398   
399   HistoryAppDataObject* theDataObject = [self theAppDataObject];
400   
401        switch (fieldEnum) {
402                case CPTScatterPlotFieldX:
403                        if (index < valueCount) {
404                                return [NSNumber numberWithUnsignedInteger:index];
405                        }
406                        break;
407                       
408                case CPTScatterPlotFieldY:
409         if (index < valueCount) {
410           
411//            return [[NSNumber alloc]initWithInt:(random() % 100)];
412           
413            NSNumber *value = [[NSNumber alloc]initWithInt:(random() % 100)];
414            NSLog(@"Random: %d", (int) value);
415            NSLog(@"lastAttention: %d", theDataObject.lastAttention);
416            return value;
417           
418         }
419         
420                        break;
421        }
422        return [NSDecimalNumber zero];
423}
424
425-(void)reloadData
426{
427   [self.graphTop reloadData];
428   [self.graphBottom reloadData];
429}
430
431- (NSArray *)secondsInHistory
432{
433   static NSArray *seconds = nil;
434   if (!seconds)
435   {
436      seconds = [NSArray arrayWithObjects:
437                 @" ",
438                 @" ",
439                 @" ",
440                 @" ",
441                 @" ",
442                 @"10",
443                 @"  ",
444                 @"  ",
445                 @"  ",
446                 @"  ",
447                 @"  ",
448                 @"  ",
449                 @"  ",
450                 @"20",
451                 @"  ",
452                 @"  ",
453                 @"  ",
454                 @"  ",
455                 @"  ",
456                 @"30",
457                 nil];
458   }
459   return seconds;
460}
461
462@end
Note: See TracBrowser for help on using the repository browser.