├── .gitignore
├── scheme@2x.png
├── Early Math Prototype Player
├── finger_demo.m4v
├── Images.xcassets
│ └── AppIcon.appiconset
│ │ ├── Bitmap.png
│ │ ├── Bitmap@2x.png
│ │ └── Contents.json
├── Early Math Prototype Player-Bridging-Header.h
├── Info.plist
├── InstructionsViewController.swift
├── LaunchScreen.storyboard
├── AppDelegate.swift
├── ReadmeViewController.swift
├── PlayerViewController.swift
├── PrototypeProvider.swift
├── Instructions.xib
└── PrototypeListCollectionViewController.swift
├── Early Math Prototype Player.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
├── xcuserdata
│ └── jason.xcuserdatad
│ │ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ └── Early Math Prototype Player.xcscheme
└── project.pbxproj
├── .gitmodules
└── readme.md
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | *.xccheckout
3 |
4 | *.xcbkptlist
5 |
--------------------------------------------------------------------------------
/scheme@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Khan/Early-Math-Prototype-Player/HEAD/scheme@2x.png
--------------------------------------------------------------------------------
/Early Math Prototype Player/finger_demo.m4v:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Khan/Early-Math-Prototype-Player/HEAD/Early Math Prototype Player/finger_demo.m4v
--------------------------------------------------------------------------------
/Early Math Prototype Player/Images.xcassets/AppIcon.appiconset/Bitmap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Khan/Early-Math-Prototype-Player/HEAD/Early Math Prototype Player/Images.xcassets/AppIcon.appiconset/Bitmap.png
--------------------------------------------------------------------------------
/Early Math Prototype Player/Images.xcassets/AppIcon.appiconset/Bitmap@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Khan/Early-Math-Prototype-Player/HEAD/Early Math Prototype Player/Images.xcassets/AppIcon.appiconset/Bitmap@2x.png
--------------------------------------------------------------------------------
/Early Math Prototype Player.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Early Math Prototype Player/Early Math Prototype Player-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // Use this file to import your target's public headers that you would like to expose to Swift.
3 | //
4 |
5 | #import
6 | #import "FLAnimatedImage.h"
7 | #import "FLAnimatedImageView.h"
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "Early Math Prototype Player/Early-Math-Prototypes"]
2 | path = Early Math Prototype Player/Early-Math-Prototypes
3 | url = git@github.com:Khan/Early-Math-Prototypes.git
4 | [submodule "Prototope"]
5 | path = Prototope
6 | url = git@github.com:Khan/Prototope.git
7 | [submodule "ThirdParty/MMMarkdown"]
8 | path = ThirdParty/MMMarkdown
9 | url = https://github.com/mdiep/MMMarkdown
10 | [submodule "ThirdParty/FLAnimatedImage"]
11 | path = ThirdParty/FLAnimatedImage
12 | url = https://github.com/Flipboard/FLAnimatedImage.git
13 |
--------------------------------------------------------------------------------
/Early Math Prototype Player.xcodeproj/xcuserdata/jason.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Early Math Prototype Player.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 962558F51B39AF1A005E4360
16 |
17 | primary
18 |
19 |
20 | 9625590A1B39AF1A005E4360
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Early Math Prototype Player/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "ipad",
5 | "size" : "29x29",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "ipad",
10 | "size" : "29x29",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "ipad",
15 | "size" : "40x40",
16 | "scale" : "1x"
17 | },
18 | {
19 | "idiom" : "ipad",
20 | "size" : "40x40",
21 | "scale" : "2x"
22 | },
23 | {
24 | "size" : "76x76",
25 | "idiom" : "ipad",
26 | "filename" : "Bitmap.png",
27 | "scale" : "1x"
28 | },
29 | {
30 | "size" : "76x76",
31 | "idiom" : "ipad",
32 | "filename" : "Bitmap@2x.png",
33 | "scale" : "2x"
34 | },
35 | {
36 | "idiom" : "ipad",
37 | "size" : "83.5x83.5",
38 | "scale" : "2x"
39 | }
40 | ],
41 | "info" : {
42 | "version" : 1,
43 | "author" : "xcode"
44 | }
45 | }
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Early-Math-Prototype-Player
2 | Play the [Early Math Prototypes](https://github.com/Khan/Early-Math-Prototypes) embedded in an iPad app.
3 |
4 | Running the app on your iPad:
5 |
6 | - Get Xcode from the Mac App Store if you don't already have it
7 | - Clone this git repository to your computer.
8 | - If you're not familiar with git, you can use the Github app to do it.
9 | - Alternatively, you can do the following from the Terminal app
10 |
11 | git clone --recursive git@github.com:Khan/Early-Math-Prototype-Player.git
12 | - Open the project file (Early Math Prototype Player.xcodeproj) in Xcode
13 | - Make sure you pick the correct app to run and device in Xcode if it's not already chosen.
14 |
15 |
16 |
17 | - Build and run the app on your Simulator or iPad.
18 |
19 | ## Navigating
20 |
21 | To navigate back to the list of prototypes, swipe to the right with three fingers. If you're using the simulator, you can also press Escape.
22 |
--------------------------------------------------------------------------------
/Early Math Prototype Player/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | org.khanacademy.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 |
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations~ipad
34 |
35 | UIInterfaceOrientationLandscapeLeft
36 | UIInterfaceOrientationLandscapeRight
37 |
38 | UIViewControllerBasedStatusBarAppearance
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Early Math Prototype Player/InstructionsViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // InstructionsViewController.swift
3 | // Early Math Prototype Player
4 | //
5 | // Created by Andy Matuschak on 7/5/15.
6 | // Copyright (c) 2015 Khan Academy. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import AVFoundation
11 |
12 | class InstructionsViewController: UIViewController {
13 | // This state shouldn't be entangled here, but this is throwaway...
14 | static var userHasSeenInstructions: Bool {
15 | return NSUserDefaults.standardUserDefaults().boolForKey(InstructionsViewController.userHasSeenInstructionsKey)
16 | }
17 |
18 | init() {
19 | super.init(nibName: "Instructions", bundle: nil)
20 | }
21 |
22 | required init?(coder aDecoder: NSCoder) {
23 | fatalError("init(coder:) has not been implemented")
24 | }
25 |
26 | private static let userHasSeenInstructionsKey = "UserHasSeenInstructions"
27 | @IBOutlet weak var videoPlayerView: AVPlayerView!
28 | @IBOutlet weak var simulatorNoteLabel: UILabel!
29 |
30 | override func viewWillAppear(animated: Bool) {
31 | NSUserDefaults.standardUserDefaults().setBool(true, forKey: InstructionsViewController.userHasSeenInstructionsKey)
32 |
33 | simulatorNoteLabel.hidden = TARGET_IPHONE_SIMULATOR == 0
34 |
35 | videoPlayerView.playerLayer.player = AVPlayer(URL: NSBundle.mainBundle().URLForResource("finger_demo", withExtension: "m4v")!)
36 | videoPlayerView.playerLayer.player!.play()
37 | NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.loopPlayer), name: AVPlayerItemDidPlayToEndTimeNotification, object: videoPlayerView.playerLayer.player!.currentItem)
38 | }
39 |
40 | override func viewDidDisappear(animated: Bool) {
41 | NSNotificationCenter.defaultCenter().removeObserver(self, name: AVPlayerItemDidPlayToEndTimeNotification, object: videoPlayerView.playerLayer.player!.currentItem)
42 | }
43 |
44 | @objc private func loopPlayer() {
45 | videoPlayerView.playerLayer.player!.seekToTime(kCMTimeZero)
46 | videoPlayerView.playerLayer.player!.play()
47 | }
48 |
49 | @IBAction func handleContinue(sender: AnyObject) {
50 | self.dismissViewControllerAnimated(true, completion: nil)
51 | }
52 | }
53 |
54 | @objc(AVPlayerView) class AVPlayerView: UIView {
55 | override class func layerClass() -> AnyClass { return AVPlayerLayer.self }
56 | var playerLayer: AVPlayerLayer { return layer as! AVPlayerLayer }
57 | }
58 |
--------------------------------------------------------------------------------
/Early Math Prototype Player/LaunchScreen.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 |
--------------------------------------------------------------------------------
/Early Math Prototype Player/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Protomath
4 | //
5 | // Created by Jason Brennan on 2015-06-22.
6 | // Copyright (c) 2015 Khan Academy. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate, UINavigationControllerDelegate, UIGestureRecognizerDelegate {
13 |
14 | var window: UIWindow?
15 | var prototypeListCollectionViewController: PrototypeListCollectionViewController!
16 | var navigationController: UINavigationController!
17 |
18 |
19 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
20 |
21 | application.idleTimerDisabled = true
22 |
23 | window = UIWindow(frame: UIScreen.mainScreen().bounds)
24 |
25 | prototypeListCollectionViewController = PrototypeListCollectionViewController()
26 |
27 | navigationController = UINavigationController(rootViewController: prototypeListCollectionViewController)
28 | navigationController.delegate = self
29 |
30 | window?.rootViewController = navigationController
31 |
32 | let swipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(self.handleSwipeBackGesture(_:)))
33 | swipeGestureRecognizer.numberOfTouchesRequired = 3
34 | swipeGestureRecognizer.direction = .Right
35 | swipeGestureRecognizer.delegate = self
36 | window?.addGestureRecognizer(swipeGestureRecognizer)
37 | window?.makeKeyAndVisible()
38 |
39 | return true
40 | }
41 |
42 | func handleSwipeBackGesture(gesture: UIGestureRecognizer!) {
43 | self.navigationController.popToRootViewControllerAnimated(true)
44 | }
45 |
46 | func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailByGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
47 | return false
48 | }
49 |
50 | func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
51 | return true
52 | }
53 |
54 | // Hacks to show/hide navigation bar in prototypes so hack wow
55 | func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
56 | if viewController is PlayerViewController {
57 | navigationController.setNavigationBarHidden(true, animated: true)
58 | UIApplication.sharedApplication().setStatusBarHidden(true, withAnimation: .None) // view controller based status bar APIs interacts poorly with hiding/showing the navigation bar
59 | } else {
60 | navigationController.setNavigationBarHidden(false, animated: true)
61 | UIApplication.sharedApplication().setStatusBarHidden(false, withAnimation: .None)
62 | }
63 | }
64 | }
65 |
66 |
--------------------------------------------------------------------------------
/Early Math Prototype Player/ReadmeViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ReadmeViewController.swift
3 | // Early Math Prototype Player
4 | //
5 | // Created by Andy Matuschak on 6/24/15.
6 | // Copyright (c) 2015 Khan Academy. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /** This view controller shows readmes for prototypes. */
12 | class ReadmeViewController: UIViewController {
13 | let prototype: Prototype
14 |
15 | lazy var startButton: UIButton = {
16 | let button = UIButton(type: .System)
17 | button.setTitle("Start", forState: .Normal)
18 | button.titleLabel!.font = UIFont.systemFontOfSize(24)
19 | return button
20 | }()
21 |
22 | lazy var webView: UIWebView = {
23 | let webView = UIWebView()
24 | webView.scrollView.alwaysBounceVertical = false
25 | webView.backgroundColor = UIColor.clearColor()
26 | return webView
27 | }()
28 |
29 | init(prototype: Prototype) {
30 | precondition(prototype.readmeURL != nil)
31 | self.prototype = prototype
32 |
33 | super.init(nibName: nil, bundle: nil)
34 |
35 | navigationItem.title = prototype.name
36 | }
37 |
38 | required init?(coder aDecoder: NSCoder) {
39 | fatalError("init(coder:) has not been implemented")
40 | }
41 |
42 | private var readmeHTMLRepresentation: String {
43 | let markdownSource = try! NSString(contentsOfURL: prototype.readmeURL!, encoding: NSUTF8StringEncoding)
44 |
45 | let body: NSString
46 | do {
47 | body = try MMMarkdown.HTMLStringWithMarkdown(String(markdownSource), extensions: .GitHubFlavored)
48 | } catch {
49 | body = "Couldn't parse README: \(error)"
50 | }
51 | let systemFontName = UIFont.systemFontOfSize(12).fontName
52 | return "\(body)"
53 | }
54 |
55 | override func loadView() {
56 | super.loadView()
57 | view.backgroundColor = UIColor.whiteColor()
58 |
59 | startButton.addTarget(self, action: #selector(self.startPrototype), forControlEvents: .TouchUpInside)
60 | view.addSubview(startButton)
61 |
62 | webView.loadHTMLString(readmeHTMLRepresentation, baseURL: NSURL(fileURLWithPath: "/"))
63 | view.addSubview(webView)
64 |
65 | view.setNeedsLayout()
66 | }
67 |
68 | override func viewWillLayoutSubviews() {
69 | // what is the difference between a view controller and a view anyways?!?
70 | startButton.sizeToFit()
71 | startButton.center.x = view.bounds.size.width / 2.0
72 | startButton.center.y = view.bounds.size.height - startButton.bounds.size.height / 2.0 - 50
73 |
74 | webView.frame.origin.y = topLayoutGuide.length + 40
75 | webView.frame.size.width = 500
76 | webView.frame.size.height = startButton.frame.origin.y - webView.frame.origin.y
77 | webView.center.x = startButton.center.x
78 | }
79 |
80 | @objc private func startPrototype() {
81 | let player = PlayerViewController(path: prototype.mainFileURL)
82 | navigationController!.pushViewController(player, animated: true) // what is a "control flow" anyway so lazy so prototype
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/Early Math Prototype Player/PlayerViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PlayerViewController.swift
3 | // Prototope
4 | //
5 | // Created by Jason Brennan on 2015-06-22.
6 | // Copyright (c) 2015 Khan Academy. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Prototope
11 | import PrototopeJSBridge
12 |
13 |
14 | /** This view controller hosts and plays Prototypes. */
15 | class PlayerViewController: UIViewController {
16 | var context: Context!
17 | let jsPath: NSURL
18 |
19 | init(path: NSURL) {
20 | self.jsPath = path
21 | super.init(nibName: nil, bundle: nil)
22 | }
23 |
24 | required init?(coder aDecoder: NSCoder) {
25 | fatalError("init(coder:) has not been implemented")
26 | }
27 |
28 |
29 | override func viewDidLoad() {
30 | super.viewDidLoad()
31 | view.backgroundColor = UIColor.whiteColor()
32 |
33 |
34 | let prototypeDirectoryURL = self.jsPath.URLByDeletingLastPathComponent!
35 |
36 | let imageProvider = {
37 | (name: String) -> UIImage? in
38 | let scale = UIScreen.mainScreen().scale
39 | let filenameWithScale = (name.stringByAppendingString("@\(Int(scale))x") as NSString).stringByAppendingPathExtension("png")!
40 | let filename = (name as NSString).stringByAppendingPathExtension("png")!
41 |
42 | let scalePath = prototypeDirectoryURL.URLByAppendingPathComponent(filenameWithScale)
43 | let noScalePath = prototypeDirectoryURL.URLByAppendingPathComponent(filename)
44 |
45 | let loadImage: (String) -> UIImage? = { path in
46 | let image = UIImage(contentsOfFile: path)
47 | return image
48 | }
49 |
50 | return loadImage(scalePath.path!) ?? loadImage(noScalePath.path!)
51 | }
52 |
53 | let soundProvider = {
54 | (name: String) -> NSData? in
55 | let fileManager = NSFileManager.defaultManager()
56 | for fileExtension in Sound.supportedExtensions {
57 | let URL = prototypeDirectoryURL.URLByAppendingPathComponent(name).URLByAppendingPathExtension(fileExtension)
58 | if fileManager.fileExistsAtPath(URL.path!) {
59 | return try? NSData(contentsOfURL: URL, options: [])
60 | }
61 | }
62 | return nil
63 | }
64 |
65 |
66 | let defaultEnvironment = Environment.defaultEnvironmentWithRootView(self.view)
67 | Environment.currentEnvironment = Environment(
68 | rootView: view,
69 | imageProvider: imageProvider,
70 | soundProvider: soundProvider,
71 | fontProvider: defaultEnvironment.fontProvider,
72 | exceptionHandler: defaultEnvironment.exceptionHandler
73 | )
74 |
75 | runJSPrototope()
76 | }
77 |
78 | override func viewWillAppear(animated: Bool) {
79 | if !InstructionsViewController.userHasSeenInstructions {
80 | self.presentViewController(InstructionsViewController(), animated: true, completion: nil)
81 | }
82 | }
83 |
84 |
85 | func runJSPrototope() {
86 |
87 | context = Context()
88 | context.exceptionHandler = { value in
89 | let lineNumber = value.objectForKeyedSubscript("line")
90 | print("Exception on line \(lineNumber): \(value)")
91 | }
92 | context.consoleLogHandler = { message in
93 | print(message)
94 | }
95 |
96 | let script = try! NSString(contentsOfURL: self.jsPath, encoding: NSUTF8StringEncoding)
97 | context.evaluateScript(script as String)
98 | }
99 |
100 |
101 | func handleKeyCommand(command: UIKeyCommand!) {
102 | switch command.input {
103 | case UIKeyInputEscape:
104 | self.navigationController?.popToRootViewControllerAnimated(true)
105 | default:
106 | return
107 | }
108 | }
109 |
110 | // needed to let vc handle keypresses
111 | override func canBecomeFirstResponder() -> Bool {
112 | return true
113 | }
114 |
115 | override var keyCommands: [UIKeyCommand]? {
116 | get {
117 | let escape = UIKeyCommand(input: UIKeyInputEscape, modifierFlags: [], action: #selector(self.handleKeyCommand(_:)))
118 | return [escape]
119 | }
120 | }
121 |
122 | }
--------------------------------------------------------------------------------
/Early Math Prototype Player/PrototypeProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PrototypeProvider.swift
3 | // Prototope
4 | //
5 | // Created by Jason Brennan on 2015-06-22.
6 | // Copyright (c) 2015 Khan Academy. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 |
12 | /** Provides Prototype objects loaded from the application's bundle. */
13 | struct PrototypeProvider {
14 |
15 | private static let prototypeDirectory = "Early-Math-Prototypes"
16 | private static let prototypeHiddenMarker = "hideme" // If this file is present in a prototype directory, we skip it in the UI.
17 | let prototypes: [Prototype]
18 |
19 | init() {
20 | if let resourcePath = NSBundle.mainBundle().resourcePath {
21 | let earlyMathPath = (resourcePath as NSString).stringByAppendingPathComponent(PrototypeProvider.prototypeDirectory)
22 | let files = try! NSFileManager.defaultManager().contentsOfDirectoryAtPath(earlyMathPath)
23 | let validPrototypeDirectories = files.filter { prototypeDirectory in
24 | PrototypeProvider.prototypeIsValidAtPath((earlyMathPath as NSString).stringByAppendingPathComponent(prototypeDirectory))
25 | }
26 | self.prototypes = validPrototypeDirectories.map { prototypeDirectory in
27 | let prototypeURL = NSURL(fileURLWithPath: (earlyMathPath as NSString).stringByAppendingPathComponent(prototypeDirectory), isDirectory: true)
28 | return Prototype(directoryURL: prototypeURL, name: prototypeDirectory)!
29 | }
30 | } else {
31 | self.prototypes = []
32 | }
33 |
34 | }
35 |
36 | private static func prototypeIsValidAtPath(path: String) -> Bool {
37 | var isDirectory: ObjCBool = ObjCBool(false)
38 | let fileManager = NSFileManager.defaultManager()
39 | if fileManager.fileExistsAtPath(path, isDirectory: &isDirectory) {
40 | let prototypeIsMarkedAsHidden = fileManager.fileExistsAtPath((path as NSString).stringByAppendingPathComponent(PrototypeProvider.prototypeHiddenMarker))
41 | return isDirectory.boolValue && !prototypeIsMarkedAsHidden
42 | } else {
43 | return false
44 | }
45 | }
46 | }
47 |
48 |
49 | /** Prototype..er, type. Represents a prototype directory on disk with reference to the main javascript file. Derived from Protorope.Prototype. */
50 | struct Prototype {
51 | let mainFileURL: NSURL
52 | let readmeURL: NSURL?
53 | let previewImageURL: NSURL?
54 | let name: String
55 | }
56 |
57 |
58 | extension Prototype {
59 | init?(directoryURL: NSURL, name: String) {
60 |
61 | if !directoryURL.fileURL { return nil }
62 |
63 | let path = directoryURL.filePathURL!.path!
64 |
65 | var isDirectory: ObjCBool = ObjCBool(false)
66 | let exists = NSFileManager.defaultManager().fileExistsAtPath(path, isDirectory: &isDirectory)
67 | if !exists {
68 | print("File does not exist: \(path)")
69 | return nil
70 | }
71 |
72 | var mainScriptPath: String
73 |
74 | if isDirectory.boolValue {
75 | do {
76 | let contents = try NSFileManager.defaultManager().contentsOfDirectoryAtPath(path) as [String]?
77 |
78 | let javaScriptFiles = contents!.filter { ($0 as NSString).pathExtension == "js" }
79 | switch javaScriptFiles.count {
80 | case 0:
81 | print("No JavaScript files found in \(path)")
82 | return nil
83 | case 1:
84 | mainScriptPath = (path as NSString).stringByAppendingPathComponent(javaScriptFiles.first!)
85 | default:
86 | print("Multiple JavaScript files found in \(path): \(javaScriptFiles)")
87 | return nil
88 | }
89 |
90 | let readmeFiles = contents!.filter { $0.lowercaseString.hasPrefix("readme.md") }
91 | switch readmeFiles.count {
92 | case 0:
93 | readmeURL = nil
94 | case 1:
95 | readmeURL = NSURL(fileURLWithPath: (path as NSString).stringByAppendingPathComponent(readmeFiles[0]))
96 | default:
97 | print("Multiple README files found in \(path): \(readmeFiles)")
98 | return nil
99 | }
100 |
101 | let previewFiles = contents!.filter {
102 | let normalizedName = $0.lowercaseString
103 | return normalizedName.hasPrefix("preview") &&
104 | ["png", "gif", "jpg"].contains((normalizedName as NSString).pathExtension)
105 | }
106 | switch previewFiles.count {
107 | case 0:
108 | previewImageURL = nil
109 | case 1:
110 | previewImageURL = NSURL(fileURLWithPath: (path as NSString).stringByAppendingPathComponent(previewFiles[0]))
111 | default:
112 | print("Multiple preview images found in \(path): \(previewFiles)")
113 | return nil
114 | }
115 | } catch {
116 | print("Couldn't read directory \(path): \(error)")
117 | return nil
118 | }
119 | } else {
120 | readmeURL = nil
121 | previewImageURL = nil
122 | mainScriptPath = path
123 | }
124 |
125 | self.name = name
126 | self.mainFileURL = NSURL(fileURLWithPath: mainScriptPath)
127 | }
128 | }
129 |
130 |
--------------------------------------------------------------------------------
/Early Math Prototype Player.xcodeproj/xcuserdata/jason.xcuserdatad/xcschemes/Early Math Prototype Player.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
65 |
66 |
75 |
77 |
83 |
84 |
85 |
86 |
87 |
88 |
94 |
96 |
102 |
103 |
104 |
105 |
107 |
108 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/Early Math Prototype Player/Instructions.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
32 |
41 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/Early Math Prototype Player/PrototypeListCollectionViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PrototypeListCollectionViewController.swift
3 | // Protomath
4 | //
5 | // Created by Jason Brennan on 2015-06-22.
6 | // Copyright (c) 2015 Khan Academy. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 |
12 | /** Shows a list of Prototypes loaded from the application's bundle and lets you tap to play. */
13 | class PrototypeListCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
14 |
15 | private let prototypeProvider = PrototypeProvider()
16 | private let layout: UICollectionViewFlowLayout = {
17 | let layout = UICollectionViewFlowLayout()
18 | layout.minimumInteritemSpacing = 0
19 | layout.minimumLineSpacing = 0
20 | return layout
21 | }()
22 |
23 | init() {
24 | super.init(collectionViewLayout: layout)
25 | }
26 |
27 | required init?(coder aDecoder: NSCoder) {
28 | fatalError("init(coder:) has intentionally not been implemented")
29 | }
30 |
31 | override func viewDidLoad() {
32 | super.viewDidLoad()
33 | collectionView!.registerClass(PrototypePreviewCell.self, forCellWithReuseIdentifier: PrototypePreviewCell.reuseIdentifier)
34 | collectionView!.backgroundColor = UIColor.whiteColor()
35 | navigationItem.title = "Prototypes"
36 | }
37 |
38 | override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
39 | return prototypeProvider.prototypes.count
40 | }
41 |
42 | override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
43 | return 1
44 | }
45 |
46 | override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
47 | let cell = collectionView.dequeueReusableCellWithReuseIdentifier(PrototypePreviewCell.reuseIdentifier, forIndexPath: indexPath) as! PrototypePreviewCell
48 | cell.prototype = self.prototypeProvider.prototypes[indexPath.item]
49 | return cell
50 | }
51 |
52 | override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
53 | let prototype = self.prototypeProvider.prototypes[indexPath.item]
54 |
55 | if prototype.readmeURL != nil {
56 | navigationController?.pushViewController(ReadmeViewController(prototype: prototype), animated: true)
57 | } else {
58 | navigationController?.pushViewController(PlayerViewController(path: prototype.mainFileURL), animated: true)
59 | }
60 | }
61 |
62 | override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
63 | layout.invalidateLayout()
64 | }
65 |
66 | func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
67 | let width = collectionView.bounds.size.width / round(collectionView.bounds.size.width / PrototypePreviewCell.desiredSize.width)
68 | let height = width * PrototypePreviewCell.desiredSize.height / PrototypePreviewCell.desiredSize.width
69 | return CGSize(width: floor(width), height: floor(height))
70 | }
71 |
72 | }
73 |
74 |
75 | private class PrototypePreviewCell: UICollectionViewCell {
76 | static let desiredSize = CGSize(width: 256, height: 192)
77 | static let labelPadding: CGFloat = 15
78 |
79 | var prototype: Prototype? {
80 | didSet {
81 | imageView.backgroundColor = prototype?.colorRepresentation
82 |
83 | if let previewImageURL = prototype?.previewImageURL {
84 | precondition(previewImageURL.fileURL)
85 | if previewImageURL.pathExtension! == "gif" {
86 | // ultra lazy async lol
87 | dispatch_async(dispatch_get_global_queue(0, 0)) {
88 | let gifData = NSData(contentsOfURL: previewImageURL)
89 | let image = FLAnimatedImage(animatedGIFData: gifData)
90 | dispatch_async(dispatch_get_main_queue()) {
91 | if self.prototype?.previewImageURL == .Some(previewImageURL) {
92 | self.imageView.animatedImage = image
93 | }
94 | }
95 | }
96 | } else {
97 | imageView.image = UIImage(contentsOfFile: previewImageURL.path!)
98 | }
99 | } else {
100 | imageView.image = nil
101 | imageView.animatedImage = nil
102 | }
103 |
104 | label.text = prototype?.name
105 | setNeedsLayout()
106 | }
107 | }
108 |
109 | let imageView: FLAnimatedImageView = {
110 | let imageView = FLAnimatedImageView()
111 | imageView.contentMode = .ScaleAspectFill
112 | return imageView
113 | }()
114 |
115 | let label: UILabel = {
116 | let label = UILabel()
117 | label.numberOfLines = 2
118 | return label
119 | }()
120 |
121 | let labelBar: UIVisualEffectView
122 | let labelVibrancyContainer: UIVisualEffectView
123 |
124 | override init(frame: CGRect) {
125 | let blurEffect = UIBlurEffect(style: .Dark)
126 | labelBar = UIVisualEffectView(effect: blurEffect)
127 | labelVibrancyContainer = UIVisualEffectView(effect: UIVibrancyEffect(forBlurEffect: blurEffect))
128 |
129 | super.init(frame: frame)
130 |
131 | contentView.addSubview(imageView)
132 |
133 | contentView.addSubview(labelBar)
134 |
135 | labelBar.contentView.addSubview(labelVibrancyContainer)
136 | labelVibrancyContainer.contentView.addSubview(label)
137 |
138 | }
139 |
140 | private override func layoutSubviews() {
141 | super.layoutSubviews()
142 |
143 | imageView.frame = contentView.bounds
144 |
145 | let labelSizeThatFits = label.sizeThatFits(CGSize(width: contentView.bounds.size.width, height: CGFloat.max))
146 | let labelHeight = labelSizeThatFits.height + 2 * PrototypePreviewCell.labelPadding
147 |
148 | labelBar.frame = CGRect(
149 | x: 0,
150 | y: contentView.bounds.size.height - labelHeight,
151 | width: contentView.bounds.size.width,
152 | height: labelHeight
153 | )
154 | labelVibrancyContainer.frame = labelBar.bounds
155 | label.frame = CGRectInset(labelVibrancyContainer.bounds, PrototypePreviewCell.labelPadding, 0)
156 | }
157 |
158 | required init?(coder aDecoder: NSCoder) {
159 | fatalError("init(coder:) has intentionally not been implemented")
160 | }
161 | }
162 |
163 | extension UICollectionViewCell {
164 | /** Provides a default reuse identifier for cells. */
165 | class var reuseIdentifier: String { return NSStringFromClass(self.self) }
166 | }
167 |
168 | extension Prototype {
169 | private var colorRepresentation: UIColor {
170 | let hue = CGFloat(name.hash % Int(Int16.max)) / CGFloat(Int16.max)
171 | return UIColor(hue: hue, saturation: 0.8, brightness: 0.96, alpha: 1)
172 | }
173 | }
--------------------------------------------------------------------------------
/Early Math Prototype Player.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 962558FC1B39AF1A005E4360 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 962558FB1B39AF1A005E4360 /* AppDelegate.swift */; };
11 | 962559031B39AF1A005E4360 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 962559021B39AF1A005E4360 /* Images.xcassets */; };
12 | 9625591C1B39AF72005E4360 /* PrototypeListCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9625591B1B39AF72005E4360 /* PrototypeListCollectionViewController.swift */; };
13 | 9625591E1B39AF80005E4360 /* PlayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9625591D1B39AF80005E4360 /* PlayerViewController.swift */; };
14 | 962559211B39AFA6005E4360 /* PrototypeProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 962559201B39AFA6005E4360 /* PrototypeProvider.swift */; };
15 | 962559231B39AFB9005E4360 /* Early-Math-Prototypes in Resources */ = {isa = PBXBuildFile; fileRef = 962559221B39AFB9005E4360 /* Early-Math-Prototypes */; };
16 | 96DBF37F1B3AF25A003E0D46 /* Prototope.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96DBF36E1B3AF243003E0D46 /* Prototope.framework */; };
17 | 96DBF3801B3AF25A003E0D46 /* Prototope.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 96DBF36E1B3AF243003E0D46 /* Prototope.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
18 | 96DBF3831B3AF25A003E0D46 /* PrototopeJSBridge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96DBF3741B3AF243003E0D46 /* PrototopeJSBridge.framework */; };
19 | 96DBF3841B3AF25A003E0D46 /* PrototopeJSBridge.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 96DBF3741B3AF243003E0D46 /* PrototopeJSBridge.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
20 | 96DBF3901B3AFE68003E0D46 /* protoscope-bundle.js in Resources */ = {isa = PBXBuildFile; fileRef = 96DBF38F1B3AFE68003E0D46 /* protoscope-bundle.js */; };
21 | EB3CBCF61B3B2ADE0038AE64 /* ReadmeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB3CBCF51B3B2ADE0038AE64 /* ReadmeViewController.swift */; };
22 | EB7841D21B3BB121008E5160 /* libMMMarkdown-iOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EB7841C61B3BB114008E5160 /* libMMMarkdown-iOS.a */; };
23 | EB9530441B47080800E4E5C8 /* FLAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = EB9530411B47080800E4E5C8 /* FLAnimatedImage.m */; };
24 | EB9530451B47080800E4E5C8 /* FLAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = EB9530431B47080800E4E5C8 /* FLAnimatedImageView.m */; };
25 | EB9530F31B498A4D00E4E5C8 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EB9530F21B498A4D00E4E5C8 /* LaunchScreen.storyboard */; };
26 | EB95312B1B49D88700E4E5C8 /* finger_demo.m4v in Resources */ = {isa = PBXBuildFile; fileRef = EB95312A1B49D88700E4E5C8 /* finger_demo.m4v */; };
27 | EB95313B1B49D8DB00E4E5C8 /* InstructionsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB95313A1B49D8DB00E4E5C8 /* InstructionsViewController.swift */; };
28 | EBB48F5D1B4AFDB500850DA5 /* Instructions.xib in Resources */ = {isa = PBXBuildFile; fileRef = EB9531371B49D8C300E4E5C8 /* Instructions.xib */; };
29 | /* End PBXBuildFile section */
30 |
31 | /* Begin PBXContainerItemProxy section */
32 | 96DBF36D1B3AF243003E0D46 /* PBXContainerItemProxy */ = {
33 | isa = PBXContainerItemProxy;
34 | containerPortal = 96DBF35D1B3AF243003E0D46 /* Prototope.xcodeproj */;
35 | proxyType = 2;
36 | remoteGlobalIDString = EBE3A75619DF79C400A77736;
37 | remoteInfo = Prototope;
38 | };
39 | 96DBF36F1B3AF243003E0D46 /* PBXContainerItemProxy */ = {
40 | isa = PBXContainerItemProxy;
41 | containerPortal = 96DBF35D1B3AF243003E0D46 /* Prototope.xcodeproj */;
42 | proxyType = 2;
43 | remoteGlobalIDString = EB306C0919DF77CC00113FA3;
44 | remoteInfo = PrototopeTestApp;
45 | };
46 | 96DBF3711B3AF243003E0D46 /* PBXContainerItemProxy */ = {
47 | isa = PBXContainerItemProxy;
48 | containerPortal = 96DBF35D1B3AF243003E0D46 /* Prototope.xcodeproj */;
49 | proxyType = 2;
50 | remoteGlobalIDString = EB1C2A6C19E4D19B000DC2C1;
51 | remoteInfo = PrototopeTests;
52 | };
53 | 96DBF3731B3AF243003E0D46 /* PBXContainerItemProxy */ = {
54 | isa = PBXContainerItemProxy;
55 | containerPortal = 96DBF35D1B3AF243003E0D46 /* Prototope.xcodeproj */;
56 | proxyType = 2;
57 | remoteGlobalIDString = EB453D8F1A7AB0B2006F2A72;
58 | remoteInfo = PrototopeJSBridge;
59 | };
60 | 96DBF3751B3AF243003E0D46 /* PBXContainerItemProxy */ = {
61 | isa = PBXContainerItemProxy;
62 | containerPortal = 96DBF35D1B3AF243003E0D46 /* Prototope.xcodeproj */;
63 | proxyType = 2;
64 | remoteGlobalIDString = EB453D991A7AB0B2006F2A72;
65 | remoteInfo = PrototopeJSBridgeTests;
66 | };
67 | 96DBF3771B3AF243003E0D46 /* PBXContainerItemProxy */ = {
68 | isa = PBXContainerItemProxy;
69 | containerPortal = 96DBF35D1B3AF243003E0D46 /* Prototope.xcodeproj */;
70 | proxyType = 2;
71 | remoteGlobalIDString = EB6BFB801A857326002B4E6A;
72 | remoteInfo = Protocaster;
73 | };
74 | 96DBF3791B3AF243003E0D46 /* PBXContainerItemProxy */ = {
75 | isa = PBXContainerItemProxy;
76 | containerPortal = 96DBF35D1B3AF243003E0D46 /* Prototope.xcodeproj */;
77 | proxyType = 2;
78 | remoteGlobalIDString = EB6BFB911A857326002B4E6A;
79 | remoteInfo = ProtocasterTests;
80 | };
81 | 96DBF37B1B3AF243003E0D46 /* PBXContainerItemProxy */ = {
82 | isa = PBXContainerItemProxy;
83 | containerPortal = 96DBF35D1B3AF243003E0D46 /* Prototope.xcodeproj */;
84 | proxyType = 2;
85 | remoteGlobalIDString = EB6BFBB51A857920002B4E6A;
86 | remoteInfo = Protoscope;
87 | };
88 | 96DBF37D1B3AF243003E0D46 /* PBXContainerItemProxy */ = {
89 | isa = PBXContainerItemProxy;
90 | containerPortal = 96DBF35D1B3AF243003E0D46 /* Prototope.xcodeproj */;
91 | proxyType = 2;
92 | remoteGlobalIDString = EB6BFBC91A857921002B4E6A;
93 | remoteInfo = ProtoscopeTests;
94 | };
95 | 96DBF3811B3AF25A003E0D46 /* PBXContainerItemProxy */ = {
96 | isa = PBXContainerItemProxy;
97 | containerPortal = 96DBF35D1B3AF243003E0D46 /* Prototope.xcodeproj */;
98 | proxyType = 1;
99 | remoteGlobalIDString = EBE3A75519DF79C400A77736;
100 | remoteInfo = Prototope;
101 | };
102 | 96DBF3851B3AF25A003E0D46 /* PBXContainerItemProxy */ = {
103 | isa = PBXContainerItemProxy;
104 | containerPortal = 96DBF35D1B3AF243003E0D46 /* Prototope.xcodeproj */;
105 | proxyType = 1;
106 | remoteGlobalIDString = EB453D8E1A7AB0B2006F2A72;
107 | remoteInfo = PrototopeJSBridge;
108 | };
109 | EB7841C31B3BB114008E5160 /* PBXContainerItemProxy */ = {
110 | isa = PBXContainerItemProxy;
111 | containerPortal = EB7841BC1B3BB114008E5160 /* MMMarkdown.xcodeproj */;
112 | proxyType = 2;
113 | remoteGlobalIDString = BE813DD614F893EB00EC9469;
114 | remoteInfo = "MMMarkdown-Mac";
115 | };
116 | EB7841C51B3BB114008E5160 /* PBXContainerItemProxy */ = {
117 | isa = PBXContainerItemProxy;
118 | containerPortal = EB7841BC1B3BB114008E5160 /* MMMarkdown.xcodeproj */;
119 | proxyType = 2;
120 | remoteGlobalIDString = BE813E0E14F8961D00EC9469;
121 | remoteInfo = "MMMarkdown-iOS";
122 | };
123 | EB7841C71B3BB114008E5160 /* PBXContainerItemProxy */ = {
124 | isa = PBXContainerItemProxy;
125 | containerPortal = EB7841BC1B3BB114008E5160 /* MMMarkdown.xcodeproj */;
126 | proxyType = 2;
127 | remoteGlobalIDString = BE813DEA14F893EB00EC9469;
128 | remoteInfo = MMMarkdownTests;
129 | };
130 | EB7841C91B3BB114008E5160 /* PBXContainerItemProxy */ = {
131 | isa = PBXContainerItemProxy;
132 | containerPortal = EB7841BC1B3BB114008E5160 /* MMMarkdown.xcodeproj */;
133 | proxyType = 2;
134 | remoteGlobalIDString = BE813E1314F92B6100EC9469;
135 | remoteInfo = mmmarkdown;
136 | };
137 | EBAAD2B21D19C36300BB2C0A /* PBXContainerItemProxy */ = {
138 | isa = PBXContainerItemProxy;
139 | containerPortal = 96DBF35D1B3AF243003E0D46 /* Prototope.xcodeproj */;
140 | proxyType = 2;
141 | remoteGlobalIDString = 96A192331B531B3200D73B07;
142 | remoteInfo = PrototopeOSX;
143 | };
144 | EBAAD2B41D19C36300BB2C0A /* PBXContainerItemProxy */ = {
145 | isa = PBXContainerItemProxy;
146 | containerPortal = 96DBF35D1B3AF243003E0D46 /* Prototope.xcodeproj */;
147 | proxyType = 2;
148 | remoteGlobalIDString = 96A1923D1B531B3300D73B07;
149 | remoteInfo = PrototopeOSXTests;
150 | };
151 | /* End PBXContainerItemProxy section */
152 |
153 | /* Begin PBXCopyFilesBuildPhase section */
154 | 96DBF3871B3AF25A003E0D46 /* Embed Frameworks */ = {
155 | isa = PBXCopyFilesBuildPhase;
156 | buildActionMask = 2147483647;
157 | dstPath = "";
158 | dstSubfolderSpec = 10;
159 | files = (
160 | 96DBF3801B3AF25A003E0D46 /* Prototope.framework in Embed Frameworks */,
161 | 96DBF3841B3AF25A003E0D46 /* PrototopeJSBridge.framework in Embed Frameworks */,
162 | );
163 | name = "Embed Frameworks";
164 | runOnlyForDeploymentPostprocessing = 0;
165 | };
166 | /* End PBXCopyFilesBuildPhase section */
167 |
168 | /* Begin PBXFileReference section */
169 | 962558F61B39AF1A005E4360 /* Early Math.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Early Math.app"; sourceTree = BUILT_PRODUCTS_DIR; };
170 | 962558FA1B39AF1A005E4360 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
171 | 962558FB1B39AF1A005E4360 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
172 | 962559021B39AF1A005E4360 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
173 | 9625591B1B39AF72005E4360 /* PrototypeListCollectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrototypeListCollectionViewController.swift; sourceTree = ""; };
174 | 9625591D1B39AF80005E4360 /* PlayerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlayerViewController.swift; sourceTree = ""; };
175 | 962559201B39AFA6005E4360 /* PrototypeProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrototypeProvider.swift; sourceTree = ""; };
176 | 962559221B39AFB9005E4360 /* Early-Math-Prototypes */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "Early-Math-Prototypes"; sourceTree = ""; };
177 | 96DBF35D1B3AF243003E0D46 /* Prototope.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Prototope.xcodeproj; path = Prototope/Prototope.xcodeproj; sourceTree = SOURCE_ROOT; };
178 | 96DBF38F1B3AFE68003E0D46 /* protoscope-bundle.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "protoscope-bundle.js"; sourceTree = ""; };
179 | EB3CBCF51B3B2ADE0038AE64 /* ReadmeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReadmeViewController.swift; sourceTree = ""; };
180 | EB7841BC1B3BB114008E5160 /* MMMarkdown.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = MMMarkdown.xcodeproj; path = ThirdParty/MMMarkdown/MMMarkdown.xcodeproj; sourceTree = SOURCE_ROOT; };
181 | EB7841D31B3BB13D008E5160 /* Early Math Prototype Player-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Early Math Prototype Player-Bridging-Header.h"; sourceTree = ""; };
182 | EB9530401B47080800E4E5C8 /* FLAnimatedImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FLAnimatedImage.h; path = ThirdParty/FLAnimatedImage/FLAnimatedImageDemo/FLAnimatedImage/FLAnimatedImage.h; sourceTree = SOURCE_ROOT; };
183 | EB9530411B47080800E4E5C8 /* FLAnimatedImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FLAnimatedImage.m; path = ThirdParty/FLAnimatedImage/FLAnimatedImageDemo/FLAnimatedImage/FLAnimatedImage.m; sourceTree = SOURCE_ROOT; };
184 | EB9530421B47080800E4E5C8 /* FLAnimatedImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FLAnimatedImageView.h; path = ThirdParty/FLAnimatedImage/FLAnimatedImageDemo/FLAnimatedImage/FLAnimatedImageView.h; sourceTree = SOURCE_ROOT; };
185 | EB9530431B47080800E4E5C8 /* FLAnimatedImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FLAnimatedImageView.m; path = ThirdParty/FLAnimatedImage/FLAnimatedImageDemo/FLAnimatedImage/FLAnimatedImageView.m; sourceTree = SOURCE_ROOT; };
186 | EB9530F21B498A4D00E4E5C8 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; };
187 | EB95312A1B49D88700E4E5C8 /* finger_demo.m4v */ = {isa = PBXFileReference; lastKnownFileType = file; path = finger_demo.m4v; sourceTree = ""; };
188 | EB9531371B49D8C300E4E5C8 /* Instructions.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = Instructions.xib; sourceTree = ""; };
189 | EB95313A1B49D8DB00E4E5C8 /* InstructionsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InstructionsViewController.swift; sourceTree = ""; };
190 | /* End PBXFileReference section */
191 |
192 | /* Begin PBXFrameworksBuildPhase section */
193 | 962558F31B39AF1A005E4360 /* Frameworks */ = {
194 | isa = PBXFrameworksBuildPhase;
195 | buildActionMask = 2147483647;
196 | files = (
197 | EB7841D21B3BB121008E5160 /* libMMMarkdown-iOS.a in Frameworks */,
198 | 96DBF37F1B3AF25A003E0D46 /* Prototope.framework in Frameworks */,
199 | 96DBF3831B3AF25A003E0D46 /* PrototopeJSBridge.framework in Frameworks */,
200 | );
201 | runOnlyForDeploymentPostprocessing = 0;
202 | };
203 | /* End PBXFrameworksBuildPhase section */
204 |
205 | /* Begin PBXGroup section */
206 | 962558ED1B39AF1A005E4360 = {
207 | isa = PBXGroup;
208 | children = (
209 | 962558F81B39AF1A005E4360 /* Early Math Prototype Player */,
210 | 962558F71B39AF1A005E4360 /* Products */,
211 | );
212 | sourceTree = "";
213 | };
214 | 962558F71B39AF1A005E4360 /* Products */ = {
215 | isa = PBXGroup;
216 | children = (
217 | 962558F61B39AF1A005E4360 /* Early Math.app */,
218 | );
219 | name = Products;
220 | sourceTree = "";
221 | };
222 | 962558F81B39AF1A005E4360 /* Early Math Prototype Player */ = {
223 | isa = PBXGroup;
224 | children = (
225 | 9625591F1B39AF96005E4360 /* Model */,
226 | 962558FB1B39AF1A005E4360 /* AppDelegate.swift */,
227 | 9625591B1B39AF72005E4360 /* PrototypeListCollectionViewController.swift */,
228 | EB3CBCF51B3B2ADE0038AE64 /* ReadmeViewController.swift */,
229 | 9625591D1B39AF80005E4360 /* PlayerViewController.swift */,
230 | EB9531391B49D8CD00E4E5C8 /* Instructions UI */,
231 | EB9530F21B498A4D00E4E5C8 /* LaunchScreen.storyboard */,
232 | 962559021B39AF1A005E4360 /* Images.xcassets */,
233 | 962558F91B39AF1A005E4360 /* Supporting Files */,
234 | );
235 | path = "Early Math Prototype Player";
236 | sourceTree = "";
237 | };
238 | 962558F91B39AF1A005E4360 /* Supporting Files */ = {
239 | isa = PBXGroup;
240 | children = (
241 | EB7841D31B3BB13D008E5160 /* Early Math Prototype Player-Bridging-Header.h */,
242 | EB9530341B4707D900E4E5C8 /* Third Party */,
243 | 96DBF35D1B3AF243003E0D46 /* Prototope.xcodeproj */,
244 | 962559221B39AFB9005E4360 /* Early-Math-Prototypes */,
245 | 962558FA1B39AF1A005E4360 /* Info.plist */,
246 | 96DBF38F1B3AFE68003E0D46 /* protoscope-bundle.js */,
247 | );
248 | name = "Supporting Files";
249 | sourceTree = "";
250 | };
251 | 9625591F1B39AF96005E4360 /* Model */ = {
252 | isa = PBXGroup;
253 | children = (
254 | 962559201B39AFA6005E4360 /* PrototypeProvider.swift */,
255 | );
256 | name = Model;
257 | sourceTree = "";
258 | };
259 | 96DBF35E1B3AF243003E0D46 /* Products */ = {
260 | isa = PBXGroup;
261 | children = (
262 | 96DBF36E1B3AF243003E0D46 /* Prototope.framework */,
263 | 96DBF3701B3AF243003E0D46 /* PrototopeTestApp.app */,
264 | 96DBF3721B3AF243003E0D46 /* PrototopeTests.xctest */,
265 | 96DBF3741B3AF243003E0D46 /* PrototopeJSBridge.framework */,
266 | 96DBF3761B3AF243003E0D46 /* PrototopeJSBridgeTests.xctest */,
267 | 96DBF3781B3AF243003E0D46 /* Protocaster.app */,
268 | 96DBF37A1B3AF243003E0D46 /* ProtocasterTests.xctest */,
269 | 96DBF37C1B3AF243003E0D46 /* Protoscope.app */,
270 | 96DBF37E1B3AF243003E0D46 /* ProtoscopeTests.xctest */,
271 | EBAAD2B31D19C36300BB2C0A /* PrototopeOSX.framework */,
272 | EBAAD2B51D19C36300BB2C0A /* PrototopeOSXTests.xctest */,
273 | );
274 | name = Products;
275 | sourceTree = "";
276 | };
277 | EB7841BD1B3BB114008E5160 /* Products */ = {
278 | isa = PBXGroup;
279 | children = (
280 | EB7841C41B3BB114008E5160 /* libMMMarkdown-Mac.a */,
281 | EB7841C61B3BB114008E5160 /* libMMMarkdown-iOS.a */,
282 | EB7841C81B3BB114008E5160 /* MMMarkdownTests.xctest */,
283 | EB7841CA1B3BB114008E5160 /* mmmarkdown */,
284 | );
285 | name = Products;
286 | sourceTree = "";
287 | };
288 | EB9530341B4707D900E4E5C8 /* Third Party */ = {
289 | isa = PBXGroup;
290 | children = (
291 | EB9530461B47080C00E4E5C8 /* FLAnimatedImageView */,
292 | EB7841BC1B3BB114008E5160 /* MMMarkdown.xcodeproj */,
293 | );
294 | name = "Third Party";
295 | sourceTree = "";
296 | };
297 | EB9530461B47080C00E4E5C8 /* FLAnimatedImageView */ = {
298 | isa = PBXGroup;
299 | children = (
300 | EB9530401B47080800E4E5C8 /* FLAnimatedImage.h */,
301 | EB9530411B47080800E4E5C8 /* FLAnimatedImage.m */,
302 | EB9530421B47080800E4E5C8 /* FLAnimatedImageView.h */,
303 | EB9530431B47080800E4E5C8 /* FLAnimatedImageView.m */,
304 | );
305 | name = FLAnimatedImageView;
306 | sourceTree = "";
307 | };
308 | EB9531391B49D8CD00E4E5C8 /* Instructions UI */ = {
309 | isa = PBXGroup;
310 | children = (
311 | EB95313A1B49D8DB00E4E5C8 /* InstructionsViewController.swift */,
312 | EB9531371B49D8C300E4E5C8 /* Instructions.xib */,
313 | EB95312A1B49D88700E4E5C8 /* finger_demo.m4v */,
314 | );
315 | name = "Instructions UI";
316 | sourceTree = "";
317 | };
318 | /* End PBXGroup section */
319 |
320 | /* Begin PBXNativeTarget section */
321 | 962558F51B39AF1A005E4360 /* Early Math Prototype Player */ = {
322 | isa = PBXNativeTarget;
323 | buildConfigurationList = 962559151B39AF1A005E4360 /* Build configuration list for PBXNativeTarget "Early Math Prototype Player" */;
324 | buildPhases = (
325 | 962558F21B39AF1A005E4360 /* Sources */,
326 | 962558F31B39AF1A005E4360 /* Frameworks */,
327 | 962558F41B39AF1A005E4360 /* Resources */,
328 | 96DBF3871B3AF25A003E0D46 /* Embed Frameworks */,
329 | );
330 | buildRules = (
331 | );
332 | dependencies = (
333 | 96DBF3821B3AF25A003E0D46 /* PBXTargetDependency */,
334 | 96DBF3861B3AF25A003E0D46 /* PBXTargetDependency */,
335 | );
336 | name = "Early Math Prototype Player";
337 | productName = "Early Math Prototype Player";
338 | productReference = 962558F61B39AF1A005E4360 /* Early Math.app */;
339 | productType = "com.apple.product-type.application";
340 | };
341 | /* End PBXNativeTarget section */
342 |
343 | /* Begin PBXProject section */
344 | 962558EE1B39AF1A005E4360 /* Project object */ = {
345 | isa = PBXProject;
346 | attributes = {
347 | LastSwiftMigration = 0730;
348 | LastSwiftUpdateCheck = 0700;
349 | LastUpgradeCheck = 0630;
350 | ORGANIZATIONNAME = "Khan Academy";
351 | TargetAttributes = {
352 | 962558F51B39AF1A005E4360 = {
353 | CreatedOnToolsVersion = 6.3.1;
354 | };
355 | };
356 | };
357 | buildConfigurationList = 962558F11B39AF1A005E4360 /* Build configuration list for PBXProject "Early Math Prototype Player" */;
358 | compatibilityVersion = "Xcode 3.2";
359 | developmentRegion = English;
360 | hasScannedForEncodings = 0;
361 | knownRegions = (
362 | en,
363 | Base,
364 | );
365 | mainGroup = 962558ED1B39AF1A005E4360;
366 | productRefGroup = 962558F71B39AF1A005E4360 /* Products */;
367 | projectDirPath = "";
368 | projectReferences = (
369 | {
370 | ProductGroup = EB7841BD1B3BB114008E5160 /* Products */;
371 | ProjectRef = EB7841BC1B3BB114008E5160 /* MMMarkdown.xcodeproj */;
372 | },
373 | {
374 | ProductGroup = 96DBF35E1B3AF243003E0D46 /* Products */;
375 | ProjectRef = 96DBF35D1B3AF243003E0D46 /* Prototope.xcodeproj */;
376 | },
377 | );
378 | projectRoot = "";
379 | targets = (
380 | 962558F51B39AF1A005E4360 /* Early Math Prototype Player */,
381 | );
382 | };
383 | /* End PBXProject section */
384 |
385 | /* Begin PBXReferenceProxy section */
386 | 96DBF36E1B3AF243003E0D46 /* Prototope.framework */ = {
387 | isa = PBXReferenceProxy;
388 | fileType = wrapper.framework;
389 | path = Prototope.framework;
390 | remoteRef = 96DBF36D1B3AF243003E0D46 /* PBXContainerItemProxy */;
391 | sourceTree = BUILT_PRODUCTS_DIR;
392 | };
393 | 96DBF3701B3AF243003E0D46 /* PrototopeTestApp.app */ = {
394 | isa = PBXReferenceProxy;
395 | fileType = wrapper.application;
396 | path = PrototopeTestApp.app;
397 | remoteRef = 96DBF36F1B3AF243003E0D46 /* PBXContainerItemProxy */;
398 | sourceTree = BUILT_PRODUCTS_DIR;
399 | };
400 | 96DBF3721B3AF243003E0D46 /* PrototopeTests.xctest */ = {
401 | isa = PBXReferenceProxy;
402 | fileType = wrapper.cfbundle;
403 | path = PrototopeTests.xctest;
404 | remoteRef = 96DBF3711B3AF243003E0D46 /* PBXContainerItemProxy */;
405 | sourceTree = BUILT_PRODUCTS_DIR;
406 | };
407 | 96DBF3741B3AF243003E0D46 /* PrototopeJSBridge.framework */ = {
408 | isa = PBXReferenceProxy;
409 | fileType = wrapper.framework;
410 | path = PrototopeJSBridge.framework;
411 | remoteRef = 96DBF3731B3AF243003E0D46 /* PBXContainerItemProxy */;
412 | sourceTree = BUILT_PRODUCTS_DIR;
413 | };
414 | 96DBF3761B3AF243003E0D46 /* PrototopeJSBridgeTests.xctest */ = {
415 | isa = PBXReferenceProxy;
416 | fileType = wrapper.cfbundle;
417 | path = PrototopeJSBridgeTests.xctest;
418 | remoteRef = 96DBF3751B3AF243003E0D46 /* PBXContainerItemProxy */;
419 | sourceTree = BUILT_PRODUCTS_DIR;
420 | };
421 | 96DBF3781B3AF243003E0D46 /* Protocaster.app */ = {
422 | isa = PBXReferenceProxy;
423 | fileType = wrapper.application;
424 | path = Protocaster.app;
425 | remoteRef = 96DBF3771B3AF243003E0D46 /* PBXContainerItemProxy */;
426 | sourceTree = BUILT_PRODUCTS_DIR;
427 | };
428 | 96DBF37A1B3AF243003E0D46 /* ProtocasterTests.xctest */ = {
429 | isa = PBXReferenceProxy;
430 | fileType = wrapper.cfbundle;
431 | path = ProtocasterTests.xctest;
432 | remoteRef = 96DBF3791B3AF243003E0D46 /* PBXContainerItemProxy */;
433 | sourceTree = BUILT_PRODUCTS_DIR;
434 | };
435 | 96DBF37C1B3AF243003E0D46 /* Protoscope.app */ = {
436 | isa = PBXReferenceProxy;
437 | fileType = wrapper.application;
438 | path = Protoscope.app;
439 | remoteRef = 96DBF37B1B3AF243003E0D46 /* PBXContainerItemProxy */;
440 | sourceTree = BUILT_PRODUCTS_DIR;
441 | };
442 | 96DBF37E1B3AF243003E0D46 /* ProtoscopeTests.xctest */ = {
443 | isa = PBXReferenceProxy;
444 | fileType = wrapper.cfbundle;
445 | path = ProtoscopeTests.xctest;
446 | remoteRef = 96DBF37D1B3AF243003E0D46 /* PBXContainerItemProxy */;
447 | sourceTree = BUILT_PRODUCTS_DIR;
448 | };
449 | EB7841C41B3BB114008E5160 /* libMMMarkdown-Mac.a */ = {
450 | isa = PBXReferenceProxy;
451 | fileType = archive.ar;
452 | path = "libMMMarkdown-Mac.a";
453 | remoteRef = EB7841C31B3BB114008E5160 /* PBXContainerItemProxy */;
454 | sourceTree = BUILT_PRODUCTS_DIR;
455 | };
456 | EB7841C61B3BB114008E5160 /* libMMMarkdown-iOS.a */ = {
457 | isa = PBXReferenceProxy;
458 | fileType = archive.ar;
459 | path = "libMMMarkdown-iOS.a";
460 | remoteRef = EB7841C51B3BB114008E5160 /* PBXContainerItemProxy */;
461 | sourceTree = BUILT_PRODUCTS_DIR;
462 | };
463 | EB7841C81B3BB114008E5160 /* MMMarkdownTests.xctest */ = {
464 | isa = PBXReferenceProxy;
465 | fileType = wrapper.cfbundle;
466 | path = MMMarkdownTests.xctest;
467 | remoteRef = EB7841C71B3BB114008E5160 /* PBXContainerItemProxy */;
468 | sourceTree = BUILT_PRODUCTS_DIR;
469 | };
470 | EB7841CA1B3BB114008E5160 /* mmmarkdown */ = {
471 | isa = PBXReferenceProxy;
472 | fileType = "compiled.mach-o.executable";
473 | path = mmmarkdown;
474 | remoteRef = EB7841C91B3BB114008E5160 /* PBXContainerItemProxy */;
475 | sourceTree = BUILT_PRODUCTS_DIR;
476 | };
477 | EBAAD2B31D19C36300BB2C0A /* PrototopeOSX.framework */ = {
478 | isa = PBXReferenceProxy;
479 | fileType = wrapper.framework;
480 | path = PrototopeOSX.framework;
481 | remoteRef = EBAAD2B21D19C36300BB2C0A /* PBXContainerItemProxy */;
482 | sourceTree = BUILT_PRODUCTS_DIR;
483 | };
484 | EBAAD2B51D19C36300BB2C0A /* PrototopeOSXTests.xctest */ = {
485 | isa = PBXReferenceProxy;
486 | fileType = wrapper.cfbundle;
487 | path = PrototopeOSXTests.xctest;
488 | remoteRef = EBAAD2B41D19C36300BB2C0A /* PBXContainerItemProxy */;
489 | sourceTree = BUILT_PRODUCTS_DIR;
490 | };
491 | /* End PBXReferenceProxy section */
492 |
493 | /* Begin PBXResourcesBuildPhase section */
494 | 962558F41B39AF1A005E4360 /* Resources */ = {
495 | isa = PBXResourcesBuildPhase;
496 | buildActionMask = 2147483647;
497 | files = (
498 | 96DBF3901B3AFE68003E0D46 /* protoscope-bundle.js in Resources */,
499 | EB95312B1B49D88700E4E5C8 /* finger_demo.m4v in Resources */,
500 | EB9530F31B498A4D00E4E5C8 /* LaunchScreen.storyboard in Resources */,
501 | 962559231B39AFB9005E4360 /* Early-Math-Prototypes in Resources */,
502 | EBB48F5D1B4AFDB500850DA5 /* Instructions.xib in Resources */,
503 | 962559031B39AF1A005E4360 /* Images.xcassets in Resources */,
504 | );
505 | runOnlyForDeploymentPostprocessing = 0;
506 | };
507 | /* End PBXResourcesBuildPhase section */
508 |
509 | /* Begin PBXSourcesBuildPhase section */
510 | 962558F21B39AF1A005E4360 /* Sources */ = {
511 | isa = PBXSourcesBuildPhase;
512 | buildActionMask = 2147483647;
513 | files = (
514 | EB9530451B47080800E4E5C8 /* FLAnimatedImageView.m in Sources */,
515 | 9625591C1B39AF72005E4360 /* PrototypeListCollectionViewController.swift in Sources */,
516 | 962558FC1B39AF1A005E4360 /* AppDelegate.swift in Sources */,
517 | EB9530441B47080800E4E5C8 /* FLAnimatedImage.m in Sources */,
518 | 9625591E1B39AF80005E4360 /* PlayerViewController.swift in Sources */,
519 | 962559211B39AFA6005E4360 /* PrototypeProvider.swift in Sources */,
520 | EB95313B1B49D8DB00E4E5C8 /* InstructionsViewController.swift in Sources */,
521 | EB3CBCF61B3B2ADE0038AE64 /* ReadmeViewController.swift in Sources */,
522 | );
523 | runOnlyForDeploymentPostprocessing = 0;
524 | };
525 | /* End PBXSourcesBuildPhase section */
526 |
527 | /* Begin PBXTargetDependency section */
528 | 96DBF3821B3AF25A003E0D46 /* PBXTargetDependency */ = {
529 | isa = PBXTargetDependency;
530 | name = Prototope;
531 | targetProxy = 96DBF3811B3AF25A003E0D46 /* PBXContainerItemProxy */;
532 | };
533 | 96DBF3861B3AF25A003E0D46 /* PBXTargetDependency */ = {
534 | isa = PBXTargetDependency;
535 | name = PrototopeJSBridge;
536 | targetProxy = 96DBF3851B3AF25A003E0D46 /* PBXContainerItemProxy */;
537 | };
538 | /* End PBXTargetDependency section */
539 |
540 | /* Begin XCBuildConfiguration section */
541 | 962559131B39AF1A005E4360 /* Debug */ = {
542 | isa = XCBuildConfiguration;
543 | buildSettings = {
544 | ALWAYS_SEARCH_USER_PATHS = NO;
545 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
546 | CLANG_CXX_LIBRARY = "libc++";
547 | CLANG_ENABLE_MODULES = YES;
548 | CLANG_ENABLE_OBJC_ARC = YES;
549 | CLANG_WARN_BOOL_CONVERSION = YES;
550 | CLANG_WARN_CONSTANT_CONVERSION = YES;
551 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
552 | CLANG_WARN_EMPTY_BODY = YES;
553 | CLANG_WARN_ENUM_CONVERSION = YES;
554 | CLANG_WARN_INT_CONVERSION = YES;
555 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
556 | CLANG_WARN_UNREACHABLE_CODE = YES;
557 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
558 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
559 | COPY_PHASE_STRIP = NO;
560 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
561 | ENABLE_STRICT_OBJC_MSGSEND = YES;
562 | GCC_C_LANGUAGE_STANDARD = gnu99;
563 | GCC_DYNAMIC_NO_PIC = NO;
564 | GCC_NO_COMMON_BLOCKS = YES;
565 | GCC_OPTIMIZATION_LEVEL = 0;
566 | GCC_PREPROCESSOR_DEFINITIONS = (
567 | "DEBUG=1",
568 | "$(inherited)",
569 | );
570 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
571 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
572 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
573 | GCC_WARN_UNDECLARED_SELECTOR = YES;
574 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
575 | GCC_WARN_UNUSED_FUNCTION = YES;
576 | GCC_WARN_UNUSED_VARIABLE = YES;
577 | IPHONEOS_DEPLOYMENT_TARGET = 8.3;
578 | MTL_ENABLE_DEBUG_INFO = YES;
579 | ONLY_ACTIVE_ARCH = YES;
580 | SDKROOT = iphoneos;
581 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
582 | TARGETED_DEVICE_FAMILY = 2;
583 | };
584 | name = Debug;
585 | };
586 | 962559141B39AF1A005E4360 /* Release */ = {
587 | isa = XCBuildConfiguration;
588 | buildSettings = {
589 | ALWAYS_SEARCH_USER_PATHS = NO;
590 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
591 | CLANG_CXX_LIBRARY = "libc++";
592 | CLANG_ENABLE_MODULES = YES;
593 | CLANG_ENABLE_OBJC_ARC = YES;
594 | CLANG_WARN_BOOL_CONVERSION = YES;
595 | CLANG_WARN_CONSTANT_CONVERSION = YES;
596 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
597 | CLANG_WARN_EMPTY_BODY = YES;
598 | CLANG_WARN_ENUM_CONVERSION = YES;
599 | CLANG_WARN_INT_CONVERSION = YES;
600 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
601 | CLANG_WARN_UNREACHABLE_CODE = YES;
602 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
603 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
604 | COPY_PHASE_STRIP = NO;
605 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
606 | ENABLE_NS_ASSERTIONS = NO;
607 | ENABLE_STRICT_OBJC_MSGSEND = YES;
608 | GCC_C_LANGUAGE_STANDARD = gnu99;
609 | GCC_NO_COMMON_BLOCKS = YES;
610 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
611 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
612 | GCC_WARN_UNDECLARED_SELECTOR = YES;
613 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
614 | GCC_WARN_UNUSED_FUNCTION = YES;
615 | GCC_WARN_UNUSED_VARIABLE = YES;
616 | IPHONEOS_DEPLOYMENT_TARGET = 8.3;
617 | MTL_ENABLE_DEBUG_INFO = NO;
618 | SDKROOT = iphoneos;
619 | TARGETED_DEVICE_FAMILY = 2;
620 | VALIDATE_PRODUCT = YES;
621 | };
622 | name = Release;
623 | };
624 | 962559161B39AF1A005E4360 /* Debug */ = {
625 | isa = XCBuildConfiguration;
626 | buildSettings = {
627 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
628 | CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO;
629 | CLANG_ENABLE_MODULES = YES;
630 | FRAMEWORK_SEARCH_PATHS = (
631 | "$(inherited)",
632 | "$(PROJECT_DIR)/Prototope/ThirdParty/pop/build/Debug-iphoneos",
633 | );
634 | HEADER_SEARCH_PATHS = (
635 | "$(inherited)",
636 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
637 | "$(SRCROOT)/prototope/Prototope",
638 | "$(SRCROOT)/prototope/ThirdParty/**",
639 | "$(CONFIGURATION_BUILD_DIR)/MMMarkdown-iOS/public/",
640 | );
641 | INFOPLIST_FILE = "Early Math Prototype Player/Info.plist";
642 | IPHONEOS_DEPLOYMENT_TARGET = 9.1;
643 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
644 | LIBRARY_SEARCH_PATHS = "$(SRCROOT)/prototope/ThirdParty/**";
645 | PRODUCT_NAME = "Early Math";
646 | SWIFT_OBJC_BRIDGING_HEADER = "Early Math Prototype Player/Early Math Prototype Player-Bridging-Header.h";
647 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
648 | TARGETED_DEVICE_FAMILY = 2;
649 | USER_HEADER_SEARCH_PATHS = "";
650 | };
651 | name = Debug;
652 | };
653 | 962559171B39AF1A005E4360 /* Release */ = {
654 | isa = XCBuildConfiguration;
655 | buildSettings = {
656 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
657 | CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO;
658 | CLANG_ENABLE_MODULES = YES;
659 | FRAMEWORK_SEARCH_PATHS = (
660 | "$(inherited)",
661 | "$(PROJECT_DIR)/Prototope/ThirdParty/pop/build/Debug-iphoneos",
662 | );
663 | HEADER_SEARCH_PATHS = (
664 | "$(inherited)",
665 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
666 | "$(SRCROOT)/prototope/Prototope",
667 | "$(SRCROOT)/prototope/ThirdParty/**",
668 | "$(CONFIGURATION_BUILD_DIR)/MMMarkdown-iOS/public/",
669 | );
670 | INFOPLIST_FILE = "Early Math Prototype Player/Info.plist";
671 | IPHONEOS_DEPLOYMENT_TARGET = 9.1;
672 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
673 | LIBRARY_SEARCH_PATHS = "$(SRCROOT)/prototope/ThirdParty/**";
674 | PRODUCT_NAME = "Early Math";
675 | SWIFT_OBJC_BRIDGING_HEADER = "Early Math Prototype Player/Early Math Prototype Player-Bridging-Header.h";
676 | TARGETED_DEVICE_FAMILY = 2;
677 | USER_HEADER_SEARCH_PATHS = "";
678 | };
679 | name = Release;
680 | };
681 | /* End XCBuildConfiguration section */
682 |
683 | /* Begin XCConfigurationList section */
684 | 962558F11B39AF1A005E4360 /* Build configuration list for PBXProject "Early Math Prototype Player" */ = {
685 | isa = XCConfigurationList;
686 | buildConfigurations = (
687 | 962559131B39AF1A005E4360 /* Debug */,
688 | 962559141B39AF1A005E4360 /* Release */,
689 | );
690 | defaultConfigurationIsVisible = 0;
691 | defaultConfigurationName = Release;
692 | };
693 | 962559151B39AF1A005E4360 /* Build configuration list for PBXNativeTarget "Early Math Prototype Player" */ = {
694 | isa = XCConfigurationList;
695 | buildConfigurations = (
696 | 962559161B39AF1A005E4360 /* Debug */,
697 | 962559171B39AF1A005E4360 /* Release */,
698 | );
699 | defaultConfigurationIsVisible = 0;
700 | defaultConfigurationName = Release;
701 | };
702 | /* End XCConfigurationList section */
703 | };
704 | rootObject = 962558EE1B39AF1A005E4360 /* Project object */;
705 | }
706 |
--------------------------------------------------------------------------------