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

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