source: orbit/iOS/Orbit/Orbit/controllers/StatisticsViewController.m @ 2246ba0

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