Esse commit está contido em:
Charlie Hewitt
2017-12-10 16:34:39 +00:00
commit 25e2163a15
32 arquivos alterados com 1445 adições e 253 exclusões
+52 -30
Ver Arquivo
@@ -7,14 +7,22 @@
objects = {
/* Begin PBXBuildFile section */
CB0DAF1C1FDD348C004668A1 /* AffUIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0DAF1B1FDD348C004668A1 /* AffUIViewController.swift */; };
CB0DAF1E1FDD354D004668A1 /* RoundedUIButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0DAF1D1FDD354D004668A1 /* RoundedUIButton.swift */; };
CB0DAF201FDD554C004668A1 /* USResultsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0DAF1F1FDD554C004668A1 /* USResultsViewController.swift */; };
CB0DAF221FDD5C63004668A1 /* USEmojiViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0DAF211FDD5C63004668A1 /* USEmojiViewController.swift */; };
CB0DAF241FDD6352004668A1 /* USAnnotateViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0DAF231FDD6352004668A1 /* USAnnotateViewController.swift */; };
CB0DAF281FDD6646004668A1 /* SlideHorSegue.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0DAF271FDD6646004668A1 /* SlideHorSegue.swift */; };
CB0DAF2C1FDD685E004668A1 /* USStartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0DAF2B1FDD685E004668A1 /* USStartViewController.swift */; };
CB0DAF2E1FDD7497004668A1 /* USFinishViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0DAF2D1FDD7497004668A1 /* USFinishViewController.swift */; };
CB0DAF301FDD9597004668A1 /* BorderedImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0DAF2F1FDD9597004668A1 /* BorderedImageView.swift */; };
CB418F5B1FDC563800E48EF3 /* HCSStarRatingView.m in Sources */ = {isa = PBXBuildFile; fileRef = CB418F591FDC563700E48EF3 /* HCSStarRatingView.m */; };
CB6ADA771FDB0E3900D36D22 /* ResultsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB6ADA761FDB0E3900D36D22 /* ResultsViewController.swift */; };
CBB8703C1FDAA373004557D9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBB8703B1FDAA373004557D9 /* AppDelegate.swift */; };
CBB8703E1FDAA373004557D9 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBB8703D1FDAA373004557D9 /* ViewController.swift */; };
CBB870411FDAA373004557D9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CBB8703F1FDAA373004557D9 /* Main.storyboard */; };
CBB870431FDAA373004557D9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CBB870421FDAA373004557D9 /* Assets.xcassets */; };
CBB870461FDAA373004557D9 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CBB870441FDAA373004557D9 /* LaunchScreen.storyboard */; };
CBB870511FDAA373004557D9 /* aff_songTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBB870501FDAA373004557D9 /* aff_songTests.swift */; };
CBB8705C1FDAA373004557D9 /* aff_songUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBB8705B1FDAA373004557D9 /* aff_songUITests.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -35,6 +43,18 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
CB0DAF1B1FDD348C004668A1 /* AffUIViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AffUIViewController.swift; sourceTree = "<group>"; };
CB0DAF1D1FDD354D004668A1 /* RoundedUIButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedUIButton.swift; sourceTree = "<group>"; };
CB0DAF1F1FDD554C004668A1 /* USResultsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = USResultsViewController.swift; sourceTree = "<group>"; };
CB0DAF211FDD5C63004668A1 /* USEmojiViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = USEmojiViewController.swift; sourceTree = "<group>"; };
CB0DAF231FDD6352004668A1 /* USAnnotateViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = USAnnotateViewController.swift; sourceTree = "<group>"; };
CB0DAF271FDD6646004668A1 /* SlideHorSegue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SlideHorSegue.swift; sourceTree = "<group>"; };
CB0DAF2B1FDD685E004668A1 /* USStartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = USStartViewController.swift; sourceTree = "<group>"; };
CB0DAF2D1FDD7497004668A1 /* USFinishViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = USFinishViewController.swift; sourceTree = "<group>"; };
CB0DAF2F1FDD9597004668A1 /* BorderedImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BorderedImageView.swift; sourceTree = "<group>"; };
CB418F581FDC563500E48EF3 /* aff-song-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "aff-song-Bridging-Header.h"; sourceTree = "<group>"; };
CB418F591FDC563700E48EF3 /* HCSStarRatingView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HCSStarRatingView.m; sourceTree = "<group>"; };
CB418F5A1FDC563800E48EF3 /* HCSStarRatingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HCSStarRatingView.h; sourceTree = "<group>"; };
CB6ADA761FDB0E3900D36D22 /* ResultsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultsViewController.swift; sourceTree = "<group>"; };
CBB870381FDAA373004557D9 /* aff-song.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "aff-song.app"; sourceTree = BUILT_PRODUCTS_DIR; };
CBB8703B1FDAA373004557D9 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
@@ -44,11 +64,7 @@
CBB870451FDAA373004557D9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
CBB870471FDAA373004557D9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
CBB8704C1FDAA373004557D9 /* aff-songTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "aff-songTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
CBB870501FDAA373004557D9 /* aff_songTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = aff_songTests.swift; sourceTree = "<group>"; };
CBB870521FDAA373004557D9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
CBB870571FDAA373004557D9 /* aff-songUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "aff-songUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
CBB8705B1FDAA373004557D9 /* aff_songUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = aff_songUITests.swift; sourceTree = "<group>"; };
CBB8705D1FDAA373004557D9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -80,8 +96,6 @@
isa = PBXGroup;
children = (
CBB8703A1FDAA373004557D9 /* aff-song */,
CBB8704F1FDAA373004557D9 /* aff-songTests */,
CBB8705A1FDAA373004557D9 /* aff-songUITests */,
CBB870391FDAA373004557D9 /* Products */,
);
sourceTree = "<group>";
@@ -99,6 +113,8 @@
CBB8703A1FDAA373004557D9 /* aff-song */ = {
isa = PBXGroup;
children = (
CB418F5A1FDC563800E48EF3 /* HCSStarRatingView.h */,
CB418F591FDC563700E48EF3 /* HCSStarRatingView.m */,
CB6ADA761FDB0E3900D36D22 /* ResultsViewController.swift */,
CBB8703B1FDAA373004557D9 /* AppDelegate.swift */,
CBB8703D1FDAA373004557D9 /* ViewController.swift */,
@@ -106,28 +122,20 @@
CBB870421FDAA373004557D9 /* Assets.xcassets */,
CBB870441FDAA373004557D9 /* LaunchScreen.storyboard */,
CBB870471FDAA373004557D9 /* Info.plist */,
CB418F581FDC563500E48EF3 /* aff-song-Bridging-Header.h */,
CB0DAF1B1FDD348C004668A1 /* AffUIViewController.swift */,
CB0DAF1D1FDD354D004668A1 /* RoundedUIButton.swift */,
CB0DAF1F1FDD554C004668A1 /* USResultsViewController.swift */,
CB0DAF211FDD5C63004668A1 /* USEmojiViewController.swift */,
CB0DAF231FDD6352004668A1 /* USAnnotateViewController.swift */,
CB0DAF271FDD6646004668A1 /* SlideHorSegue.swift */,
CB0DAF2B1FDD685E004668A1 /* USStartViewController.swift */,
CB0DAF2D1FDD7497004668A1 /* USFinishViewController.swift */,
CB0DAF2F1FDD9597004668A1 /* BorderedImageView.swift */,
);
path = "aff-song";
sourceTree = "<group>";
};
CBB8704F1FDAA373004557D9 /* aff-songTests */ = {
isa = PBXGroup;
children = (
CBB870501FDAA373004557D9 /* aff_songTests.swift */,
CBB870521FDAA373004557D9 /* Info.plist */,
);
path = "aff-songTests";
sourceTree = "<group>";
};
CBB8705A1FDAA373004557D9 /* aff-songUITests */ = {
isa = PBXGroup;
children = (
CBB8705B1FDAA373004557D9 /* aff_songUITests.swift */,
CBB8705D1FDAA373004557D9 /* Info.plist */,
);
path = "aff-songUITests";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -196,6 +204,7 @@
TargetAttributes = {
CBB870371FDAA373004557D9 = {
CreatedOnToolsVersion = 9.2;
LastSwiftMigration = 0920;
ProvisioningStyle = Automatic;
};
CBB8704B1FDAA373004557D9 = {
@@ -262,9 +271,19 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
CB0DAF301FDD9597004668A1 /* BorderedImageView.swift in Sources */,
CBB8703E1FDAA373004557D9 /* ViewController.swift in Sources */,
CB0DAF221FDD5C63004668A1 /* USEmojiViewController.swift in Sources */,
CBB8703C1FDAA373004557D9 /* AppDelegate.swift in Sources */,
CB0DAF281FDD6646004668A1 /* SlideHorSegue.swift in Sources */,
CB0DAF241FDD6352004668A1 /* USAnnotateViewController.swift in Sources */,
CB0DAF1C1FDD348C004668A1 /* AffUIViewController.swift in Sources */,
CB418F5B1FDC563800E48EF3 /* HCSStarRatingView.m in Sources */,
CB6ADA771FDB0E3900D36D22 /* ResultsViewController.swift in Sources */,
CB0DAF201FDD554C004668A1 /* USResultsViewController.swift in Sources */,
CB0DAF1E1FDD354D004668A1 /* RoundedUIButton.swift in Sources */,
CB0DAF2C1FDD685E004668A1 /* USStartViewController.swift in Sources */,
CB0DAF2E1FDD7497004668A1 /* USFinishViewController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -272,7 +291,6 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
CBB870511FDAA373004557D9 /* aff_songTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -280,7 +298,6 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
CBB8705C1FDAA373004557D9 /* aff_songUITests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -430,13 +447,16 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = T386P97R96;
INFOPLIST_FILE = "aff-song/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 11.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "me.chewitt.aff-song";
PRODUCT_BUNDLE_IDENTIFIER = me.chewitt.affectone;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "aff-song/aff-song-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
@@ -446,13 +466,15 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = T386P97R96;
INFOPLIST_FILE = "aff-song/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 11.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "me.chewitt.aff-song";
PRODUCT_BUNDLE_IDENTIFIER = me.chewitt.affectone;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "aff-song/aff-song-Bridging-Header.h";
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
@@ -2,4 +2,22 @@
<Bucket
type = "1"
version = "2.0">
<Breakpoints>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "aff-song/ResultsViewController.swift"
timestampString = "534616136.336604"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "6"
endingLineNumber = "6"
landmarkName = "unknown"
landmarkType = "0">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>
@@ -0,0 +1,22 @@
//
// AffUIViewController.swift
// aff-song
//
// Created by Charlie Hewitt on 10/12/2017.
// Copyright © 2017 Charlie Hewitt. All rights reserved.
//
import Foundation
class AffUIViewController: UIViewController {
override func viewDidLoad() {
let gradient = CAGradientLayer()
gradient.frame = view.bounds
let c1 = UIColor(red: 252.0/255.0, green: 49.0/255.0, blue: 89.0/255.0, alpha: 1.0)
let c2 = UIColor(red: 252.0/255.0, green: 45.0/255.0, blue: 119.0/255.0, alpha: 1.0)
gradient.colors = [c1.cgColor, c2.cgColor]
view.layer.insertSublayer(gradient, at: 0)
}
}
+22 -4
Ver Arquivo
@@ -13,10 +13,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
application.statusBarStyle = .lightContent
refreshAuth()
return true
}
@@ -41,7 +40,26 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
func refreshAuth() {
// get a new auth key from spotify
let url: String = "https://accounts.spotify.com/api/token"
var request: URLRequest = URLRequest(url: URL(string: url)!)
let bodyData = "grant_type=refresh_token&client_id=75f91608ce154091a1f419be415cbdda&client_secret=a6609b179eb140b086c2f6cc2c35adf4&refresh_token=AQBeDOqXW6kerokqh6WbEexkOQH5FtWGfDvw2DLePMofXTAVOUGsygF5iWYx0jtCjBUFO31qslCGNcRNh6vXGv9wxxbEuyNyWFy-t1YuYON2UD_ySlzSCcjAWsI2YiKzFAc"
request.httpBody = bodyData.data(using: String.Encoding.utf8);
request.httpMethod = "POST"
let session = URLSession.shared
session.dataTask(with: request) {data, response, err in
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String:Any]
if let authKey = json["access_token"] {
UserDefaults.standard.set(authKey, forKey: "SpotifyAuthToken")
}
} catch let error {
print(error.localizedDescription)
}
}.resume()
}
}
@@ -31,13 +31,15 @@
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"idiom" : "iphone",
"filename" : "icon.png",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"idiom" : "iphone",
"filename" : "icon-1.png",
"scale" : "3x"
},
{
Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 19 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 18 KiB

@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -1,7 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" systemVersion="17A277" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@@ -13,7 +17,7 @@
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="backgroundColor" red="0.98823529409999999" green="0.19215686269999999" blue="0.34901960780000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
+385 -38
Ver Arquivo
@@ -6,6 +6,7 @@
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@@ -18,8 +19,8 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Rqa-uL-a2b">
<rect key="frame" x="125" y="382" width="125" height="50"/>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Rqa-uL-a2b" customClass="RoundedUIButton" customModule="aff_song" customModuleProvider="target">
<rect key="frame" x="125" y="384" width="125" height="50"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="Rtf-0g-F98"/>
@@ -28,39 +29,50 @@
<state key="normal" title="Take Photo"/>
<connections>
<action selector="openCameraButtonWithSender:" destination="BYZ-38-t0r" eventType="touchUpInside" id="T1H-36-OXR"/>
<segue destination="7dN-K8-kAy" kind="presentation" identifier="resultsViewSegue" id="5tz-9X-0c7"/>
</connections>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="Affectone" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="NLu-8o-db9">
<rect key="frame" x="74" y="209" width="227" height="55"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Affectone" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="NLu-8o-db9">
<rect key="frame" x="74" y="215" width="227" height="48"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<fontDescription key="fontDescription" type="system" pointSize="40"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="highlightedColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="Song recommendations for your current mood" textAlignment="center" lineBreakMode="wordWrap" numberOfLines="5" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="6fX-wa-6UC">
<rect key="frame" x="51" y="272" width="273" height="61"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Song recommendations for your current mood" textAlignment="center" lineBreakMode="wordWrap" numberOfLines="5" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="6fX-wa-6UC">
<rect key="frame" x="51" y="293" width="273" height="41"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Y7P-rY-1Br">
<rect key="frame" x="142" y="617" width="91" height="30"/>
<state key="normal" title="User Study">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
<connections>
<segue destination="G7g-QG-zNK" kind="presentation" id="COY-mI-gOj"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" red="0.98823529409999999" green="0.19215686269999999" blue="0.34901960780000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="6fX-wa-6UC" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="51" id="IPD-dQ-U8m"/>
<constraint firstItem="Rqa-uL-a2b" firstAttribute="centerX" secondItem="NLu-8o-db9" secondAttribute="centerX" id="IdM-8H-wKd"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="bottom" secondItem="Y7P-rY-1Br" secondAttribute="bottom" constant="20" id="J6X-ae-csv"/>
<constraint firstItem="NLu-8o-db9" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="MwM-hu-dkc"/>
<constraint firstItem="Rqa-uL-a2b" firstAttribute="top" secondItem="6fX-wa-6UC" secondAttribute="bottom" constant="50" id="PmX-kb-auW"/>
<constraint firstItem="6fX-wa-6UC" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerY" constant="-20" id="QoI-t2-zXD"/>
<constraint firstItem="NLu-8o-db9" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="74" id="bxe-bm-ufE"/>
<constraint firstItem="Y7P-rY-1Br" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="142" id="chN-w3-ByX"/>
<constraint firstItem="6fX-wa-6UC" firstAttribute="centerX" secondItem="NLu-8o-db9" secondAttribute="centerX" id="iRk-b6-evO"/>
<constraint firstItem="Rqa-uL-a2b" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="125" id="mG0-Y9-N2E"/>
<constraint firstItem="6fX-wa-6UC" firstAttribute="top" secondItem="NLu-8o-db9" secondAttribute="bottom" constant="30" id="pkP-Bh-ce0"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="Y7P-rY-1Br" secondAttribute="trailing" constant="142" id="zY5-9V-cR5"/>
</constraints>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
<connections>
<outlet property="PhotoButton" destination="Rqa-uL-a2b" id="xDe-Nb-vc5"/>
<segue destination="7dN-K8-kAy" kind="presentation" identifier="resultsViewSegue" id="4id-7P-iyd"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
@@ -75,34 +87,15 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="ZNt-nn-kuI">
<rect key="frame" x="0.0" y="0.0" width="375" height="375"/>
<constraints>
<constraint firstAttribute="width" constant="375" id="3aw-ie-g99"/>
<constraint firstAttribute="height" constant="375" id="4G7-kb-ibC"/>
</constraints>
</imageView>
<button opaque="NO" alpha="0.69999999999999996" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="fa3-la-bGZ">
<rect key="frame" x="12" y="28" width="60" height="35"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<state key="normal" title="Back">
<color key="titleColor" cocoaTouchSystemColor="darkTextColor"/>
</state>
<connections>
<action selector="backButtonClick:" destination="7dN-K8-kAy" eventType="touchUpInside" id="yX0-SV-376"/>
</connections>
</button>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="iIj-Kh-GNK">
<rect key="frame" x="0.0" y="375" width="375" height="292"/>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="iIj-Kh-GNK">
<rect key="frame" x="0.0" y="284" width="375" height="383"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="b4d-GC-dH0">
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="cell" id="b4d-GC-dH0">
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="b4d-GC-dH0" id="jxY-if-ejB">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</tableViewCellContentView>
</tableViewCell>
@@ -112,21 +105,40 @@
<outlet property="delegate" destination="7dN-K8-kAy" id="tzI-Y0-W7O"/>
</connections>
</tableView>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="ZNt-nn-kuI" customClass="BorderedImageView" customModule="aff_song" customModuleProvider="target">
<rect key="frame" x="90" y="49" width="195" height="195"/>
<constraints>
<constraint firstAttribute="width" secondItem="ZNt-nn-kuI" secondAttribute="height" multiplier="1:1" id="0VL-my-7dU"/>
</constraints>
</imageView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="fa3-la-bGZ">
<rect key="frame" x="16" y="24" width="37" height="29"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<state key="normal" title="Close">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
<connections>
<action selector="backButtonClick:" destination="7dN-K8-kAy" eventType="touchUpInside" id="G5E-8L-NYJ"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="backgroundColor" red="0.98823529409999999" green="0.19215686269999999" blue="0.34901960780000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="ZNt-nn-kuI" firstAttribute="leading" secondItem="ini-zz-azT" secondAttribute="leading" id="0ZZ-mE-iMm"/>
<constraint firstItem="ZNt-nn-kuI" firstAttribute="leading" secondItem="ini-zz-azT" secondAttribute="leading" constant="90" id="0ZZ-mE-iMm"/>
<constraint firstItem="iIj-Kh-GNK" firstAttribute="bottom" secondItem="ini-zz-azT" secondAttribute="bottom" id="6SB-DN-7Gw"/>
<constraint firstItem="iIj-Kh-GNK" firstAttribute="trailing" secondItem="ini-zz-azT" secondAttribute="trailing" id="9rk-13-ArZ"/>
<constraint firstItem="ZNt-nn-kuI" firstAttribute="trailing" secondItem="ini-zz-azT" secondAttribute="trailing" id="heT-k5-vev"/>
<constraint firstItem="iIj-Kh-GNK" firstAttribute="bottom" secondItem="ini-zz-azT" secondAttribute="bottom" id="hmK-I0-Ecd"/>
<constraint firstItem="ZNt-nn-kuI" firstAttribute="top" secondItem="ini-zz-azT" secondAttribute="top" constant="29" id="G9M-Cc-nFl"/>
<constraint firstItem="ini-zz-azT" firstAttribute="trailing" secondItem="ZNt-nn-kuI" secondAttribute="trailing" constant="90" id="Q0e-An-6xI"/>
<constraint firstItem="fa3-la-bGZ" firstAttribute="leading" secondItem="ini-zz-azT" secondAttribute="leading" constant="16" id="QMJ-0L-VQY"/>
<constraint firstItem="fa3-la-bGZ" firstAttribute="top" secondItem="ini-zz-azT" secondAttribute="top" constant="4" id="RYO-LG-bOt"/>
<constraint firstItem="iIj-Kh-GNK" firstAttribute="leading" secondItem="ini-zz-azT" secondAttribute="leading" id="oYL-Os-jKT"/>
<constraint firstItem="iIj-Kh-GNK" firstAttribute="top" secondItem="ZNt-nn-kuI" secondAttribute="bottom" id="om0-fG-c5w"/>
<constraint firstItem="ZNt-nn-kuI" firstAttribute="top" secondItem="G5e-bH-Gft" secondAttribute="top" id="uYJ-EF-suT"/>
<constraint firstItem="iIj-Kh-GNK" firstAttribute="top" secondItem="ZNt-nn-kuI" secondAttribute="bottom" constant="40" id="om0-fG-c5w"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="fa3-la-bGZ" secondAttribute="trailing" constant="20" symbolic="YES" id="sA1-zW-XjR"/>
</constraints>
<viewLayoutGuide key="safeArea" id="ini-zz-azT"/>
</view>
<connections>
<outlet property="BackButton" destination="fa3-la-bGZ" id="Xw6-0u-hZI"/>
<outlet property="TrackTable" destination="iIj-Kh-GNK" id="d0a-2V-aXu"/>
<outlet property="imageView" destination="ZNt-nn-kuI" id="wGG-pn-Lre"/>
</connections>
@@ -135,5 +147,340 @@
</objects>
<point key="canvasLocation" x="759.20000000000005" y="-101.19940029985008"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="8Dj-Hk-iOc">
<objects>
<navigationController navigationBarHidden="YES" id="G7g-QG-zNK" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="mEA-iT-g8P">
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
<segue destination="VsZ-Qb-JPT" kind="relationship" relationship="rootViewController" id="1bY-xy-at9"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="LFF-dL-m3W" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-905" y="673"/>
</scene>
<!--Start View Controller-->
<scene sceneID="55x-EK-emz">
<objects>
<viewController id="VsZ-Qb-JPT" customClass="USStartViewController" customModule="aff_song" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="fNb-xL-3oz">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Q4f-1m-QEf" customClass="RoundedUIButton" customModule="aff_song" customModuleProvider="target">
<rect key="frame" x="125" y="497" width="125" height="50"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="1Kh-TB-Nao"/>
</constraints>
<color key="tintColor" red="0.98823529409999999" green="0.19215686269999999" blue="0.34901960780000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="Start"/>
<connections>
<segue destination="dIG-aH-2bA" kind="show" identifier="usStartSegues" id="Kwx-rm-fHl"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="TaA-L2-rwO">
<rect key="frame" x="160" y="572" width="55" height="30"/>
<state key="normal" title="Cancel">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
<connections>
<action selector="cancelButtonClicked:" destination="VsZ-Qb-JPT" eventType="touchUpInside" id="JO3-bv-np8"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" red="0.98823529409999999" green="0.19215686269999999" blue="0.34901960780000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="eZY-0c-5rA" firstAttribute="trailing" secondItem="TaA-L2-rwO" secondAttribute="trailing" constant="160" id="Cip-tr-oda"/>
<constraint firstItem="TaA-L2-rwO" firstAttribute="top" secondItem="Q4f-1m-QEf" secondAttribute="bottom" constant="25" id="ORP-Iy-JMC"/>
<constraint firstItem="TaA-L2-rwO" firstAttribute="leading" secondItem="eZY-0c-5rA" secondAttribute="leading" constant="160" id="X2S-PR-EUB"/>
<constraint firstItem="Q4f-1m-QEf" firstAttribute="leading" secondItem="eZY-0c-5rA" secondAttribute="leading" constant="125" id="a0g-NS-O6q"/>
<constraint firstItem="Q4f-1m-QEf" firstAttribute="centerX" secondItem="fNb-xL-3oz" secondAttribute="centerX" id="nYA-oS-Yue"/>
<constraint firstItem="eZY-0c-5rA" firstAttribute="bottom" secondItem="Q4f-1m-QEf" secondAttribute="bottom" constant="120" id="rsd-ys-6d3"/>
</constraints>
<viewLayoutGuide key="safeArea" id="eZY-0c-5rA"/>
</view>
<navigationItem key="navigationItem" id="HRW-O3-Y9W"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="YkG-7t-1mr" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-154" y="672"/>
</scene>
<!--Emoji View Controller-->
<scene sceneID="xFB-JT-fXe">
<objects>
<viewController id="dIG-aH-2bA" customClass="USEmojiViewController" customModule="aff_song" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="z5c-tz-Z5Z">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="tTE-za-2C4" customClass="RoundedUIButton" customModule="aff_song" customModuleProvider="target">
<rect key="frame" x="120" y="451" width="135" height="50"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="KNF-pa-gUJ"/>
</constraints>
<color key="tintColor" red="0.98823529409999999" green="0.19215686269999999" blue="0.34901960780000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="Take Photo"/>
<connections>
<action selector="openCameraButtonWithSender:" destination="dIG-aH-2bA" eventType="touchUpInside" id="oMN-Ej-Tla"/>
</connections>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="👽" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yVB-7b-XSy">
<rect key="frame" x="100" y="226" width="175" height="175"/>
<constraints>
<constraint firstAttribute="width" secondItem="yVB-7b-XSy" secondAttribute="height" multiplier="1:1" id="5lJ-1Y-40y"/>
<constraint firstAttribute="width" secondItem="yVB-7b-XSy" secondAttribute="height" multiplier="1:1" id="sM3-rY-dRk"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="100"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SUo-S7-g8E">
<rect key="frame" x="100" y="147" width="175" height="49"/>
<constraints>
<constraint firstAttribute="height" constant="49" id="qaB-ic-pu6"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="24"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="0.98823529409999999" green="0.19215686269999999" blue="0.34901960780000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="yVB-7b-XSy" firstAttribute="centerY" secondItem="z5c-tz-Z5Z" secondAttribute="centerY" constant="-20" id="BIm-6g-a7u"/>
<constraint firstItem="4Cn-zs-yHz" firstAttribute="trailing" secondItem="tTE-za-2C4" secondAttribute="trailing" constant="120" id="F1U-wp-t2T"/>
<constraint firstItem="4Cn-zs-yHz" firstAttribute="trailing" secondItem="SUo-S7-g8E" secondAttribute="trailing" constant="100" id="HwY-iM-lPq"/>
<constraint firstItem="tTE-za-2C4" firstAttribute="leading" secondItem="4Cn-zs-yHz" secondAttribute="leading" constant="120" id="KN7-Ki-5ZT"/>
<constraint firstItem="tTE-za-2C4" firstAttribute="top" secondItem="yVB-7b-XSy" secondAttribute="bottom" constant="50" id="Xo6-D6-Rjy"/>
<constraint firstItem="yVB-7b-XSy" firstAttribute="leading" secondItem="4Cn-zs-yHz" secondAttribute="leading" constant="100" id="eOh-SX-KwQ"/>
<constraint firstItem="yVB-7b-XSy" firstAttribute="top" secondItem="SUo-S7-g8E" secondAttribute="bottom" constant="30" id="mfD-KB-Ndg"/>
<constraint firstItem="4Cn-zs-yHz" firstAttribute="trailing" secondItem="yVB-7b-XSy" secondAttribute="trailing" constant="100" id="nuu-5h-1Jz"/>
<constraint firstItem="SUo-S7-g8E" firstAttribute="leading" secondItem="4Cn-zs-yHz" secondAttribute="leading" constant="100" id="uYP-63-J2x"/>
</constraints>
<viewLayoutGuide key="safeArea" id="4Cn-zs-yHz"/>
</view>
<connections>
<outlet property="EmojiLabel" destination="yVB-7b-XSy" id="gf9-Mm-exF"/>
<outlet property="EmotionLabel" destination="SUo-S7-g8E" id="53d-ay-REg"/>
<segue destination="4DT-qV-hjI" kind="show" identifier="usResultsSegue" id="hSV-kl-byD"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="42Y-2w-Tfc" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="642" y="672"/>
</scene>
<!--Results View Controller-->
<scene sceneID="adf-W6-Cva">
<objects>
<viewController useStoryboardIdentifierAsRestorationIdentifier="YES" id="4DT-qV-hjI" customClass="USResultsViewController" customModule="aff_song" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="D02-fx-JnK">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" rowHeight="-1" estimatedRowHeight="50" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="06U-Sq-BQO">
<rect key="frame" x="0.0" y="245" width="375" height="288"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="cell" id="32j-la-yXu">
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="32j-la-yXu" id="efb-LW-hG3">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</tableViewCellContentView>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="4DT-qV-hjI" id="PEc-U9-bEj"/>
<outlet property="delegate" destination="4DT-qV-hjI" id="8V0-35-aJv"/>
</connections>
</tableView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="pew-li-z4L" customClass="HCSStarRatingView">
<rect key="frame" x="112" y="553" width="150" height="44"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="width" constant="150" id="n8f-VD-v7Y"/>
<constraint firstAttribute="height" constant="44" id="uck-9i-jxJ"/>
</constraints>
</view>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Au4-Sf-shw">
<rect key="frame" x="156" y="617" width="62" height="30"/>
<state key="normal" title="Continue">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
<connections>
<segue destination="02j-bc-Fkp" kind="show" identifier="usAnnotateSegue" id="zpy-JF-zO3"/>
</connections>
</button>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="TpC-if-knL" customClass="BorderedImageView" customModule="aff_song" customModuleProvider="target">
<rect key="frame" x="110" y="70" width="155" height="155"/>
<constraints>
<constraint firstAttribute="width" secondItem="TpC-if-knL" secondAttribute="height" multiplier="1:1" id="cnt-a1-Tng"/>
</constraints>
</imageView>
</subviews>
<color key="backgroundColor" red="0.98823529409999999" green="0.19215686269999999" blue="0.34901960780000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="06U-Sq-BQO" firstAttribute="top" secondItem="TpC-if-knL" secondAttribute="bottom" constant="20" id="HSF-1S-0Sr"/>
<constraint firstItem="pew-li-z4L" firstAttribute="top" secondItem="06U-Sq-BQO" secondAttribute="bottom" constant="20" id="HoV-Lm-3OG"/>
<constraint firstItem="06U-Sq-BQO" firstAttribute="trailing" secondItem="CXV-Wx-4cp" secondAttribute="trailing" id="NDW-4S-VKs"/>
<constraint firstItem="Au4-Sf-shw" firstAttribute="top" secondItem="pew-li-z4L" secondAttribute="bottom" constant="20" id="QoO-wE-1gq"/>
<constraint firstItem="CXV-Wx-4cp" firstAttribute="trailing" secondItem="TpC-if-knL" secondAttribute="trailing" constant="110" id="Sry-QZ-8GH"/>
<constraint firstItem="pew-li-z4L" firstAttribute="centerX" secondItem="06U-Sq-BQO" secondAttribute="centerX" id="Vzr-TU-IZ7"/>
<constraint firstItem="TpC-if-knL" firstAttribute="leading" secondItem="CXV-Wx-4cp" secondAttribute="leading" constant="110" id="dbx-mv-hln"/>
<constraint firstItem="Au4-Sf-shw" firstAttribute="centerX" secondItem="pew-li-z4L" secondAttribute="centerX" id="gZ4-EI-LsC"/>
<constraint firstItem="06U-Sq-BQO" firstAttribute="leading" secondItem="CXV-Wx-4cp" secondAttribute="leading" id="kt2-Vi-CI3"/>
<constraint firstAttribute="bottom" secondItem="Au4-Sf-shw" secondAttribute="bottom" constant="20" symbolic="YES" id="ocY-3e-uLs"/>
<constraint firstItem="TpC-if-knL" firstAttribute="top" secondItem="CXV-Wx-4cp" secondAttribute="top" constant="50" id="q0g-iQ-OAT"/>
</constraints>
<viewLayoutGuide key="safeArea" id="CXV-Wx-4cp"/>
</view>
<connections>
<outlet property="StarRatingView" destination="pew-li-z4L" id="Vsm-Qo-izP"/>
<outlet property="TrackTable" destination="06U-Sq-BQO" id="63e-xc-398"/>
<outlet property="imageView" destination="TpC-if-knL" id="sG0-FB-mFv"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="xOe-o9-nXU" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1393" y="672"/>
</scene>
<!--Annotate View Controller-->
<scene sceneID="Nol-NR-odC">
<objects>
<viewController id="02j-bc-Fkp" customClass="USAnnotateViewController" customModule="aff_song" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="aTw-ob-Rdx">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="4pr-oy-QUs" customClass="RoundedUIButton" customModule="aff_song" customModuleProvider="target">
<rect key="frame" x="120" y="567" width="135" height="50"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="KuI-Se-j3m"/>
</constraints>
<state key="normal" title="Next">
<color key="titleColor" red="0.98823529409999999" green="0.19215686269999999" blue="0.34901960780000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<connections>
<action selector="ButtonClicked:" destination="02j-bc-Fkp" eventType="touchUpInside" id="5hS-ca-NyA"/>
</connections>
</button>
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="-1" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="KwK-6a-rUu">
<rect key="frame" x="38" y="336" width="299" height="30"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="29" id="9wM-sn-do3"/>
</constraints>
<color key="minimumTrackTintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="maximumTrackTintColor" white="1" alpha="0.5" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</slider>
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="-1" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="C7a-4Q-BgK">
<rect key="frame" x="38" y="446" width="299" height="52"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="minimumTrackTintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="maximumTrackTintColor" white="1" alpha="0.5" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</slider>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Valence" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dlY-vI-o9e">
<rect key="frame" x="140" y="295" width="95" height="21"/>
<constraints>
<constraint firstAttribute="height" constant="21" id="qlG-Ja-n01"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Arousal" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uTN-aD-DzN">
<rect key="frame" x="140" y="405" width="95" height="21"/>
<constraints>
<constraint firstAttribute="height" constant="21" id="Z6e-De-b8c"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="rE9-ON-F5D" customClass="BorderedImageView" customModule="aff_song" customModuleProvider="target">
<rect key="frame" x="110" y="70" width="155" height="155"/>
</imageView>
</subviews>
<color key="backgroundColor" red="0.98823529409999999" green="0.19215686269999999" blue="0.34901960780000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="rE9-ON-F5D" firstAttribute="width" secondItem="rE9-ON-F5D" secondAttribute="height" multiplier="1:1" id="19E-IV-4r7"/>
<constraint firstItem="KwK-6a-rUu" firstAttribute="leading" secondItem="I92-QM-jwb" secondAttribute="leading" constant="40" id="1yH-Xa-r7Q"/>
<constraint firstItem="I92-QM-jwb" firstAttribute="trailing" secondItem="dlY-vI-o9e" secondAttribute="trailing" constant="140" id="6mt-oa-znA"/>
<constraint firstItem="C7a-4Q-BgK" firstAttribute="top" secondItem="uTN-aD-DzN" secondAttribute="bottom" constant="20" id="MaY-MP-wpO"/>
<constraint firstItem="uTN-aD-DzN" firstAttribute="leading" secondItem="I92-QM-jwb" secondAttribute="leading" constant="140" id="N8i-mW-EYu"/>
<constraint firstItem="I92-QM-jwb" firstAttribute="bottom" secondItem="4pr-oy-QUs" secondAttribute="bottom" constant="50" id="Pv4-vG-xjG"/>
<constraint firstItem="dlY-vI-o9e" firstAttribute="top" secondItem="rE9-ON-F5D" secondAttribute="bottom" constant="70" id="Tbd-17-O1w"/>
<constraint firstItem="I92-QM-jwb" firstAttribute="trailing" secondItem="KwK-6a-rUu" secondAttribute="trailing" constant="40" id="UgU-eB-75O"/>
<constraint firstItem="4pr-oy-QUs" firstAttribute="leading" secondItem="I92-QM-jwb" secondAttribute="leading" constant="120" id="WSq-IE-eZF"/>
<constraint firstItem="I92-QM-jwb" firstAttribute="trailing" secondItem="4pr-oy-QUs" secondAttribute="trailing" constant="120" id="Wwx-tN-zPY"/>
<constraint firstItem="rE9-ON-F5D" firstAttribute="top" secondItem="I92-QM-jwb" secondAttribute="top" constant="50" id="XeD-7r-aQG"/>
<constraint firstItem="C7a-4Q-BgK" firstAttribute="leading" secondItem="I92-QM-jwb" secondAttribute="leading" constant="40" id="YG8-n6-XDu"/>
<constraint firstItem="KwK-6a-rUu" firstAttribute="top" secondItem="dlY-vI-o9e" secondAttribute="bottom" constant="20" id="abZ-fL-5Hl"/>
<constraint firstItem="I92-QM-jwb" firstAttribute="trailing" secondItem="uTN-aD-DzN" secondAttribute="trailing" constant="140" id="eim-lS-Wai"/>
<constraint firstItem="I92-QM-jwb" firstAttribute="trailing" secondItem="C7a-4Q-BgK" secondAttribute="trailing" constant="40" id="f1n-uH-N7Y"/>
<constraint firstItem="dlY-vI-o9e" firstAttribute="leading" secondItem="I92-QM-jwb" secondAttribute="leading" constant="140" id="hIj-1l-wYT"/>
<constraint firstItem="rE9-ON-F5D" firstAttribute="centerX" secondItem="KwK-6a-rUu" secondAttribute="centerX" id="jsX-1M-lUt"/>
<constraint firstItem="uTN-aD-DzN" firstAttribute="top" secondItem="KwK-6a-rUu" secondAttribute="bottom" constant="40" id="ltM-sL-2mD"/>
<constraint firstItem="rE9-ON-F5D" firstAttribute="leading" secondItem="I92-QM-jwb" secondAttribute="leading" constant="110" id="tkR-QI-S1B"/>
<constraint firstItem="4pr-oy-QUs" firstAttribute="top" secondItem="C7a-4Q-BgK" secondAttribute="bottom" constant="70" id="vW0-uP-bPd"/>
</constraints>
<viewLayoutGuide key="safeArea" id="I92-QM-jwb"/>
</view>
<connections>
<outlet property="ActionButton" destination="4pr-oy-QUs" id="Wsb-57-5m2"/>
<outlet property="ArousalSlider" destination="C7a-4Q-BgK" id="VN1-f6-iOd"/>
<outlet property="ValenceSlider" destination="KwK-6a-rUu" id="l18-CF-5fM"/>
<outlet property="imageView" destination="rE9-ON-F5D" id="5K6-bf-llN"/>
<segue destination="BF5-Y0-rPr" kind="unwind" identifier="usNextSegue" customClass="SlideHorSegue" customModule="aff_song" customModuleProvider="target" unwindAction="unwindToEmojiWithUnwindSegue:" id="7oA-gE-9Px"/>
<segue destination="VHG-fh-CqB" kind="show" identifier="usDoneSegue" id="aBb-Hn-f5T"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="qXG-jD-wl1" userLabel="First Responder" sceneMemberID="firstResponder"/>
<exit id="BF5-Y0-rPr" userLabel="Exit" sceneMemberID="exit"/>
</objects>
<point key="canvasLocation" x="2214" y="672"/>
</scene>
<!--Finish View Controller-->
<scene sceneID="bBT-4j-ftQ">
<objects>
<viewController id="VHG-fh-CqB" customClass="USFinishViewController" customModule="aff_song" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="LOh-rS-OAU">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Bam-GZ-0h6" customClass="RoundedUIButton" customModule="aff_song" customModuleProvider="target">
<rect key="frame" x="120" y="497" width="135" height="50"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="SIa-fx-DwU"/>
</constraints>
<state key="normal" title="Finish">
<color key="titleColor" red="0.98823529409999999" green="0.19215686269999999" blue="0.34901960780000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<connections>
<action selector="FinishButtonClicked:" destination="VHG-fh-CqB" eventType="touchUpInside" id="TKI-Zl-jir"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" red="0.98823529409999999" green="0.19215686269999999" blue="0.34901960780000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="Pkr-2k-W3E" firstAttribute="bottom" secondItem="Bam-GZ-0h6" secondAttribute="bottom" constant="120" id="94R-zc-Hli"/>
<constraint firstItem="Pkr-2k-W3E" firstAttribute="trailing" secondItem="Bam-GZ-0h6" secondAttribute="trailing" constant="120" id="Cf3-Ah-l9d"/>
<constraint firstItem="Bam-GZ-0h6" firstAttribute="leading" secondItem="Pkr-2k-W3E" secondAttribute="leading" constant="120" id="p9l-GN-nyA"/>
</constraints>
<viewLayoutGuide key="safeArea" id="Pkr-2k-W3E"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="gWf-OI-zAX" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="3015" y="672"/>
</scene>
</scenes>
</document>
@@ -0,0 +1,18 @@
//
// BorderedImageView.swift
// aff-song
//
// Created by Charlie Hewitt on 10/12/2017.
// Copyright © 2017 Charlie Hewitt. All rights reserved.
//
import Foundation
class BorderedImageView : UIImageView {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.layer.borderWidth = 1.0
self.layer.borderColor = UIColor.white.cgColor
}
}
+51
Ver Arquivo
@@ -0,0 +1,51 @@
// HCSStarRatingView.h
//
// Copyright (c) 2015 Hugo Sousa
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
@import UIKit;
typedef BOOL(^HCSStarRatingViewShouldBeginGestureRecognizerBlock)(UIGestureRecognizer *gestureRecognizer);
IB_DESIGNABLE
@interface HCSStarRatingView : UIControl
@property (nonatomic) IBInspectable NSUInteger maximumValue;
@property (nonatomic) IBInspectable CGFloat minimumValue;
@property (nonatomic) IBInspectable CGFloat value;
@property (nonatomic) IBInspectable CGFloat spacing;
@property (nonatomic) IBInspectable BOOL allowsHalfStars;
@property (nonatomic) IBInspectable BOOL accurateHalfStars;
@property (nonatomic) IBInspectable BOOL continuous;
@property (nonatomic) BOOL shouldBecomeFirstResponder;
// Optional: if `nil` method will return `NO`.
@property (nonatomic, copy) HCSStarRatingViewShouldBeginGestureRecognizerBlock shouldBeginGestureRecognizerBlock;
@property (nonatomic, strong) IBInspectable UIColor *starBorderColor;
@property (nonatomic) IBInspectable CGFloat starBorderWidth;
@property (nonatomic, strong) IBInspectable UIColor *emptyStarColor;
@property (nonatomic, strong) IBInspectable UIImage *emptyStarImage;
@property (nonatomic, strong) IBInspectable UIImage *halfStarImage;
@property (nonatomic, strong) IBInspectable UIImage *filledStarImage;
@end
+463
Ver Arquivo
@@ -0,0 +1,463 @@
// HCSStarRatingView.m
//
// Copyright (c) 2015 Hugo Sousa
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import "HCSStarRatingView.h"
@interface HCSStarRatingView ()
@property (nonatomic, readonly) BOOL shouldUseImages;
@end
@implementation HCSStarRatingView {
CGFloat _minimumValue;
NSUInteger _maximumValue;
CGFloat _value;
UIColor *_starBorderColor;
}
@dynamic minimumValue;
@dynamic maximumValue;
@dynamic value;
@dynamic shouldUseImages;
@dynamic starBorderColor;
#pragma mark - Initialization
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self _customInit];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self _customInit];
}
return self;
}
- (void)_customInit {
self.exclusiveTouch = YES;
_minimumValue = 0;
_maximumValue = 5;
_value = 0;
_spacing = 5.f;
_continuous = YES;
_starBorderWidth = 1.0f;
_emptyStarColor = [UIColor clearColor];
[self _updateAppearanceForState:self.enabled];
}
- (void)setNeedsLayout {
[super setNeedsLayout];
[self setNeedsDisplay];
}
#pragma mark - Properties
- (UIColor *)backgroundColor {
if ([super backgroundColor]) {
return [super backgroundColor];
} else {
return self.isOpaque ? [UIColor whiteColor] : [UIColor clearColor];
};
}
- (CGFloat)minimumValue {
return MAX(_minimumValue, 0);
}
- (void)setMinimumValue:(CGFloat)minimumValue {
if (_minimumValue != minimumValue) {
_minimumValue = minimumValue;
[self setNeedsDisplay];
}
}
- (NSUInteger)maximumValue {
return MAX(_minimumValue, _maximumValue);
}
- (void)setMaximumValue:(NSUInteger)maximumValue {
if (_maximumValue != maximumValue) {
_maximumValue = maximumValue;
[self setNeedsDisplay];
[self invalidateIntrinsicContentSize];
}
}
- (CGFloat)value {
return MIN(MAX(_value, _minimumValue), _maximumValue);
}
- (void)setValue:(CGFloat)value {
[self setValue:value sendValueChangedAction:NO];
}
- (void)setValue:(CGFloat)value sendValueChangedAction:(BOOL)sendAction {
[self willChangeValueForKey:NSStringFromSelector(@selector(value))];
if (_value != value && value >= _minimumValue && value <= _maximumValue) {
_value = value;
if (sendAction) [self sendActionsForControlEvents:UIControlEventValueChanged];
[self setNeedsDisplay];
}
[self didChangeValueForKey:NSStringFromSelector(@selector(value))];
}
- (void)setSpacing:(CGFloat)spacing {
_spacing = MAX(spacing, 0);
[self setNeedsDisplay];
}
- (void)setAllowsHalfStars:(BOOL)allowsHalfStars {
if (_allowsHalfStars != allowsHalfStars) {
_allowsHalfStars = allowsHalfStars;
[self setNeedsDisplay];
}
}
- (void)setAccurateHalfStars:(BOOL)accurateHalfStars {
if (_accurateHalfStars != accurateHalfStars) {
_accurateHalfStars = accurateHalfStars;
[self setNeedsDisplay];
}
}
- (void)setEmptyStarImage:(UIImage *)emptyStarImage {
if (_emptyStarImage != emptyStarImage) {
_emptyStarImage = emptyStarImage;
[self setNeedsDisplay];
}
}
- (void)setHalfStarImage:(UIImage *)halfStarImage {
if (_halfStarImage != halfStarImage) {
_halfStarImage = halfStarImage;
[self setNeedsDisplay];
}
}
- (void)setFilledStarImage:(UIImage *)filledStarImage {
if (_filledStarImage != filledStarImage) {
_filledStarImage = filledStarImage;
[self setNeedsDisplay];
}
}
- (void)setEmptyStarColor:(UIColor *)emptyStarColor {
if (_emptyStarColor != emptyStarColor) {
_emptyStarColor = emptyStarColor;
[self setNeedsDisplay];
}
}
- (void)setStarBorderColor:(UIColor *)starBorderColor {
if (_starBorderColor != starBorderColor) {
_starBorderColor = starBorderColor;
[self setNeedsDisplay];
}
}
- (UIColor *)starBorderColor {
if (_starBorderColor == nil) {
return self.tintColor;
} else {
return _starBorderColor;
}
}
- (void)setStarBorderWidth:(CGFloat)starBorderWidth {
_starBorderWidth = MAX(0, starBorderWidth);
[self setNeedsDisplay];
}
- (BOOL)shouldUseImages {
return (self.emptyStarImage!=nil && self.filledStarImage!=nil);
}
#pragma mark - State
- (void)setEnabled:(BOOL)enabled
{
[self _updateAppearanceForState:enabled];
[super setEnabled:enabled];
}
- (void)_updateAppearanceForState:(BOOL)enabled
{
self.alpha = enabled ? 1.f : .5f;
}
#pragma mark - Image Drawing
- (void)_drawStarImageWithFrame:(CGRect)frame tintColor:(UIColor*)tintColor highlighted:(BOOL)highlighted {
UIImage *image = highlighted ? self.filledStarImage : self.emptyStarImage;
[self _drawImage:image frame:frame tintColor:tintColor];
}
- (void)_drawHalfStarImageWithFrame:(CGRect)frame tintColor:(UIColor *)tintColor {
[self _drawAccurateHalfStarImageWithFrame:frame tintColor:tintColor progress:.5f];
}
- (void)_drawAccurateHalfStarImageWithFrame:(CGRect)frame tintColor:(UIColor *)tintColor progress:(CGFloat)progress {
UIImage *image = self.halfStarImage;
if (image == nil) {
// first draw star outline
[self _drawStarImageWithFrame:frame tintColor:tintColor highlighted:NO];
image = self.filledStarImage;
CGRect imageFrame = CGRectMake(0, 0, image.size.width * image.scale * progress, image.size.height * image.scale);
frame.size.width *= progress;
CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, imageFrame);
UIImage *halfImage = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:image.imageOrientation];
image = [halfImage imageWithRenderingMode:image.renderingMode];
CGImageRelease(imageRef);
}
[self _drawImage:image frame:frame tintColor:tintColor];
}
- (void)_drawImage:(UIImage *)image frame:(CGRect)frame tintColor:(UIColor *)tintColor {
if (image.renderingMode == UIImageRenderingModeAlwaysTemplate) {
[tintColor setFill];
}
[image drawInRect:frame];
}
#pragma mark - Shape Drawing
- (void)_drawStarShapeWithFrame:(CGRect)frame tintColor:(UIColor*)tintColor highlighted:(BOOL)highlighted {
[self _drawAccurateHalfStarShapeWithFrame:frame tintColor:tintColor progress:highlighted ? 1.f : 0.f];
}
- (void)_drawHalfStarShapeWithFrame:(CGRect)frame tintColor:(UIColor *)tintColor {
[self _drawAccurateHalfStarShapeWithFrame:frame tintColor:tintColor progress:.5f];
}
- (void)_drawAccurateHalfStarShapeWithFrame:(CGRect)frame tintColor:(UIColor *)tintColor progress:(CGFloat)progress {
UIBezierPath* starShapePath = UIBezierPath.bezierPath;
[starShapePath moveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.62723 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.37309 * CGRectGetHeight(frame))];
[starShapePath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.50000 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.02500 * CGRectGetHeight(frame))];
[starShapePath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.37292 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.37309 * CGRectGetHeight(frame))];
[starShapePath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.02500 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.39112 * CGRectGetHeight(frame))];
[starShapePath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.30504 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.62908 * CGRectGetHeight(frame))];
[starShapePath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.20642 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.97500 * CGRectGetHeight(frame))];
[starShapePath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.50000 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.78265 * CGRectGetHeight(frame))];
[starShapePath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.79358 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.97500 * CGRectGetHeight(frame))];
[starShapePath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.69501 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.62908 * CGRectGetHeight(frame))];
[starShapePath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.97500 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.39112 * CGRectGetHeight(frame))];
[starShapePath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.62723 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.37309 * CGRectGetHeight(frame))];
[starShapePath closePath];
starShapePath.miterLimit = 4;
CGFloat frameWidth = frame.size.width;
CGRect rightRectOfStar = CGRectMake(frame.origin.x + progress * frameWidth, frame.origin.y, frameWidth - progress * frameWidth, frame.size.height);
UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:CGRectInfinite];
[clipPath appendPath:[UIBezierPath bezierPathWithRect:rightRectOfStar]];
clipPath.usesEvenOddFillRule = YES;
[_emptyStarColor setFill];
[starShapePath fill];
CGContextSaveGState(UIGraphicsGetCurrentContext()); {
[clipPath addClip];
[tintColor setFill];
[starShapePath fill];
}
CGContextRestoreGState(UIGraphicsGetCurrentContext());
[self.starBorderColor setStroke];
starShapePath.lineWidth = _starBorderWidth;
[starShapePath stroke];
}
#pragma mark - Drawing
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, self.backgroundColor.CGColor);
CGContextFillRect(context, rect);
CGFloat availableWidth = rect.size.width - (_spacing * (_maximumValue - 1)) - 2;
CGFloat cellWidth = (availableWidth / _maximumValue);
CGFloat starSide = (cellWidth <= rect.size.height) ? cellWidth : rect.size.height;
starSide = (self.shouldUseImages) ? starSide : (starSide - _starBorderWidth);
for (int idx = 0; idx < _maximumValue; idx++) {
CGPoint center = CGPointMake(cellWidth*idx + cellWidth/2 + _spacing*idx + 1, rect.size.height/2);
CGRect frame = CGRectMake(center.x - starSide/2, center.y - starSide/2, starSide, starSide);
BOOL highlighted = (idx+1 <= ceilf(_value));
if (_allowsHalfStars && highlighted && (idx+1 > _value)) {
if (_accurateHalfStars) {
[self _drawAccurateStarWithFrame:frame tintColor:self.tintColor progress:_value - idx];
}
else {
[self _drawHalfStarWithFrame:frame tintColor:self.tintColor];
}
} else {
[self _drawStarWithFrame:frame tintColor:self.tintColor highlighted:highlighted];
}
}
}
- (void)_drawStarWithFrame:(CGRect)frame tintColor:(UIColor *)tintColor highlighted:(BOOL)highlighted {
if (self.shouldUseImages) {
[self _drawStarImageWithFrame:frame tintColor:tintColor highlighted:highlighted];
} else {
[self _drawStarShapeWithFrame:frame tintColor:tintColor highlighted:highlighted];
}
}
- (void)_drawHalfStarWithFrame:(CGRect)frame tintColor:(UIColor *)tintColor {
if (self.shouldUseImages) {
[self _drawHalfStarImageWithFrame:frame tintColor:tintColor];
} else {
[self _drawHalfStarShapeWithFrame:frame tintColor:tintColor];
}
}
- (void)_drawAccurateStarWithFrame:(CGRect)frame tintColor:(UIColor *)tintColor progress:(CGFloat)progress {
if (self.shouldUseImages) {
[self _drawAccurateHalfStarImageWithFrame:frame tintColor:tintColor progress:progress];
} else {
[self _drawAccurateHalfStarShapeWithFrame:frame tintColor:tintColor progress:progress];
}
}
#pragma mark - Touches
- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
if (self.isEnabled) {
[super beginTrackingWithTouch:touch withEvent:event];
if (_shouldBecomeFirstResponder && ![self isFirstResponder]) {
[self becomeFirstResponder];
}
[self _handleTouch:touch];
return YES;
} else {
return NO;
}
}
- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
if (self.isEnabled) {
[super continueTrackingWithTouch:touch withEvent:event];
[self _handleTouch:touch];
return YES;
} else {
return NO;
}
}
- (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
[super endTrackingWithTouch:touch withEvent:event];
if (_shouldBecomeFirstResponder && [self isFirstResponder]) {
[self resignFirstResponder];
}
[self _handleTouch:touch];
if (!_continuous) {
[self sendActionsForControlEvents:UIControlEventValueChanged];
}
}
- (void)cancelTrackingWithEvent:(UIEvent *)event {
[super cancelTrackingWithEvent:event];
if (_shouldBecomeFirstResponder && [self isFirstResponder]) {
[self resignFirstResponder];
}
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if ([gestureRecognizer.view isEqual:self]) {
return !self.isUserInteractionEnabled;
}
return self.shouldBeginGestureRecognizerBlock ? self.shouldBeginGestureRecognizerBlock(gestureRecognizer) : NO;
}
- (void)_handleTouch:(UITouch *)touch {
CGFloat cellWidth = self.bounds.size.width / _maximumValue;
CGPoint location = [touch locationInView:self];
CGFloat value = location.x / cellWidth;
if (_allowsHalfStars) {
if (_accurateHalfStars) {
value = value;
}
else {
if (value+.5f < ceilf(value)) {
value = floor(value)+.5f;
} else {
value = ceilf(value);
}
}
} else {
value = ceilf(value);
}
[self setValue:value sendValueChangedAction:_continuous];
}
#pragma mark - First responder
- (BOOL)canBecomeFirstResponder {
return _shouldBecomeFirstResponder;
}
#pragma mark - Intrinsic Content Size
- (CGSize)intrinsicContentSize {
CGFloat height = 44.f;
return CGSizeMake(_maximumValue * height + (_maximumValue-1) * _spacing, height);
}
#pragma mark - Accessibility
- (BOOL)isAccessibilityElement {
return YES;
}
- (NSString *)accessibilityLabel {
return [super accessibilityLabel] ?: NSLocalizedString(@"Rating", @"Accessibility label for star rating control.");
}
- (UIAccessibilityTraits)accessibilityTraits {
return ([super accessibilityTraits] | UIAccessibilityTraitAdjustable);
}
- (NSString *)accessibilityValue {
return [@(self.value) description];
}
- (BOOL)accessibilityActivate {
return YES;
}
- (void)accessibilityIncrement {
CGFloat value = self.value + (self.allowsHalfStars ? .5f : 1.f);
[self setValue:value sendValueChangedAction:YES];
}
- (void)accessibilityDecrement {
CGFloat value = self.value - (self.allowsHalfStars ? .5f : 1.f);
[self setValue:value sendValueChangedAction:YES];
}
@end
+2
Ver Arquivo
@@ -32,6 +32,8 @@
<array>
<string>armv7</string>
</array>
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleLightContent</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
+58 -14
Ver Arquivo
@@ -8,28 +8,19 @@
import UIKit
import CoreML
import Vision
class ResultsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
class ResultsViewController: AffUIViewController, UITableViewDataSource, UITableViewDelegate {
var spotifyAuthKey : String = ""
var faceImage : UIImage?
var tracks : [[String]]?
@IBOutlet var imageView: UIImageView!
@IBOutlet weak var BackButton: UIButton!
@IBOutlet weak var TrackTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let gradient = CAGradientLayer()
gradient.frame = view.bounds
let c1 = UIColor(red: 252.0/255.0, green: 49.0/255.0, blue: 89.0/255.0, alpha: 1.0)
let c2 = UIColor(red: 252.0/255.0, green: 45.0/255.0, blue: 119.0/255.0, alpha: 1.0)
gradient.colors = [c1.cgColor, c2.cgColor]
view.layer.insertSublayer(gradient, at: 0)
BackButton.layer.cornerRadius = BackButton.layer.frame.height/2
let (valence, arousal) = getAffect(image: faceImage)
imageView.image = faceImage
let (valence, arousal) = getAffect(image: faceImage)
getSongs(valence: valence, arousal: arousal, callback: {tracks in
self.tracks = tracks
DispatchQueue.main.async {
@@ -39,6 +30,7 @@ class ResultsViewController: UIViewController, UITableViewDataSource, UITableVie
}
@IBAction func backButtonClick(_ sender: Any) {
print("BACK")
dismiss(animated: true, completion: nil)
}
@@ -48,11 +40,14 @@ class ResultsViewController: UIViewController, UITableViewDataSource, UITableVie
}
func getSongs(valence : Double, arousal: Double, callback: @escaping ([[String]])->Void){
guard let authKey = UserDefaults.standard.string(forKey: "SpotifyAuthToken") else {
fatalError("Spotify auth failed")
}
let urlPath: String = "https://api.spotify.com/v1/recommendations?seed_genres=pop,rock,dance&valence=\(valence)&danceability=\(arousal)&limit=5&market=GB"
print(urlPath)
var request: URLRequest = URLRequest(url: URL(string: urlPath)!)
request.httpMethod = "GET"
request.addValue("Bearer " + self.spotifyAuthKey, forHTTPHeaderField: "Authorization")
request.addValue("Bearer " + authKey, forHTTPHeaderField: "Authorization")
let session = URLSession.shared
session.dataTask(with: request) {data, response, err in
@@ -74,6 +69,11 @@ class ResultsViewController: UIViewController, UITableViewDataSource, UITableVie
func getAffect(image: UIImage?) -> (Double, Double) {
// TODO CNN
// let model = nil
// let pixelBuffer = UIImage(cgImage: image.cgImage).pixelBuffer()
// guard let modelPrediction = try? model.prediction(image: pixelBuffer) else {
// fatalError("Unexpected runtime error.")
// }
return (0.5, 0.5)
}
@@ -97,3 +97,47 @@ class ResultsViewController: UIViewController, UITableViewDataSource, UITableVie
UIApplication.shared.openURL(URL(string: self.tracks![indexPath.row][2])!)
}
}
extension UIImage {
func pixelBuffer() -> CVPixelBuffer? {
let width = self.size.width
let height = self.size.height
let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue,
kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue] as CFDictionary
var pixelBuffer: CVPixelBuffer?
let status = CVPixelBufferCreate(kCFAllocatorDefault,
Int(width),
Int(height),
kCVPixelFormatType_OneComponent8,
attrs,
&pixelBuffer)
guard let resultPixelBuffer = pixelBuffer, status == kCVReturnSuccess else {
return nil
}
CVPixelBufferLockBaseAddress(resultPixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
let pixelData = CVPixelBufferGetBaseAddress(resultPixelBuffer)
let grayColorSpace = CGColorSpaceCreateDeviceGray()
guard let context = CGContext(data: pixelData,
width: Int(width),
height: Int(height),
bitsPerComponent: 8,
bytesPerRow: CVPixelBufferGetBytesPerRow(resultPixelBuffer),
space: grayColorSpace,
bitmapInfo: CGImageAlphaInfo.none.rawValue) else {
return nil
}
context.translateBy(x: 0, y: height)
context.scaleBy(x: 1.0, y: -1.0)
UIGraphicsPushContext(context)
self.draw(in: CGRect(x: 0, y: 0, width: width, height: height))
UIGraphicsPopContext()
CVPixelBufferUnlockBaseAddress(resultPixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
return resultPixelBuffer
}
}
+16
Ver Arquivo
@@ -0,0 +1,16 @@
//
// RoundedUIButton.swift
// aff-song
//
// Created by Charlie Hewitt on 10/12/2017.
// Copyright © 2017 Charlie Hewitt. All rights reserved.
//
import Foundation
class RoundedUIButton : UIButton {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.layer.cornerRadius = self.frame.height/2
}
}
+30
Ver Arquivo
@@ -0,0 +1,30 @@
//
// SlideHorSegue.swift
// aff-song
//
// Created by Charlie Hewitt on 10/12/2017.
// Copyright © 2017 Charlie Hewitt. All rights reserved.
//
import UIKit
class SlideHorSegue: UIStoryboardSegue {
override func perform() {
//set the ViewControllers for the animation
let sourceView = self.source.view as UIView!
let destinationView = self.destination.view as UIView!
let window = UIApplication.shared.delegate?.window!
window?.insertSubview(destinationView!, belowSubview: sourceView!)
destinationView?.center = CGPoint(x: (sourceView?.center.x)! + (destinationView?.frame.width)!, y: (sourceView?.center.y)!)
UIView.animate(withDuration: 0.4,
animations: {
destinationView?.center = CGPoint(x: (sourceView?.center.x)!, y: (sourceView?.center.y)!)
}, completion: {
(value: Bool) in
destinationView?.removeFromSuperview()
if let navController = self.destination.navigationController {
navController.popToViewController(self.destination, animated: false)
}
})
}
}
@@ -0,0 +1,38 @@
//
// USAnnotateViewController.swift
// aff-song
//
// Created by Charlie Hewitt on 10/12/2017.
// Copyright © 2017 Charlie Hewitt. All rights reserved.
//
import Foundation
class USAnnotateViewController : AffUIViewController {
var emotion: Int?
var faceImage: UIImage?
@IBOutlet weak var ActionButton: RoundedUIButton!
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var ValenceSlider: UISlider!
@IBOutlet weak var ArousalSlider: UISlider!
override func viewDidLoad() {
super.viewDidLoad()
imageView.image = faceImage
if (emotion! > 6) {
ActionButton.titleLabel?.text = "Finish"
}
}
@IBAction func ButtonClicked(_ sender: Any) {
// TODO save values
prtin(ValenceSlider.value, ArousalSlider.value)
if(emotion! > 6){
self.performSegue(withIdentifier: "usDoneSegue", sender: self)
}
else {
self.performSegue(withIdentifier: "usNextSegue", sender: self)
}
}
}
@@ -0,0 +1,161 @@
//
// USEmojiViewController.swift
// aff-song
//
// Created by Charlie Hewitt on 10/12/2017.
// Copyright © 2017 Charlie Hewitt. All rights reserved.
//
import Foundation
import Vision
class USEmojiViewController : AffUIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var faceImage : UIImage?
var emotion: Int = 0
@IBOutlet weak var EmotionLabel: UILabel!
@IBOutlet weak var EmojiLabel: UILabel!
@IBAction func unwindToEmoji(unwindSegue: UIStoryboardSegue) {
emotion += 1
updateForEmotionChange()
}
override func viewDidLoad() {
super.viewDidLoad()
updateForEmotionChange()
}
func updateForEmotionChange() {
var emotionText : String?
var emotionEmoji : String?
switch emotion {
case 0:
emotionText = "Neutral"
emotionEmoji = "😐"
break
case 1:
emotionText = "Happy"
emotionEmoji = "😀"
break
case 2:
emotionText = "Sad"
emotionEmoji = "😟"
break
case 3:
emotionText = "Suprised"
emotionEmoji = "😲"
break
case 4:
emotionText = "Afraid"
emotionEmoji = "😨"
break
case 5:
emotionText = "Disgusted"
emotionEmoji = "😖"
break
case 6:
emotionText = "Angry"
emotionEmoji = "😡"
break
case 7:
emotionText = "Contemptful"
emotionEmoji = "🤨"
break
default:
emotionText = "Error"
emotionEmoji = "🤪"
}
EmotionLabel.text = emotionText
EmojiLabel.text = emotionEmoji
}
@IBAction func openCameraButton(sender: AnyObject) {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .camera
imagePicker.cameraDevice = .front
imagePicker.allowsEditing = false
self.present(imagePicker, animated: true, completion: nil)
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage,
let face = detectFaces(image: pickedImage) {
self.faceImage = face
dismiss(animated: true, completion: {
self.performSegue(withIdentifier: "usResultsSegue", sender: self)
})
}
else {
dismiss(animated: true, completion: nil)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "usResultsSegue" {
if let nextViewController = segue.destination as? USResultsViewController {
nextViewController.faceImage = self.faceImage
nextViewController.emotion = self.emotion
}
}
}
func detectFaces(image: UIImage) -> UIImage? {
let orientation = CGImagePropertyOrientation(rawValue: imageOrientationToExif(image: image))!
let faceDetectionRequest = VNDetectFaceRectanglesRequest()
let myRequestHandler = VNImageRequestHandler(cgImage: image.cgImage!, orientation: orientation, options: [:])
try! myRequestHandler.perform([faceDetectionRequest])
guard let results = faceDetectionRequest.results,
let cgImage = image.cgImage,
results.count > 0 else {
return nil
}
for observation in faceDetectionRequest.results as! [VNFaceObservation] {
let box = observation.boundingBox
// iOS is a joke for image handling...
// flip h/w as in portrait but cg image is landscape
let imw = CGFloat(cgImage.height)
let imh = CGFloat(cgImage.width)
let w = box.size.width * imw
let h = box.size.height * imh
let x = box.origin.x * imw
let y = box.origin.y * imh
// and fix for stupid coordinate system inconsistencies
let cropRect = CGRect(x: imh - (y+h), y: imw - (x+w), width: h, height: w)
let croppedCGImage: CGImage = cgImage.cropping(to: cropRect)!
let croppedUIImage: UIImage = UIImage(cgImage: croppedCGImage, scale: image.scale, orientation: image.imageOrientation)
let size = CGSize(width:256,height:256)
UIGraphicsBeginImageContextWithOptions(size, false, image.scale)
croppedUIImage.draw(in: CGRect(origin: CGPoint.zero, size: size))
let scaledImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return scaledImage
}
return nil
}
func imageOrientationToExif(image: UIImage) -> uint {
switch image.imageOrientation {
case .up:
return 1;
case .down:
return 3;
case .left:
return 8;
case .right:
return 6;
case .upMirrored:
return 2;
case .downMirrored:
return 4;
case .leftMirrored:
return 5;
case .rightMirrored:
return 7;
}
}
}
@@ -0,0 +1,17 @@
//
// USFinishViewController.swift
// aff-song
//
// Created by Charlie Hewitt on 10/12/2017.
// Copyright © 2017 Charlie Hewitt. All rights reserved.
//
import Foundation
class USFinishViewController : AffUIViewController {
@IBAction func FinishButtonClicked(_ sender: Any) {
// performSegue(withIdentifier: "returnToFrontSegue", sender: self)
self.navigationController?.dismiss(animated: true, completion: nil)
}
}
@@ -0,0 +1,31 @@
//
// USResultsViewController.swift
// aff-song
//
// Created by Charlie Hewitt on 10/12/2017.
// Copyright © 2017 Charlie Hewitt. All rights reserved.
//
import Foundation
class USResultsViewController: ResultsViewController, UINavigationControllerDelegate {
var emotion: Int?
@IBOutlet weak var StarRatingView: HCSStarRatingView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "usAnnotateSegue" {
// TODO save rating
print(StarRatingView.value)
if let nextViewController = segue.destination as? USAnnotateViewController {
nextViewController.emotion = self.emotion
nextViewController.faceImage = self.faceImage
}
}
}
}
@@ -0,0 +1,16 @@
//
// USStartViewController.swift
// aff-song
//
// Created by Charlie Hewitt on 10/12/2017.
// Copyright © 2017 Charlie Hewitt. All rights reserved.
//
import Foundation
class USStartViewController : AffUIViewController {
@IBAction func cancelButtonClicked(_ sender: Any) {
navigationController?.dismiss(animated: true, completion: nil)
}
}
+8 -42
Ver Arquivo
@@ -10,29 +10,15 @@ import UIKit
import Vision
import CoreGraphics
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
class ViewController: AffUIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var spotifyAuthKey : String = ""
var faceImage : UIImage?
@IBOutlet weak var PhotoButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
PhotoButton.layer.cornerRadius = PhotoButton.layer.frame.height/2
let gradient = CAGradientLayer()
gradient.frame = view.bounds
let c1 = UIColor(red: 252.0/255.0, green: 49.0/255.0, blue: 89.0/255.0, alpha: 1.0)
let c2 = UIColor(red: 252.0/255.0, green: 45.0/255.0, blue: 119.0/255.0, alpha: 1.0)
gradient.colors = [c1.cgColor, c2.cgColor]
view.layer.insertSublayer(gradient, at: 0)
refreshAuth()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func openCameraButton(sender: AnyObject) {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
@@ -46,10 +32,12 @@ class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavig
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
self.faceImage = detectFaces(image: pickedImage)!
dismiss(animated: true, completion: nil)
performSegue(withIdentifier: "resultsViewSegue", sender: self)
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage,
let face = detectFaces(image: pickedImage) {
self.faceImage = face
dismiss(animated: true, completion: {
self.performSegue(withIdentifier: "resultsViewSegue", sender: self)
})
}
else {
dismiss(animated: true, completion: nil)
@@ -60,7 +48,6 @@ class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavig
if segue.identifier == "resultsViewSegue" {
if let imageViewController = segue.destination as? ResultsViewController {
imageViewController.faceImage = self.faceImage
imageViewController.spotifyAuthKey = self.spotifyAuthKey
}
}
}
@@ -99,27 +86,6 @@ class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavig
return nil
}
func refreshAuth() {
// get a new auth key from spotify
let url: String = "https://accounts.spotify.com/api/token"
var request: URLRequest = URLRequest(url: URL(string: url)!)
let bodyData = "grant_type=refresh_token&client_id=75f91608ce154091a1f419be415cbdda&client_secret=a6609b179eb140b086c2f6cc2c35adf4&refresh_token=AQBeDOqXW6kerokqh6WbEexkOQH5FtWGfDvw2DLePMofXTAVOUGsygF5iWYx0jtCjBUFO31qslCGNcRNh6vXGv9wxxbEuyNyWFy-t1YuYON2UD_ySlzSCcjAWsI2YiKzFAc"
request.httpBody = bodyData.data(using: String.Encoding.utf8);
request.httpMethod = "POST"
let session = URLSession.shared
session.dataTask(with: request) {data, response, err in
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String:Any]
if let authKey = json["access_token"] {
self.spotifyAuthKey = authKey as! String
}
} catch let error {
print(error.localizedDescription)
}
}.resume()
}
func imageOrientationToExif(image: UIImage) -> uint {
switch image.imageOrientation {
case .up:
@@ -0,0 +1,5 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "HCSStarRatingView.h"
-22
Ver Arquivo
@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
@@ -1,36 +0,0 @@
//
// aff_songTests.swift
// aff-songTests
//
// Created by Charlie Hewitt on 08/12/2017.
// Copyright © 2017 Charlie Hewitt. All rights reserved.
//
import XCTest
@testable import aff_song
class aff_songTests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}
}
-22
Ver Arquivo
@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
@@ -1,36 +0,0 @@
//
// aff_songUITests.swift
// aff-songUITests
//
// Created by Charlie Hewitt on 08/12/2017.
// Copyright © 2017 Charlie Hewitt. All rights reserved.
//
import XCTest
class aff_songUITests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
// In UI tests it is usually best to stop immediately when a failure occurs.
continueAfterFailure = false
// UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
XCUIApplication().launch()
// In UI tests its important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testExample() {
// Use recording to get started writing UI tests.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
}
BIN
Ver Arquivo
Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 19 KiB

BIN
Ver Arquivo
Arquivo binário não exibido.
+14 -3
Ver Arquivo
@@ -1,10 +1,14 @@
from keras.preprocessing import image
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D, Activation, Dropout, Flatten, Dense
from keras.utils.np_utils import to_categorical
from math import floor
import csv
import numpy as np
# TODO classifier for emotions too (use to_categorical on labels)
CLASSIFY_OR_REGRESS = 1
def load_images(paths, labels, batch_size=32):
while True:
batch_n = 0
@@ -61,9 +65,12 @@ model.add(Dense(1024, activation='relu'))
model.add(Dropout(0.4))
model.add(Dense(1024, activation='relu'))
model.add(Dropout(0.4))
model.add(Dense(2, activation='linear'))
model.compile(loss='mean_squared_error', optimizer='adam')
if CLASSIFY_OR_REGRESS == 0:
model.add(Dense(7, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
else:
model.add(Dense(2, activation='linear'))
model.compile(loss='mean_squared_error', optimizer='adam')
t_paths, t_labels = load_paths('training.csv')
v_paths, v_labels = load_paths('validation.csv')
@@ -76,4 +83,8 @@ model.fit_generator(
validation_data=load_images(v_paths,v_labels, batch_size),
validation_steps=800 // batch_size)
for k in model.layers:
if type(k) is keras.layers.Dropout:
model.layers.remove(k)
model.save_weights('aff_net.h5')