Description: getting of data for building a chart from text file.
#import "Charting/ChartDataSource.h"
@interface DataSource : NSObject <ChartDataSource> {
NSArray *_timestampTitles;
NSArray *_timestampArray;
double _yMin;
double _yMax;
double _xMin;
double _xMax;
double _minValue;
double _maxValue;
double _secondaryYMin;
double _secondaryYMax;
double _accumulatedMin;
double _accumulatedMax;
double _accumulatedSecondaryMin;
double _accumulatedSecondaryMax;
int m_prevCount;
int m_nextCount;
int seriesCount;
NSMutableArray *legendTitles;
NSMutableArray *data;
int _currTimestamp;
NSMutableArray *_availableKeys;
}
- (id) init;
- (void) loadData;
- (void)obtainMin:(double *)min andMax:(double *)max fromArray:(NSArray *)arr
addingPositivesTo:(NSMutableArray *)positiveValues addingNegativesTo:(NSMutableArray *)negativeValues;
- (void)prepare;
@property (assign) int countSeries;
@property (nonatomic,assign) int prevCount;
@property (nonatomic,assign) int nextCount;
@end
#import "DataSource.h"
@implementation DataSource
@synthesize accumulatedMax = _accumulatedMax;
@synthesize accumulatedMin = _accumulatedMin;
@synthesize accumulatedSecondaryMax = _accumulatedSecondaryMax;
@synthesize accumulatedSecondaryMin = _accumulatedSecondaryMin;
@synthesize yMax = _yMax;
@synthesize xMax = _xMax;
@synthesize yMin = _yMin;
@synthesize xMin = _xMin;
@synthesize minValue = _minValue;
@synthesize maxValue = _maxValue;
@synthesize secondaryYMax = _secondaryYMax;
@synthesize secondaryYMin = _secondaryYMin;
@synthesize availableSeriesKeys = _availableSerKeys;
@synthesize timestampArray = _timestampArray;
@synthesize timestampTitles = _timestampTitles;
@synthesize countSeries = seriesCount;
@synthesize nextCount = m_nextCount;
@synthesize prevCount = m_prevCount;
- (id) init{
self = [super init];
if(self)
{
_yMin = 0.0;
_yMax = 0.0;
_xMin = 0.0;
_xMax = 0.0;
_secondaryYMin = 0.0;
_secondaryYMax = 0.0;
_accumulatedMin = 0.0;
_accumulatedMax = 0.0;
_accumulatedSecondaryMin = 0.0;
_accumulatedSecondaryMax = 0.0;
_availableKeys = [NSMutableArray new];
legendTitles = [NSMutableArray new];
// Determine data array
data = [NSMutableArray new];
[self loadData];
seriesCount = [data count];
return self;
}
return nil;
}
- (void )loadData
{
NSString *path = [[NSBundle mainBundle] pathForResource:@"data.txt" ofType:nil]; // Get path to data file
NSString *dataString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; // Read contents
NSArray *lines = [dataString componentsSeparatedByString:@"\n"]; // Split string with contents into substrings and insert to array
NSMutableArray *table = [NSMutableArray new];
for (NSString *line in lines) {
[table addObject:[line componentsSeparatedByString:@";"]]; // Split each array element into substrings
}
NSMutableArray *timelineTitles = [[table objectAtIndex:0] mutableCopy];
[timelineTitles removeObjectAtIndex:0];
_timestampTitles = [[NSArray arrayWithArray:timelineTitles] retain];
_timestampArray = [[NSArray arrayWithArray:timelineTitles] retain];
[timelineTitles release];
// Insert information on each country to array
for (int i = 1; i < [table count]; i++) {
NSArray *line = [table objectAtIndex:i];
NSMutableArray *values = [[NSMutableArray new] autorelease];
[legendTitles addObject:[line objectAtIndex:0]];
for (int j = 1; j < [line count]; j++) {
[values addObject:[NSNumber numberWithFloat:[[line objectAtIndex:j] floatValue]] ];
}
[data addObject:values];
}
}
// Determine series data (population for specific period)
- (NSArray *) seriesDataWithIndex:(int)seriesIndex
{
if (seriesIndex < 0) {
seriesIndex = 3;
}
NSMutableArray *serData = [[data objectAtIndex:seriesIndex] mutableCopy];
for(int i = 0; i < m_prevCount; i++)
[serData insertObject:[NSNull null] atIndex:0];
for (int i = 0; i < m_nextCount; i++) {
[serData addObject:[NSNull null]];
}
return serData;
}
// Determine values for timeline axis
-(NSArray *)timestampArray
{
NSMutableArray *ar = [_timestampArray mutableCopy];
for(int i = 0; i < m_prevCount; i++)
[ar insertObject:[NSNumber numberWithInt:-1] atIndex:0];
for (int i = 0; i < m_nextCount; i++) {
[ar addObject:[NSNumber numberWithInt:-1]];
}
return ar;
}
// Determine titles for timeline axis values
- (NSArray *)timestampTitles
{
NSMutableArray *ar = [_timestampTitles mutableCopy];
for(int i = 0; i < m_prevCount; i++)
[ar insertObject:@" " atIndex:0];
for (int i = 0; i < m_nextCount; i++) {
[ar addObject:@" "];
}
return ar;
}
// Determine the array containing available series keys
- (NSArray *)availableSeriesKeys
{
return data;
}
// Determine series name displayed in legend
- (NSString *)seriesNameWithIndex:(int)seriesIndex
{
return [legendTitles objectAtIndex:seriesIndex];
}
// Calculate values of maximum and minimum elements in data
- (void)obtainMin:(double *)min andMax:(double *)max fromArray:(NSArray *)arr addingPositivesTo:(NSMutableArray *)positiveValues addingNegativesTo:(NSMutableArray *)negativeValues
{
if(([positiveValues count] == 0) || ([negativeValues count] == 0) )
{
[positiveValues removeAllObjects];
[negativeValues removeAllObjects];
for (int i=0; i < [arr count]; i++) {
NSNumber *value = [arr objectAtIndex:i];
if ([value class] == [NSNull class]) {
continue;
}
if ([value floatValue] > 0) {
[positiveValues addObject:[arr objectAtIndex:i]];
}
[positiveValues addObject:[NSNumber numberWithFloat:0.0f]];
}
for (int i=0; i < [arr count]; i++) {
NSNumber *value = [arr objectAtIndex:i];
if ([value class] == [NSNull class]) {
continue;
}
if ([value floatValue] < 0) {
[negativeValues addObject:[arr objectAtIndex:i]];
}
[negativeValues addObject:[NSNumber numberWithFloat:0.0f]];
}
}
else
{
for (int i=0; i < [arr count]; i++)
{
NSNumber *value = [arr objectAtIndex:i];
if ([value class] == [NSNull class]) {
continue;
}
if ([value floatValue] > 0)
{
NSNumber *num = [positiveValues objectAtIndex:i];
num = [NSNumber numberWithFloat:[num floatValue] + [value floatValue]];
[positiveValues replaceObjectAtIndex:i withObject:num];
}
else
{
NSNumber *num = [negativeValues objectAtIndex:i - m_prevCount];
num = [NSNumber numberWithFloat:[num floatValue] + [value floatValue]];
[negativeValues replaceObjectAtIndex:i - m_prevCount withObject:num];
}
}
float _min = *min;
float _max = *max;
for (int i=0; i < [arr count]; i++) {
NSNumber *value = [arr objectAtIndex:i];
if ([value class] == [NSNull class]) {
continue;
}
if ([value floatValue] > _max)
_max = [value floatValue];
if([value floatValue] < _min)
_min = [value floatValue];
}
*max = _max;
*min = _min;
}
}
- (void)prepare {
NSMutableArray *positive = [NSMutableArray new];
NSMutableArray *negative = [NSMutableArray new];
for(int i = 0; i < seriesCount; i++)
{
NSLog(@"%d",i);
[self obtainMin:&_yMin andMax:&_yMax fromArray:[self seriesDataWithIndex:i] addingPositivesTo:positive addingNegativesTo:negative];
}
for (int i=0; i < [positive count]; i++) {
NSNumber *value = [positive objectAtIndex:i];
if ([value floatValue] > _accumulatedMax)
_accumulatedMax = [value floatValue];
}
for (int i=0; i < [negative count]; i++) {
NSNumber *value = [negative objectAtIndex:i];
if ([value floatValue] < _accumulatedMax)
_accumulatedMin = [value floatValue];
}
_xMax = _yMax;
_xMin = _yMin;
_maxValue = _yMax;
_minValue = _yMin;
[positive release];
[negative release];
}
// Determine the object containing available series title parameters
- (NSDictionary *) availableSeriesHeaders
{
return nil;
}
// Determine labels for X axis
- (NSString *)xAxisNameForMask:(NSString *)mask
{
return @"";
}
// Determine labels for Y axis
- (NSString *)yAxisNameForMask:(NSString *)mask
{
return @"";
}
// Determine labels for secondary axis
- (NSString *)secondaryAxisNameForMask:(NSString *)mask
{
return @"";
}
- (double)xMax
{
return _xMax;
}
- (double) xMin
{
return _xMin;
}
- (double) yMax
{
return _yMax;
}
- (double) yMin
{
return _yMin;
}
- (double)secondaryYMin
{
return 0.0;
}
- (double)secondaryYMax
{
return 0.0;
}
- (double)accumulatedSecondaryMin
{
return 0.0;
}
- (double)accumulatedSecondaryMax
{
return 0.0;
}
- (int)minTimestamp
{
return 0;
}
- (int)maxTimestamp
{
return 0;
}
- (void)setMaxTimestamp:(int)mt{}
- (void)setMinTimestamp:(int)mt{}
- (void)setCurrentTimestamp:(int)currentTimestamp
{
_currTimestamp = currentTimestamp;
}
- (void)setStartDataIndexOffset:(int)startOffset andEndDataIndexOffset:(int)endOffset {}
@end
See also: