Skip to content
Browse files

Importing recently used docking stations into favourites

  • Loading branch information...
1 parent 027335e commit aab7e9c0650eaa6ca36992f11d7334aeac458c63 @futureshape futureshape committed Aug 23, 2010
View
2 Classes/AccountViewController.m
@@ -133,7 +133,7 @@ - (void) scraperDidFailWithError:(NSError *)error {
otherButtonTitles:nil] autorelease] show];
} else if ([error code] == kASLoginFailedError) {
[[[[UIAlertView alloc] initWithTitle:@"Login failed"
- message:@"Please check your username & password and try again"
+ message:@"Please check your email address & password and try again"
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil] autorelease] show];
View
4 Classes/CycleHireLocation.h
@@ -18,6 +18,8 @@
NSUInteger bikesAvailable;
NSUInteger spacesAvailable;
+
+ NSDate *lastUsed;
}
@property(nonatomic, retain) NSString *locationId;
@@ -28,6 +30,7 @@
@property(nonatomic) NSUInteger spacesAvailable;
@property(nonatomic,readonly) NSUInteger capacity;
@property(nonatomic) BOOL favourite;
+@property(nonatomic, retain) NSDate *lastUsed;
- (id) initWithLocationId: (NSString *)_locationId
name: (NSString *)_locationName
@@ -41,4 +44,5 @@
- (NSString *)localizedSpacesAvailableText;
- (NSString *)localizedCapacityText;
- (NSUInteger) capacity;
+- (NSComparisonResult) compareLastUsed: (CycleHireLocation *)otherLocation;
@end
View
7 Classes/CycleHireLocation.m
@@ -17,6 +17,7 @@ @implementation CycleHireLocation
@synthesize bikesAvailable;
@synthesize spacesAvailable;
@synthesize favourite;
+@synthesize lastUsed;
- (id) initWithLocationId: (NSString *)_locationId
name: (NSString *)_locationName
@@ -32,6 +33,7 @@ - (id) initWithLocationId: (NSString *)_locationId
self.coordinate = _coordinate;
self.spacesAvailable = _spaces;
self.bikesAvailable = _bikes;
+ self.lastUsed = [NSDate distantPast];
}
return self;
@@ -98,4 +100,9 @@ - (NSUInteger) capacity {
return self.spacesAvailable + self.bikesAvailable;
}
+- (NSComparisonResult) compareLastUsed: (CycleHireLocation *)otherLocation {
+ // reverse sort order - we want newest on top
+ return -[self.lastUsed compare:otherLocation.lastUsed];
+}
+
@end
View
5 Classes/CycleHireLocations.h
@@ -9,6 +9,7 @@
#import <Foundation/Foundation.h>
#import <Three20/Three20.h>
#import "CycleHireLocation.h"
+#import "AccountScraper.h"
#define FAVOURITES_FILE @"favourites.plist"
#define CYCLEHIRE_LOCATIONS_FILE @"cyclehire.csv"
@@ -17,7 +18,7 @@
#define LIVE_DATA_TOO_OLD_NOTIFICATION @"LiveDataTooOld"
#define LIVE_DATA_MAX_AGE (10*60) // 10 minutes
-@interface CycleHireLocations : NSObject {
+@interface CycleHireLocations : NSObject <AccountScraperDelegate> {
NSMutableDictionary *locationsDictionary;
NSMutableDictionary *locationsNameDictionary;
NSMutableArray *favouriteLocations;
@@ -29,6 +30,8 @@
TTURLRequest *updateRequest;
NSDate *lastUpdatedTimestamp;
+
+ AccountScraper *scraper;
}
@property(nonatomic, retain) NSDate *lastUpdatedTimestamp;
View
37 Classes/CycleHireLocations.m
@@ -71,6 +71,10 @@ -(id) init {
location.favourite = YES;
}
}
+
+ scraper = [[AccountScraper alloc] init];
+ scraper.delegate = self;
+ [self updateRecentlyUsedDockingStations];
}
return self;
}
@@ -200,12 +204,45 @@ - (NSDate *) timeStampDateFromString: (NSString *) timeStampString {
return timeStamp;
}
+-(void) updateRecentlyUsedDockingStations {
+ if ([[NSUserDefaults standardUserDefaults] objectForKey:kEmailKey] == nil) {
+ return; // credentials not yet configured, so scraper won't work
+ }
+
+ [scraper startScraping];
+}
+
+- (void) scraperDidFinishScraping {
+ NSDictionary *dockingStationsVisited = scraper.uniqueDockingStationsVisited;
+ NSMutableArray *recentlyUsedDockingStations = [NSMutableArray arrayWithCapacity:[dockingStationsVisited count]];
+
+ for (NSString *fullName in [dockingStationsVisited allKeys]) {
+ NSString *halfName = [[fullName componentsSeparatedByString:@","] objectAtIndex:0];
+ CycleHireLocation *matchingLocation =
+ [locationsNameDictionary objectForKey:[halfName stringByTrimmingCharactersInSet:
+ [NSCharacterSet whitespaceAndNewlineCharacterSet]]];
+
+ matchingLocation.lastUsed = [dockingStationsVisited objectForKey:fullName];
+ [recentlyUsedDockingStations addObject:matchingLocation];
+ }
+
+ [recentlyUsedDockingStations sortUsingSelector:@selector(compareLastUsed:)];
+
+ NSLog(@"recentlyUsedDockingStations - sortedByDate: %@", recentlyUsedDockingStations);
+}
+
+- (void) scraperDidFailWithError:(NSError *)error {
+ // We don't care :)
+}
+
- (void) dealloc {
[super dealloc];
[favouriteLocations release];
[locationsDictionary release];
+ [locationsNameDictionary release];
[favouritesPath release];
[csvDocPath release];
+ [scraper release];
}
@end
View
6 Classes/FavouritesListDataSource.h
@@ -9,9 +9,11 @@
#import <UIKit/UIKit.h>
#import "Three20/Three20.h"
-#import "CycleHireLocations.h";
+#import "CycleHireLocations.h"
-@interface FavouritesListDataSource : TTSectionedDataSource {
+#import "NSMutableArray-RowMoving.h"
+
+@interface FavouritesListDataSource : TTListDataSource {
CycleHireLocations *cycleHireLocations;
NSMutableArray *favouriteLocations;
}
View
19 Classes/FavouritesListDataSource.m
@@ -11,10 +11,9 @@
@implementation FavouritesListDataSource
- (id)initWithCycleHireLocations: (CycleHireLocations *) _cycleHireLocations {
- cycleHireLocations = _cycleHireLocations;
- favouriteLocations = [cycleHireLocations favouriteLocations];
if (self = [super init]) {
- self.sections = [NSArray arrayWithObjects:@"Marked as favourites", @"Recently used", nil];
+ cycleHireLocations = _cycleHireLocations;
+ favouriteLocations = [cycleHireLocations favouriteLocations];
[self refreshData];
}
return self;
@@ -43,16 +42,10 @@ - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fro
}
-(void) refreshData {
- NSMutableArray *favouritesTableItems = [NSMutableArray arrayWithCapacity:[favouriteLocations count]];
+ [self.items removeAllObjects];
for (CycleHireLocation *location in favouriteLocations) {
- [favouritesTableItems addObject:[self tableItemForLocation:location]];
+ [self.items addObject:[self tableItemForLocation:location]];
}
-
- NSMutableArray *recentlyUsedTableItems = [NSMutableArray arrayWithCapacity:10];
- [recentlyUsedTableItems addObject:[TTTableLongTextItem itemWithText:
- @"Recently used docking stations will appear here after you login to your Cycle Hire account"]];
-
- self.items = [NSArray arrayWithObjects:favouritesTableItems, recentlyUsedTableItems, nil];
}
-(TTTableItem*) tableItemForLocation:(CycleHireLocation*)location {
@@ -82,8 +75,8 @@ - (NSString*)titleForEmpty {
}
- (NSString*)subtitleForEmpty {
- return NSLocalizedString(@"To add a cycle hire location to your favourites, "\
- "tap on the location marker on the map and select 'Add to favourites'", nil);
+ return NSLocalizedString(@"To add a docking station to your favourites, "\
+ "tap on the marker on the map and select 'Add to favourites'", nil);
}
@end
View
18 Classes/FavouritesListViewController.m
@@ -18,6 +18,17 @@ - (id)initWithName:(NSString*)name query:(NSDictionary*)query {
if([[cycleHireLocations favouriteLocations] count] > 0) {
self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
+
+ UISegmentedControl *favTypeSelection = [[UISegmentedControl alloc] init];
+ [favTypeSelection insertSegmentWithTitle:@"Favourites" atIndex:0 animated:NO];
+ [favTypeSelection insertSegmentWithTitle:@"Recent" atIndex:1 animated:NO];
+ favTypeSelection.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+ favTypeSelection.segmentedControlStyle = UISegmentedControlStyleBar;
+ favTypeSelection.frame = CGRectMake(0, 0, 400, 30);
+ favTypeSelection.selectedSegmentIndex = 0;
+ [favTypeSelection addTarget:self action:@selector(favouritesTypeChanged:) forControlEvents:UIControlEventValueChanged];
+
+ self.navigationItem.titleView = favTypeSelection;
self.dataSource = [[[FavouritesListDataSource alloc] initWithCycleHireLocations:cycleHireLocations] autorelease];
self.variableHeightRows = YES;
@@ -45,6 +56,13 @@ - (void)viewWillAppear:(BOOL)animated {
object:nil];
}
+- (void) favouritesTypeChanged:(id)sender {
+ UISegmentedControl *favTypeSelection = (UISegmentedControl *)sender;
+
+ NSLog(@"Selected:%d", favTypeSelection.selectedSegmentIndex);
+ self.editing = NO;
+}
+
- (void) refreshData {
[self.dataSource refreshData];
[self.tableView reloadData];
View
6 CycleHire.xcodeproj/project.pbxproj
@@ -56,6 +56,7 @@
FA93603412130E170057EA41 /* MBProgressHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = FA93603312130E170057EA41 /* MBProgressHUD.m */; };
FA9D2B841222AADB00A97148 /* AccountScraper.m in Sources */ = {isa = PBXBuildFile; fileRef = FA9D2B831222AADB00A97148 /* AccountScraper.m */; };
FA9D2B871222ADEE00A97148 /* JourneyLogEntry.m in Sources */ = {isa = PBXBuildFile; fileRef = FA9D2B861222ADEE00A97148 /* JourneyLogEntry.m */; };
+ FA9D2CD31223105F00A97148 /* RecentDockingStationsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = FA9D2CD21223105F00A97148 /* RecentDockingStationsDataSource.m */; };
FAA1E6FA1157C54F00BC90E2 /* cyclehire.csv in Resources */ = {isa = PBXBuildFile; fileRef = FAA1E6F91157C54F00BC90E2 /* cyclehire.csv */; };
FAA1E82D1159FF3200BC90E2 /* marker-blue-bike-small.png in Resources */ = {isa = PBXBuildFile; fileRef = FAA1E82C1159FF3200BC90E2 /* marker-blue-bike-small.png */; };
FAA1EB17115E73AB00BC90E2 /* Three20.bundle in Resources */ = {isa = PBXBuildFile; fileRef = FAA1EB16115E73AB00BC90E2 /* Three20.bundle */; };
@@ -342,6 +343,8 @@
FA9D2B831222AADB00A97148 /* AccountScraper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AccountScraper.m; path = Classes/AccountScraper.m; sourceTree = "<group>"; };
FA9D2B851222ADEE00A97148 /* JourneyLogEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JourneyLogEntry.h; path = Classes/JourneyLogEntry.h; sourceTree = "<group>"; };
FA9D2B861222ADEE00A97148 /* JourneyLogEntry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JourneyLogEntry.m; path = Classes/JourneyLogEntry.m; sourceTree = "<group>"; };
+ FA9D2CD11223105F00A97148 /* RecentDockingStationsDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RecentDockingStationsDataSource.h; path = Classes/RecentDockingStationsDataSource.h; sourceTree = "<group>"; };
+ FA9D2CD21223105F00A97148 /* RecentDockingStationsDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RecentDockingStationsDataSource.m; path = Classes/RecentDockingStationsDataSource.m; sourceTree = "<group>"; };
FAA1E6F91157C54F00BC90E2 /* cyclehire.csv */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = cyclehire.csv; path = Resources/cyclehire.csv; sourceTree = "<group>"; };
FAA1E82C1159FF3200BC90E2 /* marker-blue-bike-small.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "marker-blue-bike-small.png"; path = "Resources/MarkerImages/marker-blue-bike-small.png"; sourceTree = "<group>"; };
FAA1EB16115E73AB00BC90E2 /* Three20.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = Three20.bundle; path = ../three20/src/Three20.bundle; sourceTree = SOURCE_ROOT; };
@@ -540,6 +543,8 @@
FA22A6D01188A74300FBF741 /* FavouritesListViewController.m */,
FA3077601188DAD000E6D336 /* FavouritesListDataSource.h */,
FA3077611188DAD000E6D336 /* FavouritesListDataSource.m */,
+ FA9D2CD11223105F00A97148 /* RecentDockingStationsDataSource.h */,
+ FA9D2CD21223105F00A97148 /* RecentDockingStationsDataSource.m */,
);
name = "Favourites List View";
sourceTree = "<group>";
@@ -1170,6 +1175,7 @@
FA6E2095121AA4C000AB5E30 /* Reachability.m in Sources */,
FA9D2B841222AADB00A97148 /* AccountScraper.m in Sources */,
FA9D2B871222ADEE00A97148 /* JourneyLogEntry.m in Sources */,
+ FA9D2CD31223105F00A97148 /* RecentDockingStationsDataSource.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

0 comments on commit aab7e9c

Please sign in to comment.
Something went wrong with that request. Please try again.