├── .gitignore ├── 2011 Fall ├── Calculator │ ├── Calculator.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ ├── Calculator │ │ ├── Calculator-Info.plist │ │ ├── Calculator-Prefix.pch │ │ ├── CalculatorAlgorithmRPN.h │ │ ├── CalculatorAlgorithmRPN.m │ │ ├── CalculatorAppDelegate.h │ │ ├── CalculatorAppDelegate.m │ │ ├── CalculatorViewController.h │ │ ├── CalculatorViewController.m │ │ ├── en.lproj │ │ │ ├── InfoPlist.strings │ │ │ └── MainStoryboard.storyboard │ │ └── main.m │ └── Screen Shot 2013-08-27 at 19.03.57.png └── Happiness │ ├── Happiness.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata │ ├── Happiness │ ├── FaceView.h │ ├── FaceView.m │ ├── Happiness-Info.plist │ ├── Happiness-Prefix.pch │ ├── HappinessAppDelegate.h │ ├── HappinessAppDelegate.m │ ├── HappinessViewController.h │ ├── HappinessViewController.m │ ├── en.lproj │ │ ├── InfoPlist.strings │ │ └── MainStoryboard.storyboard │ └── main.m │ └── Screen Shot 2013-08-27 at 19.06.13.png ├── 2013 Winter ├── Attribute │ ├── Attribute.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ └── Attribute │ │ ├── Attribute-Info.plist │ │ ├── Attribute-Prefix.pch │ │ ├── AttributeAppDelegate.h │ │ ├── AttributeAppDelegate.m │ │ ├── AttributeViewController.h │ │ ├── AttributeViewController.m │ │ ├── Default-568h@2x.png │ │ ├── Default.png │ │ ├── Default@2x.png │ │ ├── en.lproj │ │ ├── InfoPlist.strings │ │ └── MainStoryboard.storyboard │ │ └── main.m ├── CardViewer │ ├── CardViewer.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ └── CardViewer │ │ ├── CardChooserAppDelegate.h │ │ ├── CardChooserAppDelegate.m │ │ ├── CardChooserViewController.h │ │ ├── CardChooserViewController.m │ │ ├── CardDisplayViewController.h │ │ ├── CardDisplayViewController.m │ │ ├── CardViewer-Info.plist │ │ ├── CardViewer-Prefix.pch │ │ ├── Default-568h@2x.png │ │ ├── Default.png │ │ ├── Default@2x.png │ │ ├── Face Card Images │ │ ├── J♠.jpg │ │ ├── J♠@2x.jpg │ │ ├── J♣.jpg │ │ ├── J♣@2x.jpg │ │ ├── J♥.jpg │ │ ├── J♥@2x.jpg │ │ ├── J♦.jpg │ │ ├── J♦@2x.jpg │ │ ├── K♠.jpg │ │ ├── K♠@2x.jpg │ │ ├── K♣.jpg │ │ ├── K♣@2x.jpg │ │ ├── K♥.jpg │ │ ├── K♥@2x.jpg │ │ ├── K♦.jpg │ │ ├── K♦@2x.jpg │ │ ├── Q♠.jpg │ │ ├── Q♠@2x.jpg │ │ ├── Q♣.jpg │ │ ├── Q♣@2x.jpg │ │ ├── Q♥.jpg │ │ ├── Q♥@2x.jpg │ │ ├── Q♦.jpg │ │ └── Q♦@2x.jpg │ │ ├── PlayingCardView.h │ │ ├── PlayingCardView.m │ │ ├── cardback.png │ │ ├── en.lproj │ │ ├── InfoPlist.strings │ │ └── MainStoryboard.storyboard │ │ └── main.m ├── Matchismo │ ├── Matchismo Tests │ │ ├── BaseCardTests.m │ │ ├── BaseDeckTests.m │ │ ├── GcovTestObserver.m │ │ ├── Matchismo Tests-Info.plist │ │ ├── Matchismo Tests-Prefix.pch │ │ ├── PlayingCardTests.m │ │ ├── PlayingDeckTests.m │ │ ├── PlayingGameTests.m │ │ ├── SetCardTests.m │ │ ├── SetDeckTests.m │ │ ├── SetGameTests.m │ │ └── en.lproj │ │ │ └── InfoPlist.strings │ ├── Matchismo.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ ├── Matchismo │ │ ├── Abstract.h │ │ ├── CardGameAppDelegate.h │ │ ├── CardGameAppDelegate.m │ │ ├── Components │ │ │ ├── Card.h │ │ │ ├── Card.m │ │ │ ├── Deck.h │ │ │ ├── Deck.m │ │ │ ├── PlayResult.h │ │ │ ├── PlayResult.m │ │ │ ├── PlayingCard.h │ │ │ ├── PlayingCard.m │ │ │ ├── PlayingDeck.h │ │ │ ├── PlayingDeck.m │ │ │ ├── PlayingGame.h │ │ │ ├── PlayingGame.m │ │ │ ├── SetCard.h │ │ │ ├── SetCard.m │ │ │ ├── SetDeck.h │ │ │ ├── SetDeck.m │ │ │ ├── SetGame.h │ │ │ └── SetGame.m │ │ ├── Controllers │ │ │ ├── CardGameViewController.h │ │ │ ├── CardGameViewController.m │ │ │ ├── GameResult.h │ │ │ ├── GameResult.m │ │ │ ├── GameResultViewController.h │ │ │ ├── GameResultViewController.m │ │ │ ├── SetGameViewController.h │ │ │ └── SetGameViewController.m │ │ ├── Debug.xcconfig │ │ ├── Matchismo-Info.plist │ │ ├── Matchismo-Prefix.pch │ │ ├── Resources │ │ │ └── Images.xcassets │ │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ │ ├── LaunchImage.launchimage │ │ │ │ ├── Contents.json │ │ │ │ ├── Default-568h@2x-1.png │ │ │ │ ├── Default-568h@2x.png │ │ │ │ ├── Default.png │ │ │ │ ├── Default@2x-1.png │ │ │ │ └── Default@2x.png │ │ │ │ ├── Tab Bar │ │ │ │ ├── hash.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── hash.png │ │ │ │ ├── set.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── set.png │ │ │ │ └── spade.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── spade.png │ │ │ │ └── cardback.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── cardback.png │ │ │ │ └── cardback@2x.png │ │ ├── Warnings.xcconfig │ │ ├── en.lproj │ │ │ ├── InfoPlist.strings │ │ │ └── MainStoryboard.storyboard │ │ └── main.m │ ├── Screen Shot 2013-08-27 at 18.49.06.png │ ├── Screen Shot 2013-09-25 at 14.11.19.png │ └── TODO.h ├── SPoT │ ├── README.md │ ├── SPoT.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ ├── SPoT │ │ ├── Adapters │ │ │ ├── Controllers │ │ │ │ ├── ImageDetailViewController.h │ │ │ │ ├── ImageDetailViewController.m │ │ │ │ ├── ImageListViewController.h │ │ │ │ ├── ImageListViewController.m │ │ │ │ ├── TabletSplitViewController.h │ │ │ │ ├── TabletSplitViewController.m │ │ │ │ ├── TagListViewController.h │ │ │ │ └── TagListViewController.m │ │ │ └── Gateways │ │ │ │ ├── ImageSupplierFlickr.h │ │ │ │ ├── ImageSupplierFlickr.m │ │ │ │ ├── ImageSupplierGateway.h │ │ │ │ └── ImageSupplierGateway.m │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Entities │ │ │ ├── ImageEntity.h │ │ │ ├── ImageEntity.m │ │ │ ├── ImageFormatURLs.h │ │ │ ├── ImageFormatURLs.m │ │ │ ├── TagEntity.h │ │ │ └── TagEntity.m │ │ ├── Interfaces │ │ │ ├── FlickrFetcher │ │ │ │ ├── FlickrAPIKey.h │ │ │ │ ├── FlickrFetcher.h │ │ │ │ └── FlickrFetcher.m │ │ │ ├── Resources │ │ │ │ └── Images.xcassets │ │ │ │ │ ├── AppIcon.appiconset │ │ │ │ │ └── Contents.json │ │ │ │ │ └── LaunchImage.launchimage │ │ │ │ │ └── Contents.json │ │ │ └── Screens │ │ │ │ ├── iPadPhotoBrowsing.storyboard │ │ │ │ └── iPhonePhotoBrowsing.storyboard │ │ ├── SPoT-Info.plist │ │ ├── SPoT-Prefix.pch │ │ ├── Support │ │ │ ├── Config │ │ │ │ ├── Debug.xcconfig │ │ │ │ └── Warnings.xcconfig │ │ │ └── Helpers │ │ │ │ ├── ArrayCount.h │ │ │ │ └── Helpers.h │ │ ├── Use Cases │ │ │ ├── ImageSupplierDataSource.h │ │ │ ├── ImageViewingInteractor.h │ │ │ ├── ImageViewingInteractor.m │ │ │ ├── TagListingInteractor.h │ │ │ └── TagListingInteractor.m │ │ ├── en.lproj │ │ │ └── InfoPlist.strings │ │ └── main.m │ └── SPoTTests │ │ ├── FlickrFetcherLearningTests.m │ │ ├── SPoTTests-Info.plist │ │ ├── SPoTTests.m │ │ └── en.lproj │ │ └── InfoPlist.strings ├── Shutterbug │ ├── Shutterbug.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ └── Shutterbug │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Default-568h@2x.png │ │ ├── Default.png │ │ ├── Default@2x.png │ │ ├── FlickrFetcher │ │ ├── FlickrAPIKey.h │ │ ├── FlickrFetcher.h │ │ └── FlickrFetcher.m │ │ ├── FlickrPhotoTVC.h │ │ ├── FlickrPhotoTVC.m │ │ ├── HawaiiImageViewController.h │ │ ├── HawaiiImageViewController.m │ │ ├── ImageViewController.h │ │ ├── ImageViewController.m │ │ ├── LatestFlickrPhotosTVC.h │ │ ├── LatestFlickrPhotosTVC.m │ │ ├── Shutterbug-Info.plist │ │ ├── Shutterbug-Prefix.pch │ │ ├── en.lproj │ │ ├── InfoPlist.strings │ │ └── MainStoryboard.storyboard │ │ └── main.m └── SuperCard │ ├── SuperCard.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata │ ├── SuperCard │ ├── Base.lproj │ │ └── Main.storyboard │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Face Cards │ │ │ ├── J♠.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── J♠.png │ │ │ │ └── J♠@2x.png │ │ │ ├── J♣.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── J♣.png │ │ │ │ └── J♣@2x.png │ │ │ ├── J♥.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── J♥.png │ │ │ │ └── J♥@2x.png │ │ │ ├── J♦.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── J♦.png │ │ │ │ └── J♦@2x.png │ │ │ ├── K♠.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── K♠.png │ │ │ │ └── K♠@2x.png │ │ │ ├── K♣.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── K♣.png │ │ │ │ └── K♣@2x.png │ │ │ ├── K♥.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── K♥.png │ │ │ │ └── K♥@2x.png │ │ │ ├── K♦.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── K♦.png │ │ │ │ └── K♦@2x.png │ │ │ ├── Q♠.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── Q♠.png │ │ │ │ └── Q♠@2x.png │ │ │ ├── Q♣.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── Q♣.png │ │ │ │ └── Q♣@2x.png │ │ │ ├── Q♥.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── Q♥.png │ │ │ │ └── Q♥@2x.png │ │ │ └── Q♦.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── Q♦.png │ │ │ │ └── Q♦@2x.png │ │ ├── LaunchImage.launchimage │ │ │ └── Contents.json │ │ └── cardback.imageset │ │ │ ├── Contents.json │ │ │ └── cardback.png │ ├── PlayingCardView.h │ ├── PlayingCardView.m │ ├── SuperCard-Info.plist │ ├── SuperCard-Prefix.pch │ ├── SuperCardAppDelegate.h │ ├── SuperCardAppDelegate.m │ ├── SuperCardViewController.h │ ├── SuperCardViewController.m │ ├── en.lproj │ │ └── InfoPlist.strings │ └── main.m │ └── SuperCardTests │ ├── SuperCardTests-Info.plist │ ├── SuperCardTests.m │ └── en.lproj │ └── InfoPlist.strings └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # https://raw.github.com/github/gitignore/master/Objective-C.gitignore 2 | # Xcode 3 | .DS_Store 4 | */build/* 5 | *.pbxuser 6 | !default.pbxuser 7 | *.mode1v3 8 | !default.mode1v3 9 | *.mode2v3 10 | !default.mode2v3 11 | *.perspectivev3 12 | !default.perspectivev3 13 | xcuserdata 14 | profile 15 | *.moved-aside 16 | DerivedData 17 | .idea/ 18 | *.hmap 19 | *.xccheckout 20 | 21 | #CocoaPods 22 | Pods 23 | -------------------------------------------------------------------------------- /2011 Fall/Calculator/Calculator.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /2011 Fall/Calculator/Calculator/Calculator-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | pt.mindclick.cs193p.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | MainStoryboard 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /2011 Fall/Calculator/Calculator/Calculator-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'Calculator' target in the 'Calculator' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_5_0 8 | #warning "This project uses features only available in iOS SDK 5.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /2011 Fall/Calculator/Calculator/CalculatorAlgorithmRPN.h: -------------------------------------------------------------------------------- 1 | // 2 | // CalculatorAlgorithmRPN.h 3 | // Calculator 4 | // 5 | // Created by Hugo Ferreira on 2012/07/05. 6 | // Copyright (c) 2012 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CalculatorAlgorithmRPN : NSObject 12 | 13 | - (void)pushOperand:(double)operand; 14 | - (void)pushVariable:(NSString *)variable; 15 | - (void)pushOperation:(NSString *)operation; 16 | - (void)clearStack; 17 | - (void)clearTopOfStack; 18 | 19 | @property (readonly) id program; 20 | 21 | + (id)runProgram:(id)program; 22 | + (id)runProgram:(id)program usingVariableValues:(NSDictionary *)variableValues; 23 | + (NSString *)descriptionOfProgram:(id)program; 24 | + (NSSet *)variablesUsedInProgram:(id)program; 25 | + (BOOL)isVariable:(NSString *)element; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /2011 Fall/Calculator/Calculator/CalculatorAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // CalculatorAppDelegate.h 3 | // Calculator 4 | // 5 | // Created by Hugo Ferreira on 2012/07/05. 6 | // Copyright (c) 2012 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CalculatorAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /2011 Fall/Calculator/Calculator/CalculatorAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // CalculatorAppDelegate.m 3 | // Calculator 4 | // 5 | // Created by Hugo Ferreira on 2012/07/05. 6 | // Copyright (c) 2012 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "CalculatorAppDelegate.h" 10 | 11 | @implementation CalculatorAppDelegate 12 | 13 | @synthesize window = _window; 14 | 15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 16 | { 17 | // Override point for customization after application launch. 18 | return YES; 19 | } 20 | 21 | - (void)applicationWillResignActive:(UIApplication *)application 22 | { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | - (void)applicationDidEnterBackground:(UIApplication *)application 28 | { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application 34 | { 35 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 36 | } 37 | 38 | - (void)applicationDidBecomeActive:(UIApplication *)application 39 | { 40 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 41 | } 42 | 43 | - (void)applicationWillTerminate:(UIApplication *)application 44 | { 45 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /2011 Fall/Calculator/Calculator/CalculatorViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CalculatorViewController.h 3 | // Calculator 4 | // 5 | // Created by Hugo Ferreira on 2012/07/05. 6 | // Copyright (c) 2012 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CalculatorViewController : UIViewController 12 | 13 | @property (weak, nonatomic) IBOutlet UILabel *display; 14 | @property (weak, nonatomic) IBOutlet UILabel *history; 15 | @property (weak, nonatomic) IBOutlet UILabel *variables; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /2011 Fall/Calculator/Calculator/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /2011 Fall/Calculator/Calculator/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Calculator 4 | // 5 | // Created by Hugo Ferreira on 2012/07/05. 6 | // Copyright (c) 2012 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "CalculatorAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([CalculatorAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /2011 Fall/Calculator/Screen Shot 2013-08-27 at 19.03.57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2011 Fall/Calculator/Screen Shot 2013-08-27 at 19.03.57.png -------------------------------------------------------------------------------- /2011 Fall/Happiness/Happiness.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /2011 Fall/Happiness/Happiness/FaceView.h: -------------------------------------------------------------------------------- 1 | // 2 | // FaceView.h 3 | // Happiness 4 | // 5 | // Created by Hugo Ferreira on 2012/07/19. 6 | // Copyright (c) 2012 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class FaceView; 12 | 13 | @protocol FaceViewDataSource 14 | 15 | - (float)smileForFaceView:(FaceView *)sender; 16 | 17 | @end 18 | 19 | @interface FaceView : UIView 20 | 21 | @property (nonatomic) CGFloat scale; 22 | @property (nonatomic, weak) IBOutlet id dataSource; 23 | 24 | - (void)pinch:(UIPinchGestureRecognizer *)gesture; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /2011 Fall/Happiness/Happiness/FaceView.m: -------------------------------------------------------------------------------- 1 | // 2 | // FaceView.m 3 | // Happiness 4 | // 5 | // Created by Hugo Ferreira on 2012/07/19. 6 | // Copyright (c) 2012 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "FaceView.h" 10 | 11 | #define FACE_SIZE_FACTOR 0.90 12 | #define EYES_SIZE_FACTOR 0.10 13 | #define EYES_POSITION_H 0.35 14 | #define EYES_POSITION_V 0.35 15 | #define MOUTH_SIZE_FACTOR 0.25 16 | #define MOUTH_POSITION_H 0.45 17 | #define MOUTH_POSITION_V 0.40 18 | 19 | @implementation FaceView 20 | 21 | @synthesize scale = _scale; 22 | @synthesize dataSource = _dataSource; 23 | 24 | - (CGFloat)scale 25 | { 26 | if (!_scale) { 27 | return FACE_SIZE_FACTOR; 28 | } else { 29 | return _scale; 30 | } 31 | } 32 | 33 | - (void)setScale:(CGFloat)scale 34 | { 35 | if (_scale != scale) { 36 | _scale = scale; 37 | [self setNeedsDisplay]; 38 | } 39 | } 40 | 41 | - (void)pinch:(UIPinchGestureRecognizer *)gesture 42 | { 43 | if (gesture.state == UIGestureRecognizerStateChanged 44 | || gesture.scale == UIGestureRecognizerStateEnded) 45 | { 46 | self.scale *= gesture.scale; 47 | gesture.scale = 1.0; 48 | } 49 | } 50 | 51 | - (void)setup 52 | { 53 | self.contentMode = UIViewContentModeRedraw; 54 | } 55 | 56 | - (void)awakeFromNib 57 | { 58 | [self setup]; 59 | } 60 | 61 | - (id)initWithFrame:(CGRect)frame 62 | { 63 | self = [super initWithFrame:frame]; 64 | if (self) { 65 | [self setup]; 66 | } 67 | return self; 68 | } 69 | 70 | - (void)drawCircleAtPoint:(CGPoint)center withRadius:(CGFloat)radius inContext:(CGContextRef) context 71 | { 72 | UIGraphicsPushContext(context); 73 | CGContextBeginPath(context); 74 | CGContextAddArc(context, center.x, center.y, radius, 0, 2 * M_PI, YES); 75 | CGContextStrokePath(context); 76 | UIGraphicsPopContext(); 77 | } 78 | 79 | - (void)drawRect:(CGRect)rect 80 | { 81 | CGContextRef context = UIGraphicsGetCurrentContext(); 82 | 83 | // 84 | // Face... 85 | // 86 | CGPoint midPoint; 87 | midPoint.x = self.bounds.origin.x + self.bounds.size.width / 2; 88 | midPoint.y = self.bounds.origin.y + self.bounds.size.height / 2; 89 | 90 | CGFloat size = ((self.bounds.size.width < self.bounds.size.height)? self.bounds.size.width : self.bounds.size.height) / 2; 91 | size *= self.scale; 92 | 93 | CGContextSetLineWidth(context, 5.0); 94 | [[UIColor blueColor] setStroke]; 95 | [self drawCircleAtPoint:midPoint withRadius:size inContext:context]; 96 | 97 | // 98 | // Eyes... 99 | // 100 | CGPoint eyePoint; 101 | eyePoint.x = midPoint.x - size * EYES_POSITION_H; 102 | eyePoint.y = midPoint.y - size * EYES_POSITION_V; 103 | [self drawCircleAtPoint:eyePoint withRadius:size * EYES_SIZE_FACTOR inContext:context]; 104 | 105 | eyePoint.x = midPoint.x + size * EYES_POSITION_H; 106 | [self drawCircleAtPoint:eyePoint withRadius:size * EYES_SIZE_FACTOR inContext:context]; 107 | 108 | // 109 | // Mouth... 110 | // 111 | CGPoint mouthStart; 112 | mouthStart.x = midPoint.x - size * MOUTH_POSITION_H; 113 | mouthStart.y = midPoint.y + size * MOUTH_POSITION_V; 114 | CGPoint mouthStop = mouthStart; 115 | CGPoint mouthCP1 = mouthStart; 116 | CGPoint mouthCP2 = mouthStart; 117 | mouthStop.x = midPoint.x + size * MOUTH_POSITION_H; 118 | mouthCP1.x = midPoint.x - size * MOUTH_POSITION_H / 3; 119 | mouthCP2.x = midPoint.x + size * MOUTH_POSITION_H / 3; 120 | 121 | // Direction: Happy or Smile? 122 | float smileDirection = [self.dataSource smileForFaceView:self]; 123 | if (smileDirection <= -1) smileDirection = -1; 124 | if (smileDirection >= 1) smileDirection = 1; 125 | 126 | CGFloat smileOffset = size * MOUTH_SIZE_FACTOR * smileDirection; 127 | mouthCP1.y += smileOffset; 128 | mouthCP2.y += smileOffset; 129 | 130 | CGContextBeginPath(context); 131 | CGContextMoveToPoint(context, mouthStart.x, mouthStart.y); 132 | CGContextAddCurveToPoint(context, mouthCP1.x, mouthCP1.y, mouthCP2.x, mouthCP2.y, mouthStop.x, mouthStop.y); 133 | CGContextStrokePath(context); 134 | } 135 | 136 | @end 137 | -------------------------------------------------------------------------------- /2011 Fall/Happiness/Happiness/Happiness-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | pt.mindclick.cs193p.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | MainStoryboard 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /2011 Fall/Happiness/Happiness/Happiness-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'Happiness' target in the 'Happiness' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_5_0 8 | #warning "This project uses features only available in iOS SDK 5.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /2011 Fall/Happiness/Happiness/HappinessAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // HappinessAppDelegate.h 3 | // Happiness 4 | // 5 | // Created by Hugo Ferreira on 2012/07/19. 6 | // Copyright (c) 2012 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface HappinessAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /2011 Fall/Happiness/Happiness/HappinessAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // HappinessAppDelegate.m 3 | // Happiness 4 | // 5 | // Created by Hugo Ferreira on 2012/07/19. 6 | // Copyright (c) 2012 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "HappinessAppDelegate.h" 10 | 11 | @implementation HappinessAppDelegate 12 | 13 | @synthesize window = _window; 14 | 15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 16 | { 17 | // Override point for customization after application launch. 18 | return YES; 19 | } 20 | 21 | - (void)applicationWillResignActive:(UIApplication *)application 22 | { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | - (void)applicationDidEnterBackground:(UIApplication *)application 28 | { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application 34 | { 35 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 36 | } 37 | 38 | - (void)applicationDidBecomeActive:(UIApplication *)application 39 | { 40 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 41 | } 42 | 43 | - (void)applicationWillTerminate:(UIApplication *)application 44 | { 45 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /2011 Fall/Happiness/Happiness/HappinessViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // HappinessViewController.h 3 | // Happiness 4 | // 5 | // Created by Hugo Ferreira on 2012/07/19. 6 | // Copyright (c) 2012 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface HappinessViewController : UIViewController 12 | 13 | @property (nonatomic) int happiness; // [sad] 0..100 [happy] 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /2011 Fall/Happiness/Happiness/HappinessViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // HappinessViewController.m 3 | // Happiness 4 | // 5 | // Created by Hugo Ferreira on 2012/07/19. 6 | // Copyright (c) 2012 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "HappinessViewController.h" 10 | #import "FaceView.h" 11 | 12 | @interface HappinessViewController () 13 | 14 | @property (nonatomic, weak) IBOutlet FaceView *faceView; 15 | 16 | @end 17 | 18 | @implementation HappinessViewController 19 | 20 | @synthesize happiness = _happiness; 21 | @synthesize faceView = _faceView; 22 | 23 | - (void)setHappiness:(int)happiness 24 | { 25 | _happiness = happiness; 26 | [self.faceView setNeedsDisplay]; 27 | } 28 | 29 | #pragma mark - XPTO 30 | 31 | // TODO xpto 32 | 33 | - (void)setFaceView:(FaceView *)faceView 34 | { 35 | _faceView = faceView; 36 | [self.faceView addGestureRecognizer:[[UIPinchGestureRecognizer alloc] initWithTarget:faceView action:@selector(pinch:)]]; 37 | [self.faceView addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleHappiness:)]]; 38 | self.faceView.dataSource = self; 39 | } 40 | 41 | - (void)handleHappiness:(UIPanGestureRecognizer *)gesture 42 | { 43 | if (gesture.state == UIGestureRecognizerStateChanged 44 | || gesture.state == UIGestureRecognizerStateEnded) 45 | { 46 | CGPoint translation = [gesture translationInView:self.faceView]; 47 | self.happiness -= translation.y / 2; 48 | [gesture setTranslation:CGPointZero inView:self.faceView]; 49 | } 50 | } 51 | 52 | - (float)smileForFaceView:(FaceView *)sender 53 | { 54 | return (self.happiness - 50) / 50.0; 55 | } 56 | 57 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation 58 | { 59 | return YES; 60 | } 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /2011 Fall/Happiness/Happiness/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /2011 Fall/Happiness/Happiness/en.lproj/MainStoryboard.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /2011 Fall/Happiness/Happiness/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Happiness 4 | // 5 | // Created by Hugo Ferreira on 2012/07/19. 6 | // Copyright (c) 2012 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "HappinessAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([HappinessAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /2011 Fall/Happiness/Screen Shot 2013-08-27 at 19.06.13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2011 Fall/Happiness/Screen Shot 2013-08-27 at 19.06.13.png -------------------------------------------------------------------------------- /2013 Winter/Attribute/Attribute.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /2013 Winter/Attribute/Attribute/Attribute-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | edu.stanford.cs193p.instructor.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | MainStoryboard 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /2013 Winter/Attribute/Attribute/Attribute-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'Attribute' target in the 'Attribute' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_5_0 8 | #warning "This project uses features only available in iOS SDK 5.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /2013 Winter/Attribute/Attribute/AttributeAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AttributeAppDelegate.h 3 | // Attribute 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AttributeAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /2013 Winter/Attribute/Attribute/AttributeAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AttributeAppDelegate.m 3 | // Attribute 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import "AttributeAppDelegate.h" 10 | 11 | @implementation AttributeAppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application 32 | { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application 37 | { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application 42 | { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /2013 Winter/Attribute/Attribute/AttributeViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AttributeViewController.h 3 | // Attribute 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AttributeViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /2013 Winter/Attribute/Attribute/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/Attribute/Attribute/Default-568h@2x.png -------------------------------------------------------------------------------- /2013 Winter/Attribute/Attribute/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/Attribute/Attribute/Default.png -------------------------------------------------------------------------------- /2013 Winter/Attribute/Attribute/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/Attribute/Attribute/Default@2x.png -------------------------------------------------------------------------------- /2013 Winter/Attribute/Attribute/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /2013 Winter/Attribute/Attribute/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Attribute 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AttributeAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AttributeAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/CardChooserAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // CardChooserAppDelegate.h 3 | // CardViewer 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CardChooserAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/CardChooserAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // CardChooserAppDelegate.m 3 | // CardViewer 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import "CardChooserAppDelegate.h" 10 | 11 | @implementation CardChooserAppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application 32 | { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application 37 | { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application 42 | { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/CardChooserViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CardChooserViewController.h 3 | // CardViewer 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CardChooserViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/CardChooserViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CardChooserViewController.m 3 | // CardViewer 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import "CardChooserViewController.h" 10 | #import "CardDisplayViewController.h" 11 | 12 | @interface CardChooserViewController () 13 | @property (weak, nonatomic) IBOutlet UILabel *rankLabel; 14 | @property (weak, nonatomic) IBOutlet UISegmentedControl *suitSegmentedControl; 15 | @property (nonatomic) NSUInteger rank; 16 | @property (nonatomic, readonly) NSString *suit; 17 | @end 18 | 19 | @implementation CardChooserViewController 20 | 21 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 22 | { 23 | if ([segue.identifier isEqualToString:@"ShowCard"]) { 24 | if ([segue.destinationViewController isKindOfClass:[CardDisplayViewController class]]) { 25 | CardDisplayViewController *cdvc = (CardDisplayViewController *)segue.destinationViewController; 26 | cdvc.suit = self.suit; 27 | cdvc.rank = self.rank; 28 | cdvc.title = [[self rankAsString] stringByAppendingString:self.suit]; 29 | } 30 | } 31 | } 32 | 33 | - (NSString *)rankAsString 34 | { 35 | return @[@"?",@"A",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"10",@"J",@"Q",@"K"][self.rank]; 36 | } 37 | 38 | - (void)setRank:(NSUInteger)rank 39 | { 40 | _rank = rank; 41 | self.rankLabel.text = [self rankAsString]; 42 | } 43 | 44 | - (NSString *)suit 45 | { 46 | return [self.suitSegmentedControl titleForSegmentAtIndex:self.suitSegmentedControl.selectedSegmentIndex]; 47 | } 48 | 49 | - (IBAction)changeRank:(UISlider *)sender 50 | { 51 | self.rank = round(sender.value); 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/CardDisplayViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CardDisplayViewController.h 3 | // CardViewer 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CardDisplayViewController : UIViewController 12 | 13 | @property (nonatomic) NSUInteger rank; 14 | @property (nonatomic, strong) NSString *suit; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/CardDisplayViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CardDisplayViewController.m 3 | // CardViewer 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import "CardDisplayViewController.h" 10 | #import "PlayingCardView.h" 11 | 12 | @interface CardDisplayViewController () 13 | @property (weak, nonatomic) IBOutlet PlayingCardView *playingCardView; 14 | @end 15 | 16 | @implementation CardDisplayViewController 17 | 18 | - (void)viewWillAppear:(BOOL)animated 19 | { 20 | [super viewWillAppear:animated]; 21 | self.playingCardView.rank = self.rank; 22 | self.playingCardView.suit = self.suit; 23 | self.playingCardView.faceUp = YES; 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/CardViewer-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | edu.stanford.cs193p.instructor.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | MainStoryboard 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/CardViewer-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'CardViewer' target in the 'CardViewer' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_5_0 8 | #warning "This project uses features only available in iOS SDK 5.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Default-568h@2x.png -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Default.png -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Default@2x.png -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/J♠.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/J♠.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/J♠@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/J♠@2x.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/J♣.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/J♣.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/J♣@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/J♣@2x.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/J♥.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/J♥.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/J♥@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/J♥@2x.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/J♦.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/J♦.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/J♦@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/J♦@2x.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/K♠.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/K♠.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/K♠@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/K♠@2x.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/K♣.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/K♣.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/K♣@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/K♣@2x.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/K♥.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/K♥.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/K♥@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/K♥@2x.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/K♦.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/K♦.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/K♦@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/K♦@2x.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/Q♠.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/Q♠.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/Q♠@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/Q♠@2x.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/Q♣.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/Q♣.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/Q♣@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/Q♣@2x.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/Q♥.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/Q♥.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/Q♥@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/Q♥@2x.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/Q♦.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/Q♦.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/Face Card Images/Q♦@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/Face Card Images/Q♦@2x.jpg -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/PlayingCardView.h: -------------------------------------------------------------------------------- 1 | // 2 | // PlayingCardView.h 3 | // SuperCard 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PlayingCardView : UIView 12 | 13 | @property (nonatomic) NSUInteger rank; 14 | @property (strong, nonatomic) NSString *suit; 15 | 16 | @property (nonatomic) BOOL faceUp; 17 | 18 | - (void)pinch:(UIPinchGestureRecognizer *)gesture; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/cardback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/CardViewer/CardViewer/cardback.png -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /2013 Winter/CardViewer/CardViewer/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // CardViewer 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "CardChooserAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([CardChooserAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo Tests/BaseCardTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseCardTests.m 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/10/17. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "Card.h" 11 | 12 | #pragma mark - Test Support 13 | 14 | @interface BaseCardTests_CardSubclass : Card 15 | @end 16 | 17 | @implementation BaseCardTests_CardSubclass 18 | @end 19 | 20 | #pragma mark - Test Suite 21 | 22 | 23 | @interface BaseCardTests : XCTestCase 24 | 25 | @end 26 | 27 | @implementation BaseCardTests 28 | 29 | - (void)testCannotInstantiateBaseClass 30 | { 31 | XCTAssertThrows([[Card alloc] init]); 32 | } 33 | 34 | - (void)testCannotInvokeAbstractMethods 35 | { 36 | BaseCardTests_CardSubclass *card = [[BaseCardTests_CardSubclass alloc] init]; 37 | XCTAssertThrows([card match:@[]]); 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo Tests/BaseDeckTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseDeckTests.m 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/10/17. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "Deck.h" 11 | #import "Card.h" 12 | 13 | #pragma mark - Test Support 14 | 15 | @interface BaseDeckTests_CardSubclass : Card 16 | @end 17 | 18 | @implementation BaseDeckTests_CardSubclass 19 | @end 20 | 21 | #pragma mark - 22 | 23 | @interface Deck (Tests) 24 | - (NSMutableArray *)cards; 25 | @end 26 | 27 | #pragma mark - Test Suite 28 | 29 | @interface BaseDeckTests : XCTestCase 30 | 31 | @end 32 | 33 | @implementation BaseDeckTests 34 | 35 | #pragma mark - Helpers 36 | 37 | - (void)createCards:(NSUInteger)howMany inDeck:(Deck *)deck 38 | { 39 | for (NSUInteger i = 0; i < howMany; i++) { 40 | Card *card = [[BaseDeckTests_CardSubclass alloc] init]; 41 | [deck addCard:card atTop:NO]; 42 | } 43 | } 44 | 45 | - (void)drawAllCardsInDeck:(Deck *)deck 46 | { 47 | NSUInteger numberOfCards = [deck.cards count]; 48 | for (NSUInteger i = 0; i < numberOfCards; i++) { 49 | [deck drawRandomCard]; 50 | } 51 | } 52 | 53 | #pragma mark - Test Cases 54 | 55 | - (void)testCardsCanBeAdddedAtBothEnds 56 | { 57 | Card *cardBottom = [[BaseDeckTests_CardSubclass alloc] init]; 58 | Card *cardTop = [[BaseDeckTests_CardSubclass alloc] init]; 59 | Deck *deck = [[Deck alloc] init]; 60 | [self createCards:10 inDeck:deck]; 61 | 62 | [deck addCard:cardBottom atTop:NO]; 63 | [deck addCard:cardTop atTop:YES]; 64 | NSUInteger lastCardIndex = [deck.cards count]-1; 65 | XCTAssert(cardBottom == deck.cards[lastCardIndex], @"Bottom card must be the last one"); 66 | XCTAssert(cardTop == deck.cards[0], @"Top card must be the first one"); 67 | } 68 | 69 | - (void)testDrawCardsFromEmptyDeckDoesntCrash 70 | { 71 | Card *drawCard; 72 | Deck *emptyDeck = [[Deck alloc] init]; 73 | 74 | XCTAssertNoThrow(drawCard = [emptyDeck drawRandomCard]); 75 | XCTAssertNil(drawCard); 76 | } 77 | 78 | - (void)testCanDrawFromSingleCardDeck 79 | { 80 | Card *drawCard; 81 | Deck *singleCardDeck = [[Deck alloc] init]; 82 | [self createCards:1 inDeck:singleCardDeck]; 83 | 84 | XCTAssertNoThrow(drawCard = [singleCardDeck drawRandomCard]); 85 | XCTAssertNotNil(drawCard); 86 | BOOL deckIsEmpty = ![singleCardDeck.cards count]; 87 | XCTAssertTrue(deckIsEmpty); 88 | } 89 | 90 | - (void)testCannotDrawMoreCardsThanExistInDeck 91 | { 92 | Card *drawCard; 93 | Deck *manyCardsDeck = [[Deck alloc] init]; 94 | [self createCards:2 inDeck:manyCardsDeck]; 95 | 96 | XCTAssertNoThrow([self drawAllCardsInDeck:manyCardsDeck]); 97 | XCTAssertNoThrow(drawCard = [manyCardsDeck drawRandomCard]); 98 | XCTAssertNil(drawCard); 99 | } 100 | 101 | @end 102 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo Tests/GcovTestObserver.m: -------------------------------------------------------------------------------- 1 | // 2 | // GcovTestObserver.m 3 | // 4 | // Workaround for XCode 5 bug where __gcov_flush is not called properly when test coverage flags are set. 5 | // http://stackoverflow.com/questions/19136767/generate-gcda-files-with-xcode5-ios7-simulator-and-xctest 6 | // 7 | 8 | #import 9 | 10 | @interface GcovTestObserver : XCTestObserver 11 | @end 12 | 13 | @implementation GcovTestObserver 14 | 15 | - (void) stopObserving 16 | { 17 | [super stopObserving]; 18 | UIApplication* application = [UIApplication sharedApplication]; 19 | [application.delegate applicationWillTerminate:application]; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo Tests/Matchismo Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | pt.mindclick.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo Tests/Matchismo Tests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #import 10 | #endif 11 | 12 | // Custom definitions 13 | #import "Abstract.h" 14 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo Tests/PlayingDeckTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // PlayingDeckTests.m 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/10/17. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "PlayingDeck.h" 11 | #import "PlayingCard.h" 12 | 13 | #pragma mark - Test Support 14 | 15 | @interface PlayingDeck (Tests) 16 | - (NSMutableArray *)cards; 17 | @end 18 | 19 | #pragma mark - Test Suite 20 | 21 | @interface PlayingDeckTests : XCTestCase 22 | 23 | @end 24 | 25 | @implementation PlayingDeckTests 26 | 27 | - (void)testFullDeckStartsWithAllTheCards 28 | { 29 | PlayingDeck *fullDeck = [[PlayingDeck alloc] init]; 30 | NSUInteger cardsInDeck = [fullDeck.cards count]; 31 | NSUInteger totalSuits = [[PlayingCard validSuits] count]; 32 | NSUInteger totalRanks = [PlayingCard maxRank]; 33 | XCTAssertEqual(cardsInDeck, totalSuits * totalRanks); 34 | } 35 | 36 | - (void) testDeckDoesNotContainDuplicateCards 37 | { 38 | PlayingDeck *fullDeck = [[PlayingDeck alloc] init]; 39 | NSUInteger cardsInDeck = [fullDeck.cards count]; 40 | NSUInteger uniqueCards = [[NSSet setWithArray:fullDeck.cards] count]; 41 | XCTAssertEqual(cardsInDeck, uniqueCards); 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo Tests/SetDeckTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // SetDeckTests.m 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/10/17. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SetDeck.h" 11 | #import "SetCard.h" 12 | 13 | #pragma mark - Test Support 14 | 15 | @interface SetDeck (Tests) 16 | - (NSMutableArray *)cards; 17 | @end 18 | 19 | #pragma mark - Test Suite 20 | 21 | @interface SetDeckTests : XCTestCase 22 | 23 | @end 24 | 25 | @implementation SetDeckTests 26 | 27 | - (void)testFullDeckStartsWithAllTheCards 28 | { 29 | SetDeck *fullDeck = [[SetDeck alloc] init]; 30 | NSUInteger cardsInDeck = [fullDeck.cards count]; 31 | NSUInteger totalNumbers = 3; 32 | NSUInteger totalSymbols = [[SetCard validSymbols] count]; 33 | NSUInteger totalShadings = SET_CARD_SHADING_TYPE_COUNT; 34 | NSUInteger totalColors = SET_CARD_COLOR_TYPE_COUNT; 35 | XCTAssertEqual(cardsInDeck, totalNumbers * totalSymbols * totalShadings * totalColors); 36 | } 37 | 38 | - (void) testDeckDoesNotContainDuplicateCards 39 | { 40 | SetDeck *fullDeck = [[SetDeck alloc] init]; 41 | NSUInteger cardsInDeck = [fullDeck.cards count]; 42 | NSUInteger uniqueCards = [[NSSet setWithArray:fullDeck.cards] count]; 43 | XCTAssertEqual(cardsInDeck, uniqueCards); 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo Tests/SetGameTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // SetGameTests.m 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/10/23. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SetGame.h" 11 | 12 | @interface SetGameTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation SetGameTests 17 | 18 | // TODO: add tests for the Set game 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo Tests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Abstract.h: -------------------------------------------------------------------------------- 1 | /** 2 | Since Objective-C does not have real abstract classes, a common idiom is to raise an exception 3 | form the abstract class in case the subclass forgets to override/implement the method. 4 | 5 | Default behaviour in Cocoa (e.g. NSFormatter): 6 | 7 | *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 8 | '*** -stringForObjectValue: only defined for abstract class. Define -[MyFormatter stringForObjectValue:]!' 9 | 10 | References and inspiration: 11 | - https://github.com/stevegeek/cocotron/blob/master/Foundation/NSException/NSRaise.h 12 | - http://xcodeit.net/blog/abstract-classes-and-objective-c.html 13 | - http://stackoverflow.com/questions/1034373/creating-an-abstract-class-in-objective-c 14 | - https://developer.apple.com/library/ios/qa/qa1669/ 15 | */ 16 | 17 | /* 18 | *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 19 | '-instanceMethod only defined for abstract class. Define -[MySubclass instanceMethod]! (in MDKExceptionsTest.m:76)' 20 | or, 21 | '+classMethod only defined for abstract class. Define +[MySubclass classMethod]! (in MDKExceptionsTest.m:44)' 22 | */ 23 | static inline void _MDKInvalidAbstractInvocation(SEL selector, id object, const char *func, const char *file, int line) { 24 | char sign = func[0]; 25 | const char *method = sel_getName(selector); 26 | NSString *fileName = [[NSString stringWithUTF8String:file] lastPathComponent]; 27 | NSString *message = [NSString stringWithFormat:@"%c%s only defined for abstract class. Define %c[%@ %s]! (in %@:%d)", 28 | sign, method, sign, [object class], method, fileName, line]; 29 | @throw [NSException exceptionWithName:NSInvalidArgumentException reason:message userInfo:nil]; 30 | } 31 | #define RaiseInvalidAbstractInvocation() _MDKInvalidAbstractInvocation(_cmd, self, __func__, __FILE__, __LINE__) 32 | 33 | /* 34 | *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 35 | '-[MyAbstract init] cannot instantiate abstract class directly. Use a subclass instead! (in MDKExceptionsTest.m:25)' 36 | */ 37 | static inline void _MDKInvalidAbstractInstantiationForClass(Class abstract, id object, const char *func, const char *file, int line) { 38 | if ([object class] == abstract) { 39 | NSString *fileName = [[NSString stringWithUTF8String:file] lastPathComponent]; 40 | NSString *message = [NSString stringWithFormat:@"%s cannot instantiate abstract class directly. Use a subclass instead! (in %@:%d)", 41 | func, fileName, line]; 42 | @throw [NSException exceptionWithName:NSInvalidArgumentException reason:message userInfo:nil]; 43 | } 44 | } 45 | #define RaiseInvalidAbstractInstantiationForClass(CLASS) _MDKInvalidAbstractInstantiationForClass(CLASS, self, __func__, __FILE__, __LINE__) 46 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/CardGameAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // CardGameAppDelegate.h 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/07/22. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CardGameAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/CardGameAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // CardGameAppDelegate.m 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/07/22. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "CardGameAppDelegate.h" 10 | 11 | @implementation CardGameAppDelegate 12 | 13 | // http://stackoverflow.com/questions/19136767/generate-gcda-files-with-xcode5-ios7-simulator-and-xctest 14 | #ifdef DEBUG 15 | + (void)initialize { 16 | [[NSUserDefaults standardUserDefaults] setValue:@"XCTestLog,GcovTestObserver" 17 | forKey:@"XCTestObserverClass"]; 18 | } 19 | #endif 20 | 21 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 22 | { 23 | // Override point for customization after application launch. 24 | return YES; 25 | } 26 | 27 | - (void)applicationWillResignActive:(UIApplication *)application 28 | { 29 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 30 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 31 | } 32 | 33 | - (void)applicationDidEnterBackground:(UIApplication *)application 34 | { 35 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 36 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 37 | } 38 | 39 | - (void)applicationWillEnterForeground:(UIApplication *)application 40 | { 41 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 42 | } 43 | 44 | - (void)applicationDidBecomeActive:(UIApplication *)application 45 | { 46 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 47 | } 48 | 49 | - (void)applicationWillTerminate:(UIApplication *)application 50 | { 51 | #ifdef DEBUG 52 | extern void __gcov_flush(void); 53 | __gcov_flush(); 54 | #endif 55 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Components/Card.h: -------------------------------------------------------------------------------- 1 | // 2 | // Card.h 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/07/24. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** Abstract class. */ 12 | @interface Card : NSObject 13 | 14 | ///-------------------------------------------------------------------------------- 15 | /// @name Methods to Implement in a Subclass 16 | ///-------------------------------------------------------------------------------- 17 | 18 | - (int)match:(NSArray *)otherCards; 19 | 20 | ///-------------------------------------------------------------------------------- 21 | /// @name Card Information 22 | ///-------------------------------------------------------------------------------- 23 | 24 | @property (strong, nonatomic) NSString *contents; 25 | @property (nonatomic, getter = isFaceUp) BOOL faceup; 26 | @property (nonatomic, getter = isUnplayable) BOOL unplayable; 27 | - (NSString *)description; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Components/Card.m: -------------------------------------------------------------------------------- 1 | // 2 | // Card.m 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/07/24. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "Card.h" 10 | 11 | @implementation Card 12 | 13 | #pragma mark - Abstract 14 | 15 | - (int)match:(NSArray *)otherCards 16 | { 17 | RaiseInvalidAbstractInvocation(); 18 | return 0; 19 | } 20 | 21 | #pragma mark - Initialization 22 | 23 | - (id)init 24 | { 25 | RaiseInvalidAbstractInstantiationForClass([Card class]); 26 | self = [super init]; 27 | return self; 28 | } 29 | 30 | #pragma mark - Methods 31 | 32 | - (NSString *)description 33 | { 34 | return self.contents; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Components/Deck.h: -------------------------------------------------------------------------------- 1 | // 2 | // Deck.h 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/07/24. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "Card.h" 11 | 12 | @interface Deck : NSObject 13 | 14 | - (void)addCard:(Card *)card atTop:(BOOL)yn; 15 | - (Card *)drawRandomCard; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Components/Deck.m: -------------------------------------------------------------------------------- 1 | // 2 | // Deck.m 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/07/24. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "Deck.h" 10 | 11 | @interface Deck() 12 | @property (strong, nonatomic) NSMutableArray *cards; // of Card 13 | @end 14 | 15 | @implementation Deck 16 | 17 | - (NSMutableArray *)cards 18 | { 19 | if (!_cards) _cards = [[NSMutableArray alloc] init]; 20 | return _cards; 21 | } 22 | 23 | - (void)addCard:(Card *)card atTop:(BOOL)atTop 24 | { 25 | if (atTop) { 26 | [self.cards insertObject:card atIndex:0]; 27 | } else { 28 | [self.cards addObject:card]; 29 | } 30 | } 31 | 32 | - (Card *)drawRandomCard 33 | { 34 | Card *randomCard; 35 | 36 | if ([self.cards count]) { 37 | unsigned index = arc4random() % [self.cards count]; 38 | randomCard = self.cards[index]; 39 | [self.cards removeObjectAtIndex:index]; 40 | } 41 | 42 | return randomCard; 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Components/PlayResult.h: -------------------------------------------------------------------------------- 1 | // 2 | // PlayResult.h 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/09/24. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSUInteger, PlayStatus) { 12 | PlayStatusCardFlipped, 13 | PlayStatusCardsMatch, 14 | PlayStatusCardsMismatch, 15 | }; 16 | 17 | @interface PlayResult : NSObject 18 | 19 | ///-------------------------------------------------------------------------------- 20 | /// @name Initializing a Result 21 | ///-------------------------------------------------------------------------------- 22 | 23 | /** Designated initializer. */ 24 | - (id)initWithCards:(NSArray *)cards outcome:(PlayStatus)result score:(int)point; 25 | 26 | 27 | ///-------------------------------------------------------------------------------- 28 | /// @name Retrieving Result Information 29 | ///-------------------------------------------------------------------------------- 30 | 31 | @property (nonatomic, strong, readonly) NSArray *cards; // of Card 32 | @property (nonatomic, readonly) PlayStatus outcome; 33 | @property (nonatomic, readonly) NSInteger score; 34 | 35 | - (NSString *)description; 36 | 37 | - (NSString *)outcomeString; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Components/PlayResult.m: -------------------------------------------------------------------------------- 1 | // 2 | // PlayResult.m 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/09/24. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "PlayResult.h" 10 | 11 | @implementation PlayResult 12 | 13 | #pragma mark - Initializers 14 | 15 | - (id)initWithCards:(NSArray *)cards outcome:(PlayStatus)result score:(int)points 16 | { 17 | self = [super init]; 18 | if (self) { 19 | _cards = cards; 20 | _outcome = result; 21 | _score = points; 22 | } 23 | return self; 24 | } 25 | 26 | - (id)init 27 | { 28 | return [self initWithCards:nil outcome:0 score:0]; 29 | } 30 | 31 | #pragma mark - Methods 32 | 33 | - (NSString *)outcomeString 34 | { 35 | NSString *translation = @""; 36 | switch (self.outcome) { 37 | case PlayStatusCardFlipped: translation = @"Flipped"; break; 38 | case PlayStatusCardsMatch: translation = @"Matched"; break; 39 | case PlayStatusCardsMismatch: translation = @"Didn't match"; break; 40 | } 41 | return translation; 42 | } 43 | 44 | #pragma mark - NSObject 45 | 46 | - (NSString *)description 47 | { 48 | NSString *cardNames = [self.cards componentsJoinedByString:@" "]; 49 | return [NSString stringWithFormat:@"%@ %@ (%+d)", [self outcomeString], cardNames, self.score]; 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Components/PlayingCard.h: -------------------------------------------------------------------------------- 1 | // 2 | // PlayingCard.h 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/07/24. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "Card.h" 11 | 12 | extern NSString * const PlayingCardSymbolHearts; 13 | extern NSString * const PlayingCardSymbolDiamonds; 14 | extern NSString * const PlayingCardSymbolSpades; 15 | extern NSString * const PlayingCardSymbolClubs; 16 | 17 | @interface PlayingCard : Card 18 | 19 | @property (strong, nonatomic) NSString *suit; 20 | @property (nonatomic) NSUInteger rank; 21 | 22 | + (NSArray *)validSuits; 23 | + (NSUInteger)maxRank; 24 | 25 | @end 26 | 27 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Components/PlayingCard.m: -------------------------------------------------------------------------------- 1 | // 2 | // PlayingCard.m 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/07/24. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "PlayingCard.h" 10 | 11 | NSString * const PlayingCardSymbolHearts = @"♥"; 12 | NSString * const PlayingCardSymbolDiamonds = @"♦"; 13 | NSString * const PlayingCardSymbolSpades = @"♠"; 14 | NSString * const PlayingCardSymbolClubs = @"♣"; 15 | 16 | @implementation PlayingCard 17 | 18 | #pragma mark - Class 19 | 20 | + (NSArray *)validSuits 21 | { 22 | static NSArray *suits = nil; 23 | if (!suits) suits = @[PlayingCardSymbolHearts, 24 | PlayingCardSymbolDiamonds, 25 | PlayingCardSymbolSpades, 26 | PlayingCardSymbolClubs]; 27 | return suits; 28 | } 29 | 30 | + (NSArray *)validRanks 31 | { 32 | static NSArray *ranks = nil; 33 | if (!ranks) ranks = @[@"?", @"A", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @"10", @"J", @"Q", @"K"]; 34 | return ranks; 35 | } 36 | 37 | + (NSUInteger)maxRank 38 | { 39 | return [[self validRanks] count] - 1; 40 | } 41 | 42 | #pragma mark - Properties 43 | 44 | @synthesize suit = _suit; 45 | 46 | - (NSString *)suit 47 | { 48 | return (_suit)? _suit : @"Ø"; 49 | } 50 | 51 | - (void)setSuit:(NSString *)suit 52 | { 53 | if ([[PlayingCard validSuits] containsObject:suit]) { 54 | _suit = suit; 55 | } 56 | } 57 | 58 | - (void)setRank:(NSUInteger)rank { 59 | if (rank <= [PlayingCard maxRank]) { 60 | _rank = rank; 61 | } 62 | } 63 | 64 | #pragma mark - Methods 65 | 66 | - (NSString *)contents 67 | { 68 | NSArray *ranks = [PlayingCard validRanks]; 69 | return [ranks[self.rank] stringByAppendingString:self.suit]; 70 | } 71 | 72 | - (int)match:(NSArray *)otherCards 73 | { 74 | int score = 0; 75 | BOOL(^isSameSuit)(id, NSUInteger, BOOL*); 76 | BOOL(^isSameRank)(id, NSUInteger, BOOL*); 77 | 78 | if ([otherCards count] > 0) { 79 | // Define the matching block conditions 80 | isSameSuit = ^(id obj, NSUInteger idx, BOOL *stop) { 81 | return (BOOL)([obj isKindOfClass:[PlayingCard class]]? [self.suit isEqualToString:[obj suit]] : NO); 82 | }; 83 | isSameRank = ^(id obj, NSUInteger idx, BOOL *stop) { 84 | return (BOOL)([obj isKindOfClass:[PlayingCard class]]? self.rank == [obj rank] : NO); 85 | }; 86 | 87 | // Does suit or rank match in all cards? 88 | BOOL suitsMatch = ([otherCards count] == [[otherCards indexesOfObjectsPassingTest:isSameSuit] count]); 89 | BOOL ranksMatch = ([otherCards count] == [[otherCards indexesOfObjectsPassingTest:isSameRank] count]); 90 | 91 | // Give out points 92 | if (suitsMatch) { 93 | score = 1; 94 | } else if (ranksMatch) { 95 | score = 4; 96 | } 97 | } 98 | return score; 99 | } 100 | 101 | @end 102 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Components/PlayingDeck.h: -------------------------------------------------------------------------------- 1 | // 2 | // PlayingDeck.h 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/07/24. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "Deck.h" 11 | 12 | @interface PlayingDeck : Deck 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Components/PlayingDeck.m: -------------------------------------------------------------------------------- 1 | // 2 | // PlayingDeck.m 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/07/24. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "PlayingDeck.h" 10 | #import "PlayingCard.h" 11 | 12 | @implementation PlayingDeck 13 | 14 | - (id)init 15 | { 16 | self = [super init]; 17 | if (self) { 18 | for (NSString *suit in [PlayingCard validSuits]) { 19 | for (NSUInteger rank = 1; rank <= [PlayingCard maxRank]; rank++) { 20 | PlayingCard *card = [[PlayingCard alloc] init]; 21 | card.suit = suit; 22 | card.rank = rank; 23 | [self addCard:card atTop:YES]; 24 | } 25 | } 26 | } 27 | return self; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Components/PlayingGame.h: -------------------------------------------------------------------------------- 1 | // 2 | // PlayingGame.h 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/08/02. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "Deck.h" 11 | #import "Card.h" 12 | @class PlayResult; 13 | 14 | typedef struct { 15 | NSInteger flipCost; 16 | NSInteger mismatchPenalty; 17 | NSInteger matchBonus; 18 | } ScoringDefinitions; 19 | 20 | @interface PlayingGame : NSObject 21 | 22 | /** Designated Initializer */ 23 | - (id)initWithCardCount:(NSUInteger)count 24 | fromDeck:(Deck *)deck 25 | matchCount:(NSUInteger)numCards 26 | bonusPenalties:(ScoringDefinitions)weights; 27 | 28 | - (id)initWithCardCount:(NSUInteger)count 29 | fromDeck:(Deck *)deck; 30 | 31 | @property (readonly, nonatomic) int score; 32 | @property (nonatomic) NSUInteger numCardsToMatch; 33 | 34 | - (PlayResult *)lastPlay; 35 | 36 | - (NSArray *)lastPlays; 37 | 38 | - (void)flipCardAtIndex:(NSUInteger)index; 39 | 40 | - (Card *)cardAtIndex:(NSUInteger)index; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Components/SetCard.h: -------------------------------------------------------------------------------- 1 | // 2 | // SetCard.h 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/09/12. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "Card.h" 11 | 12 | extern NSString * const SetCardSymbolDiamond; 13 | extern NSString * const SetCardSymbolSquiggle; 14 | extern NSString * const SetCardSymbolOval; 15 | 16 | typedef NS_ENUM(NSInteger, SetCardShadingType) { 17 | SetCardShadingSolid, 18 | SetCardShadingStriped, 19 | SetCardShadingOpen, 20 | SET_CARD_SHADING_TYPE_COUNT 21 | }; 22 | 23 | typedef NS_ENUM(NSInteger, SetCardColorType) { 24 | SetCardColorRed, 25 | SetCardColorGreen, 26 | SetCardColorPurple, 27 | SET_CARD_COLOR_TYPE_COUNT 28 | }; 29 | 30 | /** 31 | The Set cards vary in four features: number, symbol, shading, and color. 32 | 33 | A set consists of three cards which satisfy all of these conditions: 34 | 35 | - They all have the same number, or they have three different numbers. 36 | - They all have the same symbol, or they have three different symbols. 37 | - They all have the same shading, or they have three different shadings. 38 | - They all have the same color, or they have three different colors. 39 | 40 | The rules of Set are summarized by: If you can sort a group of three cards 41 | into "Two of ____ and one of _____," then it is not a set. 42 | 43 | For example, these three cards form a set: 44 | 45 | - One red striped diamond 46 | - Two red solid diamonds 47 | - Three red open diamonds 48 | 49 | Given any two cards from the deck, there will be one and only one other 50 | card that forms a set with them. 51 | */ 52 | @interface SetCard : Card 53 | 54 | /** Designated initializer. */ 55 | - (id)initWithNumber:(NSUInteger)number 56 | shading:(SetCardShadingType)shading 57 | color:(SetCardColorType)color 58 | symbol:(NSString *)symbol; 59 | 60 | /** number = one, two, or three. */ 61 | @property (readonly, nonatomic) NSUInteger number; 62 | 63 | /** symbol = diamond, squiggle, oval. */ 64 | @property (readonly, strong, nonatomic) NSString *symbol; 65 | 66 | /** shading = solid, striped, or open. */ 67 | @property (readonly, nonatomic) SetCardShadingType shading; 68 | 69 | /** color = red, green, or purple. */ 70 | @property (readonly, nonatomic) SetCardColorType color; 71 | 72 | /** List of NSString symbols allowed for the Set cards. */ 73 | + (NSArray *)validSymbols; 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Components/SetCard.m: -------------------------------------------------------------------------------- 1 | // 2 | // SetCard.m 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/09/12. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "SetCard.h" 10 | 11 | NSString * const SetCardSymbolDiamond = @"▲"; 12 | NSString * const SetCardSymbolSquiggle = @"■"; 13 | NSString * const SetCardSymbolOval = @"●"; 14 | 15 | @implementation SetCard 16 | 17 | #pragma mark - Class 18 | 19 | /** Validates if a property of the cards is all the same or all distinct. */ 20 | + (BOOL)allSameOrDifferent:(SEL)property forArray:(NSArray *)cards 21 | { 22 | return ([self allElementsInArray:cards haveTheSame:property]) 23 | || ([self allElementsInArray:cards haveDistinct:property]); 24 | } 25 | 26 | + (BOOL)allElementsInArray:(NSArray *)cards haveTheSame:(SEL)property 27 | { 28 | return (1 == [self countUniquePropertyValuesFor:property inCards:cards]); 29 | } 30 | 31 | + (BOOL)allElementsInArray:(NSArray *)cards haveDistinct:(SEL)property 32 | { 33 | return ([cards count] == [self countUniquePropertyValuesFor:property inCards:cards]); 34 | } 35 | 36 | /** 37 | Since sets only contain unique values, making a set out of the values of the property 38 | is an easy way to count the number of unique values for that property. 39 | */ 40 | + (NSUInteger)countUniquePropertyValuesFor:(SEL)property inCards:(NSArray *)cards 41 | { 42 | NSString *propertyName = NSStringFromSelector(property); 43 | NSArray *propertyValues = [cards valueForKey:propertyName]; 44 | NSSet *uniquePropertyValues = [NSSet setWithArray:propertyValues]; 45 | return [uniquePropertyValues count]; 46 | } 47 | 48 | + (NSArray *)validSymbols 49 | { 50 | static NSArray *symbols = nil; 51 | if (!symbols) symbols = @[SetCardSymbolDiamond, SetCardSymbolOval, SetCardSymbolSquiggle]; 52 | return symbols; 53 | } 54 | 55 | #pragma mark - Initialization 56 | 57 | - (id)initWithNumber:(NSUInteger)number 58 | shading:(SetCardShadingType)shading 59 | color:(SetCardColorType)color 60 | symbol:(NSString *)symbol 61 | { 62 | self = [super init]; 63 | if (self) { 64 | // validate params 65 | if (!(number >= 1 && number <= 3) 66 | || !(shading >= 0 && shading < SET_CARD_SHADING_TYPE_COUNT) 67 | || !(color >= 0 && color < SET_CARD_COLOR_TYPE_COUNT) 68 | || ![[SetCard validSymbols] containsObject:symbol]) 69 | { 70 | return nil; 71 | } 72 | 73 | // define the card 74 | _number = number; 75 | _symbol = symbol; 76 | _shading = shading; 77 | _color = color; 78 | } 79 | return self; 80 | } 81 | 82 | - (id)init 83 | { 84 | // "reasonable" settings for a default card 85 | return [self initWithNumber:1 86 | shading:SetCardShadingSolid 87 | color:SetCardColorRed 88 | symbol:[SetCard validSymbols][0]]; 89 | } 90 | 91 | #pragma mark - Methods 92 | 93 | - (NSString *)contents 94 | { 95 | return [@"" stringByPaddingToLength:self.number withString:self.symbol startingAtIndex:0]; 96 | } 97 | 98 | - (int)match:(NSArray *)otherCards 99 | { 100 | int score = 0; 101 | 102 | // Are all other cards a SetCard? 103 | BOOL(^isSameClass)(id, NSUInteger, BOOL*) = ^(id obj, NSUInteger idx, BOOL *stop) { 104 | return [obj isKindOfClass:[SetCard class]]; 105 | }; 106 | BOOL isOnlySetCards = ([otherCards count] == [[otherCards indexesOfObjectsPassingTest:isSameClass] count]); 107 | 108 | // Compare with several SetCards... 109 | if ([otherCards count] > 0 && isOnlySetCards) { 110 | NSArray *allCards = [otherCards arrayByAddingObject:self]; 111 | 112 | // Penalise if some characteristic didn't match 113 | if (![SetCard allSameOrDifferent:@selector(number) forArray:allCards]) score--; 114 | if (![SetCard allSameOrDifferent:@selector(shading) forArray:allCards]) score--; 115 | if (![SetCard allSameOrDifferent:@selector(color) forArray:allCards]) score--; 116 | if (![SetCard allSameOrDifferent:@selector(symbol) forArray:allCards]) score--; 117 | 118 | // Give points for matching a set 119 | if (!(score < 0)) score = 3; 120 | } 121 | return score; 122 | } 123 | 124 | @end 125 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Components/SetDeck.h: -------------------------------------------------------------------------------- 1 | // 2 | // SetDeck.h 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/09/12. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "Deck.h" 11 | 12 | /** 13 | The Set deck consists of 81 cards. 14 | */ 15 | @interface SetDeck : Deck 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Components/SetDeck.m: -------------------------------------------------------------------------------- 1 | // 2 | // SetDeck.m 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/09/12. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "SetDeck.h" 10 | #import "SetCard.h" 11 | 12 | @implementation SetDeck 13 | 14 | - (id)init 15 | { 16 | self = [super init]; 17 | if (self) { 18 | for (NSUInteger number = 1; number <= 3; number++) { 19 | for (NSString *symbol in [SetCard validSymbols]) { 20 | for (SetCardShadingType shade = 0; shade < SET_CARD_SHADING_TYPE_COUNT; shade++) { 21 | for (SetCardColorType color = 0; color < SET_CARD_COLOR_TYPE_COUNT; color++) { 22 | SetCard *card = [[SetCard alloc] initWithNumber:number 23 | shading:shade 24 | color:color 25 | symbol:symbol]; 26 | if (card) [self addCard:card atTop:YES]; 27 | } 28 | } 29 | } 30 | 31 | } 32 | } 33 | return self; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Components/SetGame.h: -------------------------------------------------------------------------------- 1 | // 2 | // SetGame.h 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/09/12. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "PlayingGame.h" 10 | #import "SetDeck.h" 11 | #import "SetCard.h" 12 | 13 | @interface SetGame : PlayingGame 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Components/SetGame.m: -------------------------------------------------------------------------------- 1 | // 2 | // SetGame.m 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/09/12. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "SetGame.h" 10 | 11 | @implementation SetGame 12 | 13 | #pragma mark - NSObject 14 | 15 | - (NSString *)description 16 | { 17 | return @"Sets"; 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Controllers/CardGameViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CardGameViewController.h 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/07/22. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | @class PlayingGame; 11 | 12 | @interface CardGameViewController : UIViewController 13 | { 14 | @protected 15 | PlayingGame *_game; 16 | } 17 | @end 18 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Controllers/CardGameViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CardGameViewController.m 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/07/22. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "CardGameViewController.h" 10 | #import "PlayingGame.h" 11 | #import "PlayingDeck.h" 12 | #import "GameResult.h" 13 | #import "PlayResult.h" 14 | 15 | @interface CardGameViewController () 16 | 17 | @property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *cardButtons; 18 | @property (weak, nonatomic) IBOutlet UILabel *flipsDisplay; 19 | @property (weak, nonatomic) IBOutlet UILabel *scoreDisplay; 20 | @property (weak, nonatomic) IBOutlet UILabel *messageDisplay; 21 | @property (weak, nonatomic) IBOutlet UISegmentedControl *gameModeSelector; 22 | @property (weak, nonatomic) IBOutlet UISlider *messageHistory; 23 | @property (nonatomic) int flipsCount; 24 | @property (strong, nonatomic) PlayingGame *game; 25 | @property (strong, nonatomic) GameResult *gameResult; 26 | 27 | @end 28 | 29 | @implementation CardGameViewController 30 | 31 | - (GameResult *)gameResult 32 | { 33 | if (!_gameResult) { 34 | _gameResult = [[GameResult alloc] init]; 35 | _gameResult.gameName = self.game.description; 36 | } 37 | return _gameResult; 38 | } 39 | 40 | - (PlayingGame *)game 41 | { 42 | if (!_game) _game = [[PlayingGame alloc] initWithCardCount:[self.cardButtons count] 43 | fromDeck:[[PlayingDeck alloc] init] 44 | matchCount:(self.gameModeSelector.selectedSegmentIndex)? 3 : 2 45 | bonusPenalties:(ScoringDefinitions){-1, -2, 4}]; 46 | return _game; 47 | } 48 | 49 | - (void)setCardButtons:(NSArray *)cardButtons 50 | { 51 | _cardButtons = cardButtons; 52 | [self updateUI]; 53 | } 54 | 55 | - (void)updateUI 56 | { 57 | for (UIButton *cardButton in self.cardButtons) { 58 | Card *card = [self.game cardAtIndex:[self.cardButtons indexOfObject:cardButton]]; 59 | // Card face 60 | [cardButton setTitle:card.contents forState:UIControlStateSelected]; 61 | [cardButton setTitle:card.contents forState:UIControlStateSelected|UIControlStateDisabled]; 62 | // Card back 63 | cardButton.imageEdgeInsets = UIEdgeInsetsMake(4.0, 4.0, 4.0, 4.0); 64 | UIImage *cardBackImage = [UIImage imageNamed:@"cardback"]; 65 | [cardButton setImage:(card.isFaceUp)? nil : cardBackImage forState:UIControlStateNormal]; 66 | // Card state 67 | cardButton.selected = card.isFaceUp; 68 | cardButton.enabled = !card.isUnplayable; 69 | cardButton.alpha = (card.isUnplayable)? 0.3 : 1.0; 70 | } 71 | self.scoreDisplay.text = [NSString stringWithFormat:@"Score: %d", self.game.score]; 72 | self.messageDisplay.text = [[self.game lastPlay] description]; 73 | } 74 | 75 | - (void)setFlipsCount:(int)count 76 | { 77 | _flipsCount = count; 78 | self.flipsDisplay.text = [NSString stringWithFormat:@"Flips: %d", self.flipsCount]; 79 | } 80 | 81 | - (IBAction)flipCard:(UIButton *)sender 82 | { 83 | self.gameModeSelector.enabled = NO; 84 | [self.game flipCardAtIndex:[self.cardButtons indexOfObject:sender]]; 85 | if (sender.isEnabled && !sender.isSelected) { 86 | self.flipsCount++; // Card flipped up 87 | } 88 | self.messageHistory.maximumValue = [[self.game lastPlays] count]; 89 | self.messageHistory.value = [[self.game lastPlays] count]; 90 | self.messageDisplay.alpha = 1.0; 91 | [self updateUI]; 92 | self.gameResult.score = self.game.score; 93 | } 94 | 95 | - (IBAction)dealGame { 96 | self.gameModeSelector.enabled = YES; 97 | self.game = nil; 98 | self.flipsCount = 0; 99 | self.messageHistory.maximumValue = self.flipsCount; 100 | [self updateUI]; 101 | self.gameResult = nil; 102 | } 103 | 104 | - (IBAction)changeGameMode:(UISegmentedControl *)sender 105 | { 106 | self.game.numCardsToMatch = (sender.selectedSegmentIndex)? 3 : 2; 107 | } 108 | 109 | - (IBAction)timeTravel:(UISlider *)sender { 110 | if (sender.maximumValue > 0) { 111 | int index = (int)[sender value]; 112 | self.messageDisplay.text = (!index)? @"" : [[self.game lastPlays][index - 1] description]; 113 | self.messageDisplay.alpha = (index == sender.maximumValue)? 1.0 : 0.3; 114 | } 115 | } 116 | 117 | @end 118 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Controllers/GameResult.h: -------------------------------------------------------------------------------- 1 | // 2 | // GameResult.h 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/09/10. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface GameResult : NSObject 12 | 13 | + (NSArray *)allGameResults; // of GameResult 14 | 15 | @property (readonly, nonatomic) NSDate *start; 16 | @property (readonly, nonatomic) NSDate *end; 17 | @property (readonly, nonatomic) NSTimeInterval duration; 18 | @property (nonatomic) int score; 19 | @property (nonatomic) NSString *gameName; 20 | 21 | - (NSComparisonResult)compareDateDescending:(GameResult *)otherResult; 22 | - (NSComparisonResult)compareDurationAscending:(GameResult *)otherResult; 23 | - (NSComparisonResult)compareScoreDescending:(GameResult *)otherResult; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Controllers/GameResult.m: -------------------------------------------------------------------------------- 1 | // 2 | // GameResult.m 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/09/10. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "GameResult.h" 10 | 11 | @interface GameResult() 12 | 13 | @property (readwrite, nonatomic) NSDate *start; 14 | @property (readwrite, nonatomic) NSDate *end; 15 | 16 | @end 17 | 18 | @implementation GameResult 19 | 20 | #define KEY_ALL_RESULTS @"GameResult.AllResults" 21 | #define KEY_START @"StartDate" 22 | #define KEY_END @"EndDate" 23 | #define KEY_SCORE @"Score" 24 | #define KEY_GAME @"GameName" 25 | 26 | #pragma mark - Class 27 | 28 | + (NSArray *)allGameResults 29 | { 30 | NSMutableArray *allGameResults = [[NSMutableArray alloc] init]; 31 | 32 | for (id plist in [[[NSUserDefaults standardUserDefaults] dictionaryForKey:KEY_ALL_RESULTS] allValues]) { 33 | GameResult *result = [[GameResult alloc] initFromPropertyList:plist]; 34 | [allGameResults addObject:result]; 35 | } 36 | 37 | return allGameResults; 38 | } 39 | 40 | #pragma mark - Initializers 41 | 42 | /** Designated initializer */ 43 | - (id)init 44 | { 45 | self = [super init]; 46 | if (self) { 47 | _start = [NSDate date]; 48 | _end = _start; 49 | } 50 | return self; 51 | } 52 | 53 | - (id)initFromPropertyList:(id)plist 54 | { 55 | self = [self init]; 56 | if (self) { 57 | if ([plist isKindOfClass:[NSDictionary class]]) { 58 | _start = plist[KEY_START]; 59 | _end = plist[KEY_END]; 60 | _score = [plist[KEY_SCORE] intValue]; 61 | _gameName = plist[KEY_GAME]; 62 | if (!_start || !_end) self = nil; 63 | } 64 | } 65 | return self; 66 | } 67 | 68 | #pragma mark - Properties 69 | 70 | - (NSTimeInterval)duration 71 | { 72 | return [self.end timeIntervalSinceDate:self.start]; 73 | } 74 | 75 | - (void)setScore:(int)score 76 | { 77 | _score = score; 78 | self.end = [NSDate date]; 79 | [self synchronize]; 80 | } 81 | 82 | #pragma mark - Methods 83 | 84 | - (NSDictionary *)asPropertyList 85 | { 86 | return @{KEY_START: self.start, 87 | KEY_END: self.end, 88 | KEY_SCORE: @(self.score), 89 | KEY_GAME: self.gameName}; 90 | } 91 | 92 | - (NSComparisonResult)compareDateDescending:(GameResult *)otherResult 93 | { 94 | return [otherResult.start compare:self.end]; 95 | } 96 | 97 | - (NSComparisonResult)compareDurationAscending:(GameResult *)otherResult 98 | { 99 | return [@(self.duration) compare:@(otherResult.duration)]; 100 | } 101 | 102 | - (NSComparisonResult)compareScoreDescending:(GameResult *)otherResult 103 | { 104 | return [@(otherResult.score) compare:@(self.score)]; 105 | } 106 | 107 | - (void)synchronize 108 | { 109 | // Fetch 110 | NSMutableDictionary *allGameResults = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:KEY_ALL_RESULTS ] mutableCopy]; 111 | if (!allGameResults) allGameResults = [[NSMutableDictionary alloc] init]; 112 | // Change 113 | allGameResults[[self.start description]] = [self asPropertyList]; 114 | // Store 115 | [[NSUserDefaults standardUserDefaults] setObject:allGameResults forKey:KEY_ALL_RESULTS]; 116 | [[NSUserDefaults standardUserDefaults] synchronize]; 117 | } 118 | 119 | #pragma mark - NSObject 120 | 121 | - (NSString *)description 122 | { 123 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 124 | [formatter setDateStyle:NSDateFormatterMediumStyle]; 125 | [formatter setTimeStyle:NSDateFormatterShortStyle]; 126 | return [NSString stringWithFormat:@"%@:\t%d\t@ %@ (%0g)", self.gameName, self.score, [formatter stringFromDate:self.end], round(self.duration)]; 127 | } 128 | 129 | @end 130 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Controllers/GameResultViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // GameResultViewController.h 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/09/10. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface GameResultViewController : UIViewController 12 | 13 | @property (weak, nonatomic) IBOutlet UITextView *display; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Controllers/GameResultViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // GameResultViewController.m 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/09/10. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "GameResultViewController.h" 10 | #import "GameResult.h" 11 | 12 | @interface GameResultViewController() 13 | @property (nonatomic) SEL criteriaForSorting; 14 | @end 15 | 16 | @implementation GameResultViewController 17 | 18 | #pragma mark - Boilerplate template (for reference) 19 | 20 | - (void)setup 21 | { 22 | // things that can't wait until viewDidLoad 23 | } 24 | 25 | - (void)awakeFromNib 26 | { 27 | [self setup]; 28 | } 29 | 30 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 31 | { 32 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 33 | [self setup]; 34 | return self; 35 | } 36 | 37 | #pragma mark - Properties 38 | 39 | @synthesize criteriaForSorting = _criteriaForSorting; 40 | 41 | - (SEL)criteriaForSorting 42 | { 43 | if (!_criteriaForSorting) _criteriaForSorting = @selector(compareDateDescending:); 44 | return _criteriaForSorting; 45 | } 46 | 47 | - (void)setCriteriaForSorting:(SEL)criteriaForSorting 48 | { 49 | _criteriaForSorting = criteriaForSorting; 50 | [self updateUI]; 51 | } 52 | 53 | #pragma mark - Methods 54 | 55 | - (void)updateUI 56 | { 57 | self.display.text = [[[GameResult allGameResults] sortedArrayUsingSelector:self.criteriaForSorting] componentsJoinedByString:@"\n"]; 58 | } 59 | 60 | - (IBAction)defineSortingCriteria:(UIButton *)sender 61 | { 62 | int tag = sender.tag; 63 | switch (tag) { 64 | case 2: 65 | self.criteriaForSorting = @selector(compareScoreDescending:); 66 | break; 67 | case 3: 68 | self.criteriaForSorting = @selector(compareDurationAscending:); 69 | break; 70 | default: 71 | self.criteriaForSorting = @selector(compareDateDescending:); 72 | } 73 | } 74 | 75 | #pragma mark - UIViewController 76 | 77 | - (void)viewWillAppear:(BOOL)animated 78 | { 79 | [super viewWillAppear:animated]; 80 | [self updateUI]; 81 | } 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Controllers/SetGameViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SetGameViewController.h 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/09/12. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CardGameViewController.h" 11 | 12 | @interface SetGameViewController : CardGameViewController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // Settings.xcconfig 3 | // 4 | // Created by Hugo Ferreira on 2013/10/10. 5 | // Copyright (c) 2013 Mindclick. All rights reserved. 6 | // 7 | 8 | #include "Warnings.xcconfig" 9 | 10 | // Override some of the warnings settings 11 | GCC_TREAT_WARNINGS_AS_ERRORS = NO 12 | 13 | // Setup code coverage analysis 14 | // http://blog.nwoolls.com/2013/02/08/visualizing-code-coverage-with-xcode/ 15 | GCC_GENERATE_TEST_COVERAGE_FILES = YES 16 | GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES 17 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Matchismo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIcons 12 | 13 | CFBundleIcons~ipad 14 | 15 | CFBundleIdentifier 16 | pt.mindclick.cs193p.${PRODUCT_NAME:rfc1034identifier} 17 | CFBundleInfoDictionaryVersion 18 | 6.0 19 | CFBundleName 20 | ${PRODUCT_NAME} 21 | CFBundlePackageType 22 | APPL 23 | CFBundleShortVersionString 24 | 1.0 25 | CFBundleSignature 26 | ???? 27 | CFBundleVersion 28 | 1.0 29 | LSRequiresIPhoneOS 30 | 31 | UIMainStoryboardFile 32 | MainStoryboard 33 | UIRequiredDeviceCapabilities 34 | 35 | armv7 36 | 37 | UISupportedInterfaceOrientations 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationLandscapeLeft 41 | UIInterfaceOrientationLandscapeRight 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Matchismo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'Matchismo' target in the 'Matchismo' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_5_0 8 | #warning "This project uses features only available in iOS SDK 5.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | 16 | // Custom definitions 17 | #import "Abstract.h" 18 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "1x", 6 | "size" : "57x57" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "2x", 11 | "size" : "57x57" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "60x60" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "1x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "29x29" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "2x", 31 | "size" : "40x40" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "filename" : "Default@2x.png", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "extent" : "full-screen", 13 | "idiom" : "iphone", 14 | "subtype" : "retina4", 15 | "filename" : "Default-568h@2x.png", 16 | "minimum-system-version" : "7.0", 17 | "orientation" : "portrait", 18 | "scale" : "2x" 19 | }, 20 | { 21 | "orientation" : "portrait", 22 | "idiom" : "iphone", 23 | "extent" : "full-screen", 24 | "filename" : "Default.png", 25 | "scale" : "1x" 26 | }, 27 | { 28 | "orientation" : "portrait", 29 | "idiom" : "iphone", 30 | "extent" : "full-screen", 31 | "filename" : "Default@2x-1.png", 32 | "scale" : "2x" 33 | }, 34 | { 35 | "orientation" : "portrait", 36 | "idiom" : "iphone", 37 | "extent" : "full-screen", 38 | "filename" : "Default-568h@2x-1.png", 39 | "subtype" : "retina4", 40 | "scale" : "2x" 41 | } 42 | ], 43 | "info" : { 44 | "version" : 1, 45 | "author" : "xcode" 46 | } 47 | } -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/LaunchImage.launchimage/Default-568h@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/LaunchImage.launchimage/Default-568h@2x-1.png -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/LaunchImage.launchimage/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/LaunchImage.launchimage/Default-568h@2x.png -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/LaunchImage.launchimage/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/LaunchImage.launchimage/Default.png -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/LaunchImage.launchimage/Default@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/LaunchImage.launchimage/Default@2x-1.png -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/LaunchImage.launchimage/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/LaunchImage.launchimage/Default@2x.png -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/Tab Bar/hash.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "hash.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/Tab Bar/hash.imageset/hash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/Tab Bar/hash.imageset/hash.png -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/Tab Bar/set.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "set.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/Tab Bar/set.imageset/set.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/Tab Bar/set.imageset/set.png -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/Tab Bar/spade.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "spade.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/Tab Bar/spade.imageset/spade.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/Tab Bar/spade.imageset/spade.png -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/cardback.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "cardback.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "cardback@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/cardback.imageset/cardback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/cardback.imageset/cardback.png -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/cardback.imageset/cardback@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/Matchismo/Matchismo/Resources/Images.xcassets/cardback.imageset/cardback@2x.png -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // Warnings.xcconfig 3 | // 4 | // Created by Steven Fisher: 5 | // http://tewha.net/2010/11/xcode-warnings/ 6 | // See also: 7 | // http://boredzo.org/blog/archives/2009-11-07/warnings 8 | // 9 | 10 | GCC_WARN_CHECK_SWITCH_STATEMENTS = YES 11 | GCC_WARN_SHADOW = YES 12 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES 13 | GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES 14 | GCC_WARN_ABOUT_RETURN_TYPE = YES 15 | GCC_WARN_MISSING_PARENTHESES = YES 16 | GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES 17 | GCC_WARN_ABOUT_MISSING_NEWLINE = YES 18 | GCC_WARN_SIGN_COMPARE = YES 19 | GCC_WARN_UNDECLARED_SELECTOR = YES 20 | GCC_WARN_UNUSED_FUNCTION = YES 21 | GCC_WARN_UNUSED_LABEL = YES 22 | GCC_WARN_UNUSED_VALUE = YES 23 | GCC_WARN_UNUSED_VARIABLE = YES 24 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES 25 | GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES 26 | GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES 27 | GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES 28 | GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = YES 29 | GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES 30 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES 31 | CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES 32 | CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES 33 | OTHER_CFLAGS = -Wextra -Wno-unused-parameter 34 | GCC_TREAT_WARNINGS_AS_ERRORS = YES 35 | RUN_CLANG_STATIC_ANALYZER = YES 36 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Matchismo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Matchismo 4 | // 5 | // Created by Hugo Ferreira on 2013/07/22. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "CardGameAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([CardGameAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Screen Shot 2013-08-27 at 18.49.06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/Matchismo/Screen Shot 2013-08-27 at 18.49.06.png -------------------------------------------------------------------------------- /2013 Winter/Matchismo/Screen Shot 2013-09-25 at 14.11.19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/Matchismo/Screen Shot 2013-09-25 at 14.11.19.png -------------------------------------------------------------------------------- /2013 Winter/Matchismo/TODO.h: -------------------------------------------------------------------------------- 1 | 2 | /* TODO: Maybe test fixture should be is a separate classs? 3 | (so test code is for sure uncapable to change the ivar) */ 4 | 5 | /* IGNORE: Skip the rest of assignment 3. Not much learning value left in there! */ 6 | 7 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/README.md: -------------------------------------------------------------------------------- 1 | [The Clean Architecture | 8th Light](http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html) 2 | 3 | ![The Clean Architecture](http://blog.8thlight.com/uncle-bob/images/2012-08-13-the-clean-architecture/CleanArchitecture.jpg) 4 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Adapters/Controllers/ImageDetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ImageDetailViewController.h 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/07. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ImageEntity.h" 11 | 12 | @interface ImageDetailViewController : UIViewController 13 | 14 | @property (strong, nonatomic) ImageEntity *imageToDisplay; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Adapters/Controllers/ImageDetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ImageDetailViewController.m 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/07. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "ImageDetailViewController.h" 10 | 11 | static const CGFloat ImageDetailZoomMin = 0.2f; 12 | static const CGFloat ImageDetailZoomNormal = 1.0f; 13 | static const CGFloat ImageDetailZoomMax = 5.0f; 14 | 15 | @interface ImageDetailViewController () 16 | 17 | @property (weak, nonatomic) IBOutlet UINavigationItem *toolbar; 18 | @property (weak, nonatomic) IBOutlet UIScrollView *scrollView; 19 | @property (strong, nonatomic) UIImageView *imageView; 20 | 21 | @end 22 | 23 | @implementation ImageDetailViewController 24 | 25 | #pragma mark - Properties 26 | 27 | - (UIImageView *)imageView 28 | { 29 | if (!_imageView) _imageView = [[UIImageView alloc] initWithFrame:CGRectZero]; 30 | return _imageView; 31 | } 32 | 33 | - (void)setImageToDisplay:(ImageEntity *)imageToDisplay 34 | { 35 | _imageToDisplay = imageToDisplay; 36 | [self resetImage]; 37 | } 38 | 39 | #pragma mark - Methods 40 | 41 | - (void)resetImage 42 | { 43 | if (self.toolbar) { 44 | self.toolbar.title = self.imageToDisplay.title; 45 | } 46 | if (self.scrollView) { 47 | [self resetDisplayArea]; 48 | [self displayImage:[self loadImage]]; 49 | } 50 | } 51 | 52 | - (void)resetDisplayArea 53 | { 54 | self.scrollView.zoomScale = ImageDetailZoomNormal; 55 | self.scrollView.contentSize = CGSizeZero; 56 | self.imageView.image = nil; 57 | } 58 | 59 | - (UIImage *)loadImage 60 | { 61 | NSData *imageData = [[NSData alloc] initWithContentsOfURL:self.imageToDisplay.formats.normal]; 62 | return [[UIImage alloc] initWithData:imageData]; 63 | } 64 | 65 | - (void)displayImage:(UIImage *)image 66 | { 67 | if (image) { 68 | self.scrollView.contentSize = image.size; 69 | self.imageView.image = image; 70 | self.imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height); 71 | } 72 | } 73 | 74 | - (void)configureScrollView 75 | { 76 | self.scrollView.maximumZoomScale = ImageDetailZoomMax; 77 | self.scrollView.minimumZoomScale = ImageDetailZoomMin; 78 | self.scrollView.delegate = self; 79 | } 80 | 81 | #pragma mark - UIScrollViewDelegate 82 | 83 | - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView 84 | { 85 | return self.imageView; 86 | } 87 | 88 | #pragma mark - UIViewController 89 | 90 | - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation 91 | { 92 | /* TODO: Add auto scrolling based on UIScrollView’s bounds and the size of the photo. */ 93 | /* See when in the VC's lifecycle you can do geometry calculations with Autolayout on. */ 94 | // CGFloat zoomFactor; 95 | // if (self.imageView.image.size.width < self.scrollView.frame.size.width) { 96 | // zoomFactor = self.scrollView.frame.size.width / self.imageView.image.size.width; 97 | // self.scrollView.zoomScale = zoomFactor; 98 | // } 99 | // [self resetImage]; 100 | } 101 | 102 | - (void)viewDidLoad 103 | { 104 | [super viewDidLoad]; 105 | [self.scrollView addSubview:self.imageView]; 106 | [self configureScrollView]; 107 | [self resetImage]; 108 | } 109 | 110 | @end 111 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Adapters/Controllers/ImageListViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ImageListViewController.h 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/07. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TagEntity.h" 11 | 12 | @interface ImageListViewController : UITableViewController 13 | 14 | @property (strong, nonatomic) NSArray *imageEntries; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Adapters/Controllers/ImageListViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ImageListViewController.m 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/07. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "ImageListViewController.h" 10 | #import "ImageDetailViewController.h" 11 | #import "ImageViewingInteractor.h" 12 | #import "ImageEntity.h" 13 | 14 | static NSString * const ImageListCellReuseIdentifier = @"ImageName"; 15 | 16 | @interface ImageListViewController () 17 | 18 | @end 19 | 20 | @implementation ImageListViewController 21 | 22 | #pragma mark - Properties 23 | 24 | - (void)setImageEntries:(NSArray *)imageEntries 25 | { 26 | _imageEntries = imageEntries; 27 | [self.tableView reloadData]; 28 | } 29 | 30 | #pragma mark - UITableViewDataSource 31 | 32 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 33 | { 34 | return (NSInteger)[self.imageEntries count]; 35 | } 36 | 37 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 38 | { 39 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ImageListCellReuseIdentifier 40 | forIndexPath:indexPath]; 41 | ImageEntity *image = (ImageEntity *)self.imageEntries[(NSUInteger)indexPath.row]; 42 | cell.textLabel.text = image.title; 43 | cell.detailTextLabel.text = image.description; 44 | return cell; 45 | } 46 | 47 | #pragma mark - UIViewController 48 | 49 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 50 | { 51 | if ([sender isKindOfClass:[UITableViewCell class]]) { 52 | NSIndexPath *indexPath = [self.tableView indexPathForCell:sender]; 53 | if (indexPath) { 54 | if ([segue.destinationViewController isKindOfClass:[ImageDetailViewController class]]) { 55 | ImageEntity *image = self.imageEntries[(NSUInteger)indexPath.row]; 56 | ((ImageDetailViewController *)segue.destinationViewController).imageToDisplay = image; 57 | } 58 | } 59 | } 60 | } 61 | 62 | - (void)viewDidLoad 63 | { 64 | if (!self.imageEntries) { 65 | self.imageEntries = [[ImageViewingInteractor new] listRecentImages]; 66 | } 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Adapters/Controllers/TabletSplitViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TabletSplitViewController.h 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/24. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TabletSplitViewController : UISplitViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Adapters/Controllers/TabletSplitViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TabletSplitViewController.m 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/24. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "TabletSplitViewController.h" 10 | 11 | @interface TabletSplitViewController () 12 | 13 | @end 14 | 15 | @implementation TabletSplitViewController 16 | 17 | #pragma mark - NSObject 18 | 19 | - (void)awakeFromNib 20 | { 21 | self.delegate = self; 22 | } 23 | 24 | #pragma mark - UISplitViewControllerDelegate 25 | 26 | -(BOOL)splitViewController:(UISplitViewController *)svc 27 | shouldHideViewController:(UIViewController *)vc 28 | inOrientation:(UIInterfaceOrientation)orientation 29 | { 30 | return NO; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Adapters/Controllers/TagListViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TagListViewController.h 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/07. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TagListViewController : UITableViewController 12 | 13 | @property (strong, nonatomic) NSArray *tagEntries; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Adapters/Controllers/TagListViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TagListViewController.m 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/07. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "TagListViewController.h" 10 | #import "TagListingInteractor.h" 11 | #import "TagEntity.h" 12 | #import "ImageViewingInteractor.h" 13 | 14 | static NSString * const TagListCellReuseIdentifier = @"TagName"; 15 | static NSString * const TagListCellSegueIdentifier = @"ShowImagesForTag"; 16 | static NSString * const TagListCellSegueSelector = @"setTagForImages:"; 17 | static NSString * const TagListSubtitleText = @"%ld photo%@"; 18 | 19 | @interface TagListViewController () 20 | 21 | @end 22 | 23 | @implementation TagListViewController 24 | 25 | #pragma mark - Properties 26 | 27 | - (void)setTagEntries:(NSArray *)tagEntries 28 | { 29 | _tagEntries = tagEntries; 30 | [self.tableView reloadData]; 31 | } 32 | 33 | #pragma mark - Methods 34 | 35 | - (NSArray *)sortAlphabetically:(NSArray *)tagList 36 | { 37 | NSSortDescriptor *byAscendingName = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES]; 38 | return [tagList sortedArrayUsingDescriptors:@[byAscendingName]]; 39 | } 40 | 41 | #pragma mark - UITableViewDataSource 42 | 43 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 44 | { 45 | return (NSInteger)[self.tagEntries count]; 46 | } 47 | 48 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 49 | { 50 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TagListCellReuseIdentifier 51 | forIndexPath:indexPath]; 52 | TagEntity *tag = (TagEntity *)self.tagEntries[(NSUInteger)indexPath.row]; 53 | BOOL isPlural = tag.numberOfImages > 1; 54 | cell.textLabel.text = tag.description; 55 | cell.detailTextLabel.text = [NSString stringWithFormat:TagListSubtitleText, 56 | (unsigned long)tag.numberOfImages, (isPlural)? @"s" : @""]; 57 | return cell; 58 | } 59 | 60 | #pragma mark - UIViewController 61 | 62 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 63 | { 64 | if ([segue.identifier isEqualToString:TagListCellSegueIdentifier]) { 65 | if ([sender isKindOfClass:[UITableViewCell class]]) { 66 | NSIndexPath *indexPath = [self.tableView indexPathForCell:sender]; 67 | if (indexPath) { 68 | #pragma clang diagnostic push 69 | #pragma clang diagnostic ignored "-Wundeclared-selector" 70 | if ([segue.destinationViewController respondsToSelector:@selector(setImageEntries:)]) { 71 | TagEntity *tag = self.tagEntries[(NSUInteger)indexPath.row]; 72 | NSArray * images = [[ImageViewingInteractor new] listImagesByTag:tag]; 73 | [segue.destinationViewController performSelector:@selector(setImageEntries:) withObject:images]; 74 | } 75 | #pragma clang diagnostic pop 76 | } 77 | } 78 | } 79 | } 80 | 81 | - (void)viewDidLoad 82 | { 83 | [super viewDidLoad]; 84 | if (!self.tagEntries) { 85 | NSArray *tagList = [[TagListingInteractor new] listAllTags]; 86 | self.tagEntries = [self sortAlphabetically:tagList]; 87 | } 88 | } 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Adapters/Gateways/ImageSupplierFlickr.h: -------------------------------------------------------------------------------- 1 | // 2 | // ImageSupplierFlickr.h 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/07. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ImageSupplierGateway.h" 11 | 12 | @interface ImageSupplierFlickr : NSObject 13 | 14 | + (instancetype)sharedImageSupplierFlickr; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Adapters/Gateways/ImageSupplierGateway.h: -------------------------------------------------------------------------------- 1 | // 2 | // ImageSupplierGateway.h 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/12. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ImageSupplierDataSource.h" 11 | 12 | @interface ImageSupplierGateway : NSObject 13 | 14 | + (id )defaultDataSource; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Adapters/Gateways/ImageSupplierGateway.m: -------------------------------------------------------------------------------- 1 | // 2 | // ImageSupplierGateway.m 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/12. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "ImageSupplierGateway.h" 10 | #import "ImageSupplierFlickr.h" 11 | 12 | @implementation ImageSupplierGateway 13 | 14 | + (id)defaultDataSource 15 | { 16 | return [ImageSupplierFlickr sharedImageSupplierFlickr]; 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/07. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/07. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @implementation AppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application 32 | { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application 37 | { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application 42 | { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Entities/ImageEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // ImageEntity.h 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/07. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ImageFormatURLs.h" 11 | 12 | @interface ImageEntity : NSObject 13 | 14 | @property (readonly, strong, nonatomic) NSString *title; 15 | @property (readonly, strong, nonatomic) NSString *description; 16 | @property (readonly, strong, nonatomic) NSString *author; 17 | @property (readonly, strong, nonatomic) ImageFormatURLs *formats; 18 | 19 | ///-------------------------------------------------------------------------------- 20 | /// @name Initializing an Image 21 | ///-------------------------------------------------------------------------------- 22 | 23 | /** Designated initializer. */ 24 | - (id)initWithTitle:(NSString *)titleText 25 | description:(NSString *)descriptionText 26 | author:(NSString *)authorName 27 | formats:(ImageFormatURLs *)formatURLs; 28 | 29 | + (id)new __attribute__((unavailable("use the designated initializer instead"))); 30 | - (id)init __attribute__((unavailable("use the designated initializer instead"))); 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Entities/ImageEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // ImageEntity.m 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/07. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "ImageEntity.h" 10 | 11 | @implementation ImageEntity 12 | 13 | - (id)initWithTitle:(NSString *)titleText 14 | description:(NSString *)descriptionText 15 | author:(NSString *)authorName 16 | formats:(ImageFormatURLs *)formatURLs 17 | { 18 | self = [super init]; 19 | if (self) { 20 | _title = titleText; 21 | _description = descriptionText; 22 | _author = authorName; 23 | _formats = formatURLs; 24 | } 25 | return self; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Entities/ImageFormatURLs.h: -------------------------------------------------------------------------------- 1 | // 2 | // ImageFormatURLs.h 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/13. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ImageFormatURLs : NSObject 12 | 13 | @property (readonly, strong, nonatomic) NSURL *thumbnail; 14 | @property (readonly, strong, nonatomic) NSURL *normal; 15 | @property (readonly, strong, nonatomic) NSURL *hires; 16 | 17 | ///-------------------------------------------------------------------------------- 18 | /// @name Initializing an Image 19 | ///-------------------------------------------------------------------------------- 20 | 21 | /** Designated initializer. */ 22 | - (id)initWithURL:(NSURL *)normalURL thumbnail:(NSURL *)thumbURL hires:(NSURL *)hiresURL; 23 | 24 | + (id)new __attribute__((unavailable("use the designated initializer instead"))); 25 | - (id)init __attribute__((unavailable("use the designated initializer instead"))); 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Entities/ImageFormatURLs.m: -------------------------------------------------------------------------------- 1 | // 2 | // ImageFormatURLs.m 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/13. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "ImageFormatURLs.h" 10 | 11 | @implementation ImageFormatURLs 12 | 13 | #pragma mark - Initialization 14 | 15 | - (id)initWithURL:(NSURL *)normalURL thumbnail:(NSURL *)thumbURL hires:(NSURL *)hiresURL 16 | { 17 | self = [super init]; 18 | if (self) { 19 | _normal = normalURL; 20 | _thumbnail = thumbURL; 21 | _hires = hiresURL; 22 | } 23 | return self; 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Entities/TagEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // TagEntity.h 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/07. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TagEntity : NSObject 12 | 13 | @property (readonly, strong, nonatomic) NSString *name; 14 | @property (readonly, nonatomic) NSUInteger numberOfImages; 15 | 16 | ///-------------------------------------------------------------------------------- 17 | /// @name Initializing a Tag 18 | ///-------------------------------------------------------------------------------- 19 | 20 | /** Designated initializer. */ 21 | - (id)initWithName:(NSString *)name imageCount:(NSUInteger)count; 22 | 23 | + (id)new __attribute__((unavailable("use the designated initializer instead"))); 24 | - (id)init __attribute__((unavailable("use the designated initializer instead"))); 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Entities/TagEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // TagEntity.m 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/07. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "TagEntity.h" 10 | 11 | @implementation TagEntity 12 | 13 | #pragma mark - Initialization 14 | 15 | - (id)initWithName:(NSString *)name imageCount:(NSUInteger)count 16 | { 17 | self = [super init]; 18 | if (self) { 19 | _name = name; 20 | _numberOfImages = count; 21 | } 22 | return self; 23 | } 24 | 25 | #pragma mark - NSObject 26 | 27 | - (NSString *)description 28 | { 29 | return [self.name capitalizedString]; 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Interfaces/FlickrFetcher/FlickrAPIKey.h: -------------------------------------------------------------------------------- 1 | // 2 | // FlickrAPIKey.h 3 | // 4 | // Created for Stanford CS193p Winter 2013. 5 | // Copyright 2013 Stanford University. All rights reserved. 6 | // 7 | // Get your own key! 8 | // No Flickr fetches will work without the API Key! 9 | // 10 | 11 | #define FlickrAPIKey @"9a0554259914a86fb9e7eb014e4e5d52" 12 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Interfaces/FlickrFetcher/FlickrFetcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // FlickrFetcher.h 3 | // 4 | // Created for Stanford CS193p Winter 2013. 5 | // Copyright 2013 Stanford University. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | // tags in the photo dictionaries returned from stanfordPhotos or latestGeoreferencedPhotos 11 | 12 | #define FLICKR_PHOTO_TITLE @"title" 13 | #define FLICKR_PHOTO_DESCRIPTION @"description._content" // must use valueForKeyPath: on this one 14 | #define FLICKR_PLACE_NAME @"_content" 15 | #define FLICKR_PHOTO_ID @"id" 16 | #define FLICKR_LATITUDE @"latitude" 17 | #define FLICKR_LONGITUDE @"longitude" 18 | #define FLICKR_PHOTO_OWNER @"ownername" 19 | #define FLICKR_PHOTO_PLACE_NAME @"derived_place" // doesn't work for Stanford photos 20 | #define FLICKR_TAGS @"tags" 21 | 22 | #define NSLOG_FLICKR NO 23 | 24 | typedef enum { 25 | FlickrPhotoFormatSquare = 1, // 75x75 26 | FlickrPhotoFormatLarge = 2, // 1024x768 27 | FlickrPhotoFormatOriginal = 64 // at least 1024x768 28 | } FlickrPhotoFormat; 29 | 30 | @interface FlickrFetcher : NSObject 31 | 32 | // fetch a bunch of Flickr photo dictionaries using the Flickr API 33 | + (NSArray *)stanfordPhotos; 34 | 35 | // get the URL for a Flickr photo given a dictionary of Flickr photo info 36 | // (which can be gotten using stanfordPhotos or latestGeoreferencedPhotos) 37 | + (NSURL *)urlForPhoto:(NSDictionary *)photo format:(FlickrPhotoFormat)format; 38 | 39 | // fetch a bunch of recently taken georeferenced Flickr photo dictionaries 40 | + (NSArray *)latestGeoreferencedPhotos; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Interfaces/FlickrFetcher/FlickrFetcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // FlickrFetcher.m 3 | // 4 | // Created for Stanford CS193p Winter 2013. 5 | // Copyright 2013 Stanford University. All rights reserved. 6 | // 7 | 8 | #import "FlickrFetcher.h" 9 | #import "FlickrAPIKey.h" 10 | 11 | #define FLICKR_PLACE_ID @"place_id" 12 | 13 | @implementation FlickrFetcher 14 | 15 | + (NSDictionary *)executeFlickrFetch:(NSString *)query 16 | { 17 | query = [NSString stringWithFormat:@"%@&format=json&nojsoncallback=1&api_key=%@", query, FlickrAPIKey]; 18 | query = [query stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 19 | if (NSLOG_FLICKR) NSLog(@"[%@ %@] sent %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), query); 20 | NSData *jsonData = [[NSString stringWithContentsOfURL:[NSURL URLWithString:query] encoding:NSUTF8StringEncoding error:nil] dataUsingEncoding:NSUTF8StringEncoding]; 21 | NSError *error = nil; 22 | NSDictionary *results = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves error:&error] : nil; 23 | if (error) NSLog(@"[%@ %@] JSON error: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), error.localizedDescription); 24 | if (NSLOG_FLICKR) NSLog(@"[%@ %@] received %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), results); 25 | return results; 26 | } 27 | 28 | + (NSArray *)topPlaces 29 | { 30 | NSString *request = [NSString stringWithFormat:@"http://api.flickr.com/services/rest/?method=flickr.places.getTopPlacesList&place_type_id=7"]; 31 | return [[self executeFlickrFetch:request] valueForKeyPath:@"places.place"]; 32 | } 33 | 34 | + (NSArray *)stanfordPhotos 35 | { 36 | NSString *request = @"http://api.flickr.com/services/rest/?user_id=48247111@N07&format=json&nojsoncallback=1&extras=original_format,tags,description,geo,date_upload,owner_name&page=1&method=flickr.photos.search"; 37 | return [[self executeFlickrFetch:request] valueForKeyPath:@"photos.photo"]; 38 | } 39 | 40 | + (NSArray *)photosInPlace:(NSDictionary *)place maxResults:(int)maxResults 41 | { 42 | NSArray *photos = nil; 43 | NSString *placeId = [place objectForKey:FLICKR_PLACE_ID]; 44 | if (placeId) { 45 | NSString *request = [NSString stringWithFormat:@"http://api.flickr.com/services/rest/?method=flickr.photos.search&place_id=%@&per_page=%d&extras=original_format,tags,description,geo,date_upload,owner_name,place_url", placeId, maxResults]; 46 | NSString *placeName = [place objectForKey:FLICKR_PLACE_NAME]; 47 | photos = [[self executeFlickrFetch:request] valueForKeyPath:@"photos.photo"]; 48 | for (NSMutableDictionary *photo in photos) { 49 | [photo setObject:placeName forKey:FLICKR_PHOTO_PLACE_NAME]; 50 | } 51 | } 52 | return photos; 53 | } 54 | 55 | + (NSArray *)latestGeoreferencedPhotos 56 | { 57 | NSString *request = [NSString stringWithFormat:@"http://api.flickr.com/services/rest/?method=flickr.photos.search&per_page=500&license=1,2,4,7&has_geo=1&extras=original_format,tags,description,geo,date_upload,owner_name,place_url"]; 58 | return [[self executeFlickrFetch:request] valueForKeyPath:@"photos.photo"]; 59 | } 60 | 61 | + (NSString *)urlStringForPhoto:(NSDictionary *)photo format:(FlickrPhotoFormat)format 62 | { 63 | id farm = [photo objectForKey:@"farm"]; 64 | id server = [photo objectForKey:@"server"]; 65 | id photo_id = [photo objectForKey:@"id"]; 66 | id secret = [photo objectForKey:@"secret"]; 67 | if (format == FlickrPhotoFormatOriginal) secret = [photo objectForKey:@"originalsecret"]; 68 | 69 | NSString *fileType = @"jpg"; 70 | if (format == FlickrPhotoFormatOriginal) fileType = [photo objectForKey:@"originalformat"]; 71 | 72 | if (!farm || !server || !photo_id || !secret) return nil; 73 | 74 | NSString *formatString = @"s"; 75 | switch (format) { 76 | case FlickrPhotoFormatSquare: formatString = @"s"; break; 77 | case FlickrPhotoFormatLarge: formatString = @"b"; break; 78 | // case FlickrPhotoFormatThumbnail: formatString = @"t"; break; 79 | // case FlickrPhotoFormatSmall: formatString = @"m"; break; 80 | // case FlickrPhotoFormatMedium500: formatString = @"-"; break; 81 | // case FlickrPhotoFormatMedium640: formatString = @"z"; break; 82 | case FlickrPhotoFormatOriginal: formatString = @"o"; break; 83 | } 84 | 85 | return [NSString stringWithFormat:@"http://farm%@.static.flickr.com/%@/%@_%@_%@.%@", farm, server, photo_id, secret, formatString, fileType]; 86 | } 87 | 88 | + (NSURL *)urlForPhoto:(NSDictionary *)photo format:(FlickrPhotoFormat)format 89 | { 90 | return [NSURL URLWithString:[self urlStringForPhoto:photo format:format]]; 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Interfaces/Resources/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Interfaces/Resources/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/SPoT-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | pt.mindclick.cs193p.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | iPhonePhotoBrowsing 29 | UIMainStoryboardFile~ipad 30 | iPadPhotoBrowsing 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationLandscapeLeft 45 | UIInterfaceOrientationLandscapeRight 46 | UIInterfaceOrientationPortraitUpsideDown 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/SPoT-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_3_0 10 | #warning "This project uses features only available in iOS SDK 3.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | 18 | // Custom definitions 19 | #import "Helpers.h" 20 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Support/Config/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // Debug.xcconfig 3 | // 4 | // Created by Hugo Ferreira on 2013/10/10. 5 | // Copyright (c) 2013 Mindclick. All rights reserved. 6 | // 7 | 8 | #include "Warnings.xcconfig" 9 | 10 | // Override some of the warnings settings 11 | GCC_TREAT_WARNINGS_AS_ERRORS = NO 12 | 13 | // Setup code coverage analysis 14 | // http://blog.nwoolls.com/2013/02/08/visualizing-code-coverage-with-xcode/ 15 | GCC_GENERATE_TEST_COVERAGE_FILES = YES 16 | GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES 17 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Support/Config/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // MoreWarnings.xcconfig 3 | // 4 | // Created by Steven Fisher: 5 | // http://tewha.net/2010/11/xcode-warnings/ 6 | // See also: 7 | // http://boredzo.org/blog/archives/2009-11-07/warnings 8 | // 9 | 10 | GCC_WARN_CHECK_SWITCH_STATEMENTS = YES 11 | GCC_WARN_SHADOW = YES 12 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES 13 | GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES 14 | GCC_WARN_ABOUT_RETURN_TYPE = YES 15 | GCC_WARN_MISSING_PARENTHESES = YES 16 | GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES 17 | GCC_WARN_ABOUT_MISSING_NEWLINE = YES 18 | GCC_WARN_SIGN_COMPARE = YES 19 | GCC_WARN_UNDECLARED_SELECTOR = YES 20 | GCC_WARN_UNUSED_FUNCTION = YES 21 | GCC_WARN_UNUSED_LABEL = YES 22 | GCC_WARN_UNUSED_VALUE = YES 23 | GCC_WARN_UNUSED_VARIABLE = YES 24 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES 25 | GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES 26 | GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES 27 | GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES 28 | GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = YES 29 | GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES 30 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES 31 | CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES 32 | CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES 33 | OTHER_CFLAGS = -Wextra -Wno-unused-parameter 34 | GCC_TREAT_WARNINGS_AS_ERRORS = YES 35 | RUN_CLANG_STATIC_ANALYZER = YES 36 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Support/Helpers/ArrayCount.h: -------------------------------------------------------------------------------- 1 | /** 2 | "Get the number of elements of an array passed by parameter in C?" 3 | http://stackoverflow.com/a/19415065/1380781 4 | */ 5 | #define C_ARRAY_COUNT(array) (sizeof(array)/sizeof(*(array))) 6 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Support/Helpers/Helpers.h: -------------------------------------------------------------------------------- 1 | // 2 | // Helpers.h 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/13. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #ifndef SPoT_Helpers 10 | #define SPoT_Helpers 11 | 12 | #import "ArrayCount.h" 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Use Cases/ImageSupplierDataSource.h: -------------------------------------------------------------------------------- 1 | // 2 | // ImageSupplierDataSource.h 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/15. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TagEntity.h" 11 | 12 | @protocol ImageSupplierDataSource 13 | 14 | /** @return List of `TagEntity` objects. */ 15 | - (NSArray *)listTagsAvailable; 16 | 17 | /** 18 | @param tagsToExclude List of objects defining the ignored tags, evaluated as strings. 19 | @return List of `TagEntity` objects. 20 | */ 21 | - (NSArray *)listTagsExcluding:(NSArray *)tagsToExclude; 22 | 23 | /** @return List of `ImageEntity` objects. */ 24 | - (NSArray *)listImagesRecentlyUploaded; 25 | 26 | /** @return List of `ImageEntity` objects. */ 27 | - (NSArray *)listImagesWithTag:(TagEntity *)tag; 28 | 29 | /** @return List of `ImageEntity` objects. */ 30 | - (NSArray *)listMax:(NSUInteger)number imagesWithTag:(TagEntity *)tag; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Use Cases/ImageViewingInteractor.h: -------------------------------------------------------------------------------- 1 | // 2 | // PhotoViewingInteractor.h 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/07. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TagEntity.h" 11 | 12 | @interface ImageViewingInteractor : NSObject 13 | 14 | - (NSArray *)listImagesByTag:(TagEntity *)tag; 15 | - (NSArray *)listRecentImages; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Use Cases/ImageViewingInteractor.m: -------------------------------------------------------------------------------- 1 | // 2 | // PhotoViewingInteractor.m 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/07. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "ImageViewingInteractor.h" 10 | #import "ImageSupplierGateway.h" /* FIXME: Isn't this breaking the Dependency Rule? */ 11 | 12 | @interface ImageViewingInteractor () 13 | 14 | @property (strong, nonatomic) id photoSupplier; 15 | 16 | @end 17 | 18 | @implementation ImageViewingInteractor 19 | 20 | #pragma mark - Properties 21 | 22 | - (id)photoSupplier 23 | { 24 | if (!_photoSupplier) _photoSupplier = [ImageSupplierGateway defaultDataSource]; 25 | return _photoSupplier; 26 | } 27 | 28 | #pragma mark - Methods 29 | 30 | - (NSArray *)listImagesByTag:(TagEntity *)tag 31 | { 32 | return [self.photoSupplier listImagesWithTag:tag]; 33 | } 34 | 35 | - (NSArray *)listRecentImages 36 | { 37 | /* TODO: Load from [NSUserDefaults standardUserDefaults] if exists, fetch online otherwise */ 38 | NSArray *photos = [self.photoSupplier listImagesRecentlyUploaded]; 39 | photos = [self removeDuplicates:photos]; 40 | photos = [self sortByMostRecent:photos]; 41 | return photos; 42 | } 43 | 44 | - (NSArray *)removeDuplicates:(NSArray *)photos 45 | { 46 | /* TODO: implement this someday (based on FLICKR_PHOTO_ID) */ 47 | return photos; 48 | } 49 | 50 | - (NSArray *)sortByMostRecent:(NSArray *)photos 51 | { 52 | /* TODO: implement this someday */ 53 | return photos; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Use Cases/TagListingInteractor.h: -------------------------------------------------------------------------------- 1 | // 2 | // TagListingInteractor.h 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/07. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TagListingInteractor : NSObject 12 | 13 | - (NSArray *)listAllTags; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/Use Cases/TagListingInteractor.m: -------------------------------------------------------------------------------- 1 | // 2 | // TagListingInteractor.m 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/07. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "TagListingInteractor.h" 10 | #import "ImageSupplierGateway.h" /* FIXME: Isn't this breaking the Dependency Rule? */ 11 | 12 | static NSString * const TagListExclusions[] = { @"cs193pspot", @"portrait", @"landscape" }; 13 | 14 | @interface TagListingInteractor () 15 | 16 | @property (strong, nonatomic) id photoSupplier; 17 | 18 | @end 19 | 20 | @implementation TagListingInteractor 21 | 22 | #pragma mark - Properties 23 | 24 | - (id)photoSupplier 25 | { 26 | if (!_photoSupplier) _photoSupplier = [ImageSupplierGateway defaultDataSource]; 27 | return _photoSupplier; 28 | } 29 | 30 | #pragma mark - Methods 31 | 32 | - (NSArray *)listAllTags 33 | { 34 | NSArray *tagsToIgnore = [NSArray arrayWithObjects:TagListExclusions count:C_ARRAY_COUNT(TagListExclusions)]; 35 | return [self.photoSupplier listTagsExcluding:tagsToIgnore]; 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoT/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/07. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoTTests/FlickrFetcherLearningTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // FlickrFetcherLearningTests.m 3 | // SPoT 4 | // 5 | // Created by Hugo Ferreira on 2013/11/12. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "FlickrFetcher.h" 11 | 12 | @interface FlickrFetcherLearningTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation FlickrFetcherLearningTests 17 | 18 | - (void)testStanfordPhotosReturnsTags 19 | { 20 | NSArray *photos = [FlickrFetcher stanfordPhotos]; 21 | NSArray *tagsPerPhoto = [photos valueForKey:FLICKR_TAGS]; 22 | NSArray *allTagsUsed = [[tagsPerPhoto componentsJoinedByString:@" "] componentsSeparatedByString:@" "]; 23 | NSSet *uniqueTagList = [NSSet setWithArray:allTagsUsed]; 24 | XCTAssert([uniqueTagList count] < [allTagsUsed count], @"Duplicate tags should have disappeared"); 25 | } 26 | 27 | - (void)testRecentPhotosReturnsLimitedSize 28 | { 29 | NSArray *photos = [FlickrFetcher latestGeoreferencedPhotos]; 30 | XCTAssertEqual([photos count] <= 250, @"Too many photos received"); 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoTTests/SPoTTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | pt.mindclick.cs193p.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoTTests/SPoTTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPoTTests.m 3 | // SPoTTests 4 | // 5 | // Created by Hugo Ferreira on 2013/11/07. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SPoTTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation SPoTTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /2013 Winter/SPoT/SPoTTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /2013 Winter/Shutterbug/Shutterbug.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /2013 Winter/Shutterbug/Shutterbug/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // Shutterbug 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /2013 Winter/Shutterbug/Shutterbug/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // Shutterbug 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @implementation AppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application 32 | { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application 37 | { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application 42 | { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /2013 Winter/Shutterbug/Shutterbug/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/Shutterbug/Shutterbug/Default-568h@2x.png -------------------------------------------------------------------------------- /2013 Winter/Shutterbug/Shutterbug/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/Shutterbug/Shutterbug/Default.png -------------------------------------------------------------------------------- /2013 Winter/Shutterbug/Shutterbug/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/Shutterbug/Shutterbug/Default@2x.png -------------------------------------------------------------------------------- /2013 Winter/Shutterbug/Shutterbug/FlickrFetcher/FlickrAPIKey.h: -------------------------------------------------------------------------------- 1 | // 2 | // FlickrAPIKey.h 3 | // 4 | // Created for Stanford CS193p Winter 2013. 5 | // Copyright 2013 Stanford University 6 | // All rights reserved. 7 | // 8 | // Get your own key! 9 | // No Flickr fetches will work without the API Key! 10 | // 11 | 12 | #define FlickrAPIKey @"9a0554259914a86fb9e7eb014e4e5d52" 13 | -------------------------------------------------------------------------------- /2013 Winter/Shutterbug/Shutterbug/FlickrFetcher/FlickrFetcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // FlickrFetcher.h 3 | // 4 | // Created for Stanford CS193p Winter 2013. 5 | // Copyright 2013 Stanford University 6 | // All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | // tags in the photo dictionaries returned from stanfordPhotos or latestGeoreferencedPhotos 12 | 13 | #define FLICKR_PHOTO_TITLE @"title" 14 | #define FLICKR_PHOTO_DESCRIPTION @"description._content" // must use valueForKeyPath: on this one 15 | #define FLICKR_PLACE_NAME @"_content" 16 | #define FLICKR_PHOTO_ID @"id" 17 | #define FLICKR_LATITUDE @"latitude" 18 | #define FLICKR_LONGITUDE @"longitude" 19 | #define FLICKR_PHOTO_OWNER @"ownername" 20 | #define FLICKR_PHOTO_PLACE_NAME @"derived_place" // doesn't work for Stanford photos 21 | #define FLICKR_TAGS @"tags" 22 | 23 | #define NSLOG_FLICKR NO 24 | 25 | typedef enum { 26 | FlickrPhotoFormatSquare = 1, // 75x75 27 | FlickrPhotoFormatLarge = 2, // 1024x768 28 | FlickrPhotoFormatOriginal = 64 // at least 1024x768 29 | } FlickrPhotoFormat; 30 | 31 | @interface FlickrFetcher : NSObject 32 | 33 | // fetch a bunch of Flickr photo dictionaries using the Flickr API 34 | + (NSArray *)stanfordPhotos; 35 | 36 | // get the URL for a Flickr photo given a dictionary of Flickr photo info 37 | // (which can be gotten using stanfordPhotos or latestGeoreferencedPhotos) 38 | + (NSURL *)urlForPhoto:(NSDictionary *)photo format:(FlickrPhotoFormat)format; 39 | 40 | // fetch a bunch of recently taken georeferenced Flickr photo dictionaries 41 | + (NSArray *)latestGeoreferencedPhotos; 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /2013 Winter/Shutterbug/Shutterbug/FlickrFetcher/FlickrFetcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // FlickrFetcher.m 3 | // 4 | // Created for Stanford CS193p Winter 2013. 5 | // Copyright 2013 Stanford University 6 | // All rights reserved. 7 | // 8 | 9 | #import "FlickrFetcher.h" 10 | #import "FlickrAPIKey.h" 11 | 12 | #define FLICKR_PLACE_ID @"place_id" 13 | 14 | @implementation FlickrFetcher 15 | 16 | + (NSDictionary *)executeFlickrFetch:(NSString *)query 17 | { 18 | query = [NSString stringWithFormat:@"%@&format=json&nojsoncallback=1&api_key=%@", query, FlickrAPIKey]; 19 | query = [query stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 20 | if (NSLOG_FLICKR) NSLog(@"[%@ %@] sent %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), query); 21 | NSData *jsonData = [[NSString stringWithContentsOfURL:[NSURL URLWithString:query] encoding:NSUTF8StringEncoding error:nil] dataUsingEncoding:NSUTF8StringEncoding]; 22 | NSError *error = nil; 23 | NSDictionary *results = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves error:&error] : nil; 24 | if (error) NSLog(@"[%@ %@] JSON error: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), error.localizedDescription); 25 | if (NSLOG_FLICKR) NSLog(@"[%@ %@] received %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), results); 26 | return results; 27 | } 28 | 29 | + (NSArray *)topPlaces 30 | { 31 | NSString *request = [NSString stringWithFormat:@"http://api.flickr.com/services/rest/?method=flickr.places.getTopPlacesList&place_type_id=7"]; 32 | return [[self executeFlickrFetch:request] valueForKeyPath:@"places.place"]; 33 | } 34 | 35 | + (NSArray *)stanfordPhotos 36 | { 37 | NSString *request = @"http://api.flickr.com/services/rest/?user_id=48247111@N07&format=json&nojsoncallback=1&extras=original_format,tags,description,geo,date_upload,owner_name&page=1&method=flickr.photos.search"; 38 | return [[self executeFlickrFetch:request] valueForKeyPath:@"photos.photo"]; 39 | } 40 | 41 | + (NSArray *)photosInPlace:(NSDictionary *)place maxResults:(int)maxResults 42 | { 43 | NSArray *photos = nil; 44 | NSString *placeId = [place objectForKey:FLICKR_PLACE_ID]; 45 | if (placeId) { 46 | NSString *request = [NSString stringWithFormat:@"http://api.flickr.com/services/rest/?method=flickr.photos.search&place_id=%@&per_page=%d&extras=original_format,tags,description,geo,date_upload,owner_name,place_url", placeId, maxResults]; 47 | NSString *placeName = [place objectForKey:FLICKR_PLACE_NAME]; 48 | photos = [[self executeFlickrFetch:request] valueForKeyPath:@"photos.photo"]; 49 | for (NSMutableDictionary *photo in photos) { 50 | [photo setObject:placeName forKey:FLICKR_PHOTO_PLACE_NAME]; 51 | } 52 | } 53 | return photos; 54 | } 55 | 56 | + (NSArray *)latestGeoreferencedPhotos 57 | { 58 | NSString *request = [NSString stringWithFormat:@"http://api.flickr.com/services/rest/?method=flickr.photos.search&per_page=500&license=1,2,4,7&has_geo=1&extras=original_format,tags,description,geo,date_upload,owner_name,place_url"]; 59 | return [[self executeFlickrFetch:request] valueForKeyPath:@"photos.photo"]; 60 | } 61 | 62 | + (NSString *)urlStringForPhoto:(NSDictionary *)photo format:(FlickrPhotoFormat)format 63 | { 64 | id farm = [photo objectForKey:@"farm"]; 65 | id server = [photo objectForKey:@"server"]; 66 | id photo_id = [photo objectForKey:@"id"]; 67 | id secret = [photo objectForKey:@"secret"]; 68 | if (format == FlickrPhotoFormatOriginal) secret = [photo objectForKey:@"originalsecret"]; 69 | 70 | NSString *fileType = @"jpg"; 71 | if (format == FlickrPhotoFormatOriginal) fileType = [photo objectForKey:@"originalformat"]; 72 | 73 | if (!farm || !server || !photo_id || !secret) return nil; 74 | 75 | NSString *formatString = @"s"; 76 | switch (format) { 77 | case FlickrPhotoFormatSquare: formatString = @"s"; break; 78 | case FlickrPhotoFormatLarge: formatString = @"b"; break; 79 | // case FlickrPhotoFormatThumbnail: formatString = @"t"; break; 80 | // case FlickrPhotoFormatSmall: formatString = @"m"; break; 81 | // case FlickrPhotoFormatMedium500: formatString = @"-"; break; 82 | // case FlickrPhotoFormatMedium640: formatString = @"z"; break; 83 | case FlickrPhotoFormatOriginal: formatString = @"o"; break; 84 | } 85 | 86 | return [NSString stringWithFormat:@"http://farm%@.static.flickr.com/%@/%@_%@_%@.%@", farm, server, photo_id, secret, formatString, fileType]; 87 | } 88 | 89 | + (NSURL *)urlForPhoto:(NSDictionary *)photo format:(FlickrPhotoFormat)format 90 | { 91 | return [NSURL URLWithString:[self urlStringForPhoto:photo format:format]]; 92 | } 93 | 94 | @end 95 | -------------------------------------------------------------------------------- /2013 Winter/Shutterbug/Shutterbug/FlickrPhotoTVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // FlickrPhotoTVC.h 3 | // Shutterbug 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | // Will call setImageURL: as part of any "Show Image" segue. 9 | 10 | #import 11 | 12 | @interface FlickrPhotoTVC : UITableViewController 13 | 14 | // the Model for this VC 15 | // an array of dictionaries of Flickr information 16 | // obtained using Flickr API 17 | // (e.g. FlickrFetcher will obtain such an array of dictionaries) 18 | @property (nonatomic, strong) NSArray *photos; // of NSDictionary 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /2013 Winter/Shutterbug/Shutterbug/FlickrPhotoTVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // FlickrPhotoTVC.m 3 | // Shutterbug 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import "FlickrPhotoTVC.h" 10 | #import "FlickrFetcher.h" 11 | 12 | @implementation FlickrPhotoTVC 13 | 14 | // sets the Model 15 | // reloads the UITableView (since Model is changing) 16 | 17 | - (void)setPhotos:(NSArray *)photos 18 | { 19 | _photos = photos; 20 | [self.tableView reloadData]; 21 | } 22 | 23 | #pragma mark - Segue 24 | 25 | // prepares for the "Show Image" segue by seeing if the destination view controller of the segue 26 | // understands the method "setImageURL:" 27 | // if it does, it sends setImageURL: to the destination view controller with 28 | // the URL of the photo that was selected in the UITableView as the argument 29 | // also sets the title of the destination view controller to the photo's title 30 | 31 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 32 | { 33 | if ([sender isKindOfClass:[UITableViewCell class]]) { 34 | NSIndexPath *indexPath = [self.tableView indexPathForCell:sender]; 35 | if (indexPath) { 36 | if ([segue.identifier isEqualToString:@"Show Image"]) { 37 | if ([segue.destinationViewController respondsToSelector:@selector(setImageURL:)]) { 38 | NSURL *url = [FlickrFetcher urlForPhoto:self.photos[indexPath.row] format:FlickrPhotoFormatLarge]; 39 | [segue.destinationViewController performSelector:@selector(setImageURL:) withObject:url]; 40 | [segue.destinationViewController setTitle:[self titleForRow:indexPath.row]]; 41 | } 42 | } 43 | } 44 | } 45 | } 46 | 47 | #pragma mark - UITableViewDataSource 48 | 49 | // lets the UITableView know how many rows it should display 50 | // in this case, just the count of dictionaries in the Model's array 51 | 52 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 53 | { 54 | return [self.photos count]; 55 | } 56 | 57 | // a helper method that looks in the Model for the photo dictionary at the given row 58 | // and gets the title out of it 59 | 60 | - (NSString *)titleForRow:(NSUInteger)row 61 | { 62 | return [self.photos[row][FLICKR_PHOTO_TITLE] description]; // description because could be NSNull 63 | } 64 | 65 | // a helper method that looks in the Model for the photo dictionary at the given row 66 | // and gets the owner of the photo out of it 67 | 68 | - (NSString *)subtitleForRow:(NSUInteger)row 69 | { 70 | return [self.photos[row][FLICKR_PHOTO_OWNER] description]; // description because could be NSNull 71 | } 72 | 73 | // loads up a table view cell with the title and owner of the photo at the given row in the Model 74 | 75 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 76 | { 77 | static NSString *CellIdentifier = @"Flickr Photo"; 78 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; 79 | 80 | // Configure the cell... 81 | cell.textLabel.text = [self titleForRow:indexPath.row]; 82 | cell.detailTextLabel.text = [self subtitleForRow:indexPath.row]; 83 | 84 | return cell; 85 | } 86 | 87 | @end 88 | -------------------------------------------------------------------------------- /2013 Winter/Shutterbug/Shutterbug/HawaiiImageViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // HawaiiImageViewController.h 3 | // Shutterbug 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import "ImageViewController.h" 10 | 11 | @interface HawaiiImageViewController : ImageViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /2013 Winter/Shutterbug/Shutterbug/HawaiiImageViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // HawaiiImageViewController.m 3 | // Shutterbug 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import "HawaiiImageViewController.h" 10 | 11 | @implementation HawaiiImageViewController 12 | 13 | // purpose of this entire VC is just to set its Model to a particular photo 14 | 15 | - (void)viewDidLoad 16 | { 17 | [super viewDidLoad]; 18 | self.imageURL = [[NSURL alloc] initWithString:@"http://images.apple.com/v/iphone/gallery/a/images/photo_3.jpg"]; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /2013 Winter/Shutterbug/Shutterbug/ImageViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ImageViewController.h 3 | // Shutterbug 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ImageViewController : UIViewController 12 | 13 | // the Model for this VC 14 | // simply the URL of a UIImage-compatible image (jpg, png, etc.) 15 | @property (nonatomic, strong) NSURL *imageURL; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /2013 Winter/Shutterbug/Shutterbug/ImageViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ImageViewController.m 3 | // Shutterbug 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import "ImageViewController.h" 10 | 11 | @interface ImageViewController () 12 | @property (weak, nonatomic) IBOutlet UIScrollView *scrollView; 13 | @property (strong, nonatomic) UIImageView *imageView; 14 | @end 15 | 16 | @implementation ImageViewController 17 | 18 | // resets the image whenever the URL changes 19 | 20 | - (void)setImageURL:(NSURL *)imageURL 21 | { 22 | _imageURL = imageURL; 23 | [self resetImage]; 24 | } 25 | 26 | // fetches the data from the URL 27 | // turns it into an image 28 | // adjusts the scroll view's content size to fit the image 29 | // sets the image as the image view's image 30 | 31 | - (void)resetImage 32 | { 33 | if (self.scrollView) { 34 | self.scrollView.contentSize = CGSizeZero; 35 | self.imageView.image = nil; 36 | 37 | NSData *imageData = [[NSData alloc] initWithContentsOfURL:self.imageURL]; 38 | UIImage *image = [[UIImage alloc] initWithData:imageData]; 39 | if (image) { 40 | self.scrollView.zoomScale = 1.0; 41 | self.scrollView.contentSize = image.size; 42 | self.imageView.image = image; 43 | self.imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height); 44 | } 45 | } 46 | } 47 | 48 | // lazy instantiation 49 | 50 | - (UIImageView *)imageView 51 | { 52 | if (!_imageView) _imageView = [[UIImageView alloc] initWithFrame:CGRectZero]; 53 | return _imageView; 54 | } 55 | 56 | // returns the view which will be zoomed when the user pinches 57 | // in this case, it is the image view, obviously 58 | // (there are no other subviews of the scroll view in its content area) 59 | 60 | - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView 61 | { 62 | return self.imageView; 63 | } 64 | 65 | // add the image view to the scroll view's content area 66 | // setup zooming by setting min and max zoom scale 67 | // and setting self to be the scroll view's delegate 68 | // resets the image in case URL was set before outlets (e.g. scroll view) were set 69 | 70 | - (void)viewDidLoad 71 | { 72 | [super viewDidLoad]; 73 | [self.scrollView addSubview:self.imageView]; 74 | self.scrollView.minimumZoomScale = 0.2; 75 | self.scrollView.maximumZoomScale = 5.0; 76 | self.scrollView.delegate = self; 77 | [self resetImage]; 78 | } 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /2013 Winter/Shutterbug/Shutterbug/LatestFlickrPhotosTVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // LatestFlickrPhotosTVC.h 3 | // Shutterbug 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import "FlickrPhotoTVC.h" 10 | 11 | @interface LatestFlickrPhotosTVC : FlickrPhotoTVC 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /2013 Winter/Shutterbug/Shutterbug/LatestFlickrPhotosTVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // LatestFlickrPhotosTVC.m 3 | // Shutterbug 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import "LatestFlickrPhotosTVC.h" 10 | #import "FlickrFetcher.h" 11 | 12 | @implementation LatestFlickrPhotosTVC 13 | 14 | // purpose of this entire VC is just to set its Model by querying Flickr using FlickrFetcher 15 | 16 | - (void)viewDidLoad 17 | { 18 | [super viewDidLoad]; 19 | self.photos = [FlickrFetcher latestGeoreferencedPhotos]; 20 | } 21 | 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /2013 Winter/Shutterbug/Shutterbug/Shutterbug-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | edu.stanford.cs193p.instructor.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | MainStoryboard 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /2013 Winter/Shutterbug/Shutterbug/Shutterbug-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'Shutterbug' target in the 'Shutterbug' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_5_0 8 | #warning "This project uses features only available in iOS SDK 5.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /2013 Winter/Shutterbug/Shutterbug/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /2013 Winter/Shutterbug/Shutterbug/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Shutterbug 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2013 Stanford University. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/J♠.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "J♠.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "J♠@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/J♠.imageset/J♠.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/J♠.imageset/J♠.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/J♠.imageset/J♠@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/J♠.imageset/J♠@2x.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/J♣.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "J♣.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "J♣@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/J♣.imageset/J♣.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/J♣.imageset/J♣.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/J♣.imageset/J♣@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/J♣.imageset/J♣@2x.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/J♥.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "J♥.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "J♥@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/J♥.imageset/J♥.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/J♥.imageset/J♥.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/J♥.imageset/J♥@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/J♥.imageset/J♥@2x.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/J♦.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "J♦.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "J♦@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/J♦.imageset/J♦.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/J♦.imageset/J♦.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/J♦.imageset/J♦@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/J♦.imageset/J♦@2x.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/K♠.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "K♠.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "K♠@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/K♠.imageset/K♠.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/K♠.imageset/K♠.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/K♠.imageset/K♠@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/K♠.imageset/K♠@2x.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/K♣.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "K♣.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "K♣@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/K♣.imageset/K♣.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/K♣.imageset/K♣.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/K♣.imageset/K♣@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/K♣.imageset/K♣@2x.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/K♥.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "K♥.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "K♥@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/K♥.imageset/K♥.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/K♥.imageset/K♥.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/K♥.imageset/K♥@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/K♥.imageset/K♥@2x.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/K♦.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "K♦.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "K♦@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/K♦.imageset/K♦.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/K♦.imageset/K♦.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/K♦.imageset/K♦@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/K♦.imageset/K♦@2x.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/Q♠.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Q♠.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "Q♠@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/Q♠.imageset/Q♠.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/Q♠.imageset/Q♠.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/Q♠.imageset/Q♠@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/Q♠.imageset/Q♠@2x.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/Q♣.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Q♣.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "Q♣@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/Q♣.imageset/Q♣.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/Q♣.imageset/Q♣.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/Q♣.imageset/Q♣@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/Q♣.imageset/Q♣@2x.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/Q♥.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Q♥.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "Q♥@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/Q♥.imageset/Q♥.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/Q♥.imageset/Q♥.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/Q♥.imageset/Q♥@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/Q♥.imageset/Q♥@2x.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/Q♦.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Q♦.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "Q♦@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/Q♦.imageset/Q♦.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/Q♦.imageset/Q♦.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/Q♦.imageset/Q♦@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/Face Cards/Q♦.imageset/Q♦@2x.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/cardback.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "cardback.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/Images.xcassets/cardback.imageset/cardback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hugocf/stanford-cs193p-ios/2f49e8735831b076cf2e672adce4a9312bb8e733/2013 Winter/SuperCard/SuperCard/Images.xcassets/cardback.imageset/cardback.png -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/PlayingCardView.h: -------------------------------------------------------------------------------- 1 | // 2 | // PlayingCardView.h 3 | // SuperCard 4 | // 5 | // Created by Hugo Ferreira on 2013/09/26. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PlayingCardView : UIView 12 | 13 | @property (nonatomic) NSUInteger rank; 14 | @property (strong, nonatomic) NSString *suit; 15 | @property (nonatomic, getter = isFaceUp) BOOL faceUp; 16 | 17 | - (void)pinch:(UIGestureRecognizer *)gesture; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/SuperCard-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | pt.mindclick.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/SuperCard-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/SuperCardAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // SuperCardAppDelegate.h 3 | // SuperCard 4 | // 5 | // Created by Hugo Ferreira on 2013/09/26. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SuperCardAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/SuperCardAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // SuperCardAppDelegate.m 3 | // SuperCard 4 | // 5 | // Created by Hugo Ferreira on 2013/09/26. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "SuperCardAppDelegate.h" 10 | 11 | @implementation SuperCardAppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application 32 | { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application 37 | { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application 42 | { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/SuperCardViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SuperCardViewController.h 3 | // SuperCard 4 | // 5 | // Created by Hugo Ferreira on 2013/09/26. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SuperCardViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/SuperCardViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SuperCardViewController.m 3 | // SuperCard 4 | // 5 | // Created by Hugo Ferreira on 2013/09/26. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import "SuperCardViewController.h" 10 | #import "PlayingCardView.h" 11 | 12 | @interface SuperCardViewController () 13 | @property (weak, nonatomic) IBOutlet PlayingCardView *playingCard; 14 | @end 15 | 16 | @implementation SuperCardViewController 17 | 18 | #pragma mark - Properties 19 | 20 | - (void)setPlayingCard:(PlayingCardView *)playingCard 21 | { 22 | _playingCard = playingCard; 23 | // TODO: Import Matchismo model and draw a random paying card every time it flips 24 | playingCard.rank = 13; // K 25 | playingCard.suit = @"♥"; 26 | [playingCard addGestureRecognizer:[[UIPinchGestureRecognizer alloc] initWithTarget:self.playingCard 27 | action:@selector(pinch:)]]; 28 | } 29 | 30 | #pragma mark - Methods 31 | 32 | - (IBAction)swipeCard:(UISwipeGestureRecognizer *)sender 33 | { 34 | [UIView transitionWithView:self.playingCard 35 | duration:0.5 36 | options:UIViewAnimationOptionTransitionFlipFromLeft 37 | animations:^{ 38 | self.playingCard.faceUp = !self.playingCard.isFaceUp; 39 | } 40 | completion:nil]; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCard/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SuperCard 4 | // 5 | // Created by Hugo Ferreira on 2013/09/26. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "SuperCardAppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([SuperCardAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCardTests/SuperCardTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | pt.mindclick.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCardTests/SuperCardTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // SuperCardTests.m 3 | // SuperCardTests 4 | // 5 | // Created by Hugo Ferreira on 2013/09/26. 6 | // Copyright (c) 2013 Mindclick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SuperCardTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation SuperCardTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /2013 Winter/SuperCard/SuperCardTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Stanford CS193P - iPad and iPhone Application Development 2 | *by Paul Hegarty* 3 | 4 | ## Stanford's class page 5 | 6 | * [CS 193P iPhone Application Development](http://cs193p.stanford.edu/) 7 | 8 | ## 2014-15 Winter 9 | 10 | Updated for iOS 8 and Swift. 11 | 12 | * Stanford's [Downloads (2014-15 Winter)](http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2015-winter) 13 | * *2015-02-08: Course still in progress… See the [main Stanford’s class page](http://cs193p.stanford.edu/) for the supporting materials.* 14 | * iTunes U: [Developing iOS 8 Apps with Swift](https://itunes.apple.com/us/course/developing-ios-8-apps-swift/id961180099) 15 | 16 | ## 2013-14 Fall 17 | 18 | Updated for iOS 7. 19 | 20 | * Stanford's [Downloads (2013-14 Fall)](http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2013-fall) 21 | * iTunes U: [Developing iOS 7 Apps for iPhone and iPad](https://itunes.apple.com/en/course/developing-ios-7-apps-for/id733644550) 22 | 23 | ## 2012-13 Winter 24 | 25 | Updated for iOS 6. 26 | 27 | * Stanford's [Downloads (2012-13 Winter)](http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2013-winter) 28 | * iTunes U: [Coding Together: Developing Apps for iPhone and iPad (Winter 2013)](https://itunes.apple.com/en/course/coding-together-developing/id593208016) 29 | 30 | ## 2011-12 Fall 31 | 32 | Learn how to create iOS 5 apps. 33 | 34 | * Stanford's [Downloads (2011-12 Fall)](http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2011-fall) 35 | * iTunes U: [iPad and iPhone Application Development (HD) iTunes](http://itunes.apple.com/itunes-u/ipad-iphone-application-development/id473757255?mt=10) 36 | 37 | --------------------------------------------------------------------------------