1#import "CPTDataSourceTestCase.h"
2#import "CPTExceptions.h"
3#import "CPTScatterPlot.h"
4#import "CPTPlotRange.h"
5#import "CPTUtilities.h"
6
7const CGFloat CPTDataSourceTestCasePlotOffset = 0.5;
8
9/**	@cond */
10@interface CPTDataSourceTestCase ()
11
12-(CPTPlotRange *)plotRangeForData:(NSArray *)dataArray;
13
14@end
15/**	@endcond */
16
17@implementation CPTDataSourceTestCase
18
19@synthesize xData;
20@synthesize yData;
21@synthesize nRecords;
22@synthesize xRange;
23@synthesize yRange;
24@synthesize plots;
25
26-(void)dealloc
27{
28    self.plots = nil;
29    [super dealloc];
30}
31
32-(void)setUp
33{
34    //check CPTDataSource conformance
35    STAssertTrue([self conformsToProtocol:@protocol(CPTPlotDataSource)], @"CPTDataSourceTestCase should conform to <CPTPlotDataSource>");
36}
37
38
39-(void)tearDown
40{
41    self.xData = nil;
42    self.yData = nil;
43    [[self plots] removeAllObjects];
44}
45
46-(void)buildData
47{
48    NSMutableArray *arr = [NSMutableArray arrayWithCapacity:self.nRecords];
49    for ( NSUInteger i=0; i < self.nRecords; i++ ) {
50        [arr insertObject:[NSDecimalNumber numberWithUnsignedInteger:i] atIndex:i];
51    }
52    self.xData = arr;
53
54    arr = [NSMutableArray arrayWithCapacity:self.nRecords];
55    for ( NSUInteger i=0; i < self.nRecords; i++ ) {
56        [arr insertObject:[NSDecimalNumber numberWithDouble:sin(2*M_PI*(double)i/(double)nRecords)] atIndex:i];
57    }
58    self.yData = arr;
59}
60
61-(void)addPlot:(CPTPlot *)newPlot
62{
63    if ( nil == self.plots ) {
64        self.plots = [NSMutableArray array];
65    }
66
67    [[self plots] addObject:newPlot];
68}
69
70-(CPTPlotRange *)xRange
71{
72    [self buildData];
73    return  [self plotRangeForData:self.xData];
74}
75
76-(CPTPlotRange *)yRange
77{
78    [self buildData];
79    CPTPlotRange *range = [self plotRangeForData:self.yData];
80
81    if ( self.plots.count > 1 ) {
82        range.length = CPTDecimalAdd([range length], CPTDecimalFromDouble(self.plots.count));
83    }
84
85    return range;
86}
87
88-(CPTPlotRange *)plotRangeForData:(NSArray *)dataArray
89{
90    double min = [[dataArray valueForKeyPath:@"@min.doubleValue"] doubleValue];
91    double max = [[dataArray valueForKeyPath:@"@max.doubleValue"] doubleValue];
92    double range = max-min;
93
94    return [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(min - 0.05*range)
95                                       length:CPTDecimalFromDouble(range + 0.1*range)];
96}
97
98#pragma mark -
99#pragma mark Plot Data Source Methods
100
101-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
102{
103    return self.nRecords;
104}
105
106-(NSArray *)numbersForPlot:(CPTPlot *)plot
107                     field:(NSUInteger)fieldEnum
108          recordIndexRange:(NSRange)indexRange
109{
110    NSArray *result;
111
112    switch ( fieldEnum ) {
113        case CPTScatterPlotFieldX:
114            result = [[self xData] objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:indexRange]];
115            break;
116        case CPTScatterPlotFieldY:
117            result = [[self yData] objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:indexRange]];
118            if ( self.plots.count > 1 ) {
119                STAssertTrue([[self plots] containsObject:plot], @"Plot missing");
120                NSMutableArray *shiftedResult = [NSMutableArray arrayWithCapacity:result.count];
121                for ( NSDecimalNumber *d in result ) {
122                    [shiftedResult addObject:[d decimalNumberByAdding:[NSDecimalNumber decimalNumberWithDecimal:CPTDecimalFromDouble(CPTDataSourceTestCasePlotOffset * ([[self plots] indexOfObject:plot]+1))]]];
123                }
124
125                result = shiftedResult;
126            }
127
128            break;
129        default:
130            [NSException raise:CPTDataException format:@"Unexpected fieldEnum"];
131    }
132
133    return result;
134}
135@end
136