diff --git a/.gitignore b/.gitignore index 93c86d3..04217b7 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ Carthage/Build # `pod install` in .travis.yml # # Pods/ +IDEWorkspaceChecks.plist diff --git a/.travis.yml b/.travis.yml index b3ae6c9..ed2de48 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,8 @@ -# references: -# * https://www.objc.io/issues/6-build-tools/travis-ci/ -# * https://github.com/supermarin/xcpretty#usage - -osx_image: xcode7.3 language: objective-c -# cache: cocoapods -# podfile: Example/Podfile -# before_install: -# - gem install cocoapods # Since Travis is not always on latest version -# - pod install --project-directory=Example +osx_image: xcode10 +before_install: +- gem update fastlane --no-ri --no-rdoc --no-document +- gem update cocoapods --no-ri --no-rdoc --no-document script: -- set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/PunkAPI.xcworkspace -scheme PunkAPI-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty -- pod lib lint +- cd Example/ +- fastlane ci diff --git a/Example/Podfile.lock b/Example/Podfile.lock new file mode 100644 index 0000000..cf454a6 --- /dev/null +++ b/Example/Podfile.lock @@ -0,0 +1,16 @@ +PODS: + - PunkAPI (0.1.0) + +DEPENDENCIES: + - PunkAPI (from `../`) + +EXTERNAL SOURCES: + PunkAPI: + :path: "../" + +SPEC CHECKSUMS: + PunkAPI: c9891a38a2efa7a052f02d02decceb58ca87b5ed + +PODFILE CHECKSUM: 77a7edfbda92bc42f026175f2a4105df175a2c99 + +COCOAPODS: 1.5.3 diff --git a/Example/Pods/Local Podspecs/PunkAPI.podspec.json b/Example/Pods/Local Podspecs/PunkAPI.podspec.json new file mode 100644 index 0000000..a076944 --- /dev/null +++ b/Example/Pods/Local Podspecs/PunkAPI.podspec.json @@ -0,0 +1,24 @@ +{ + "name": "PunkAPI", + "version": "0.1.0", + "summary": "A little swift wrapper for PunkAPI by @samjbmason", + "swift_version": "4.2", + "description": "\"Have you ever wanted to search through Brewdog's expansive back catalogue of beer in a programmatic way? Maybe build a tool that pairs beer with food, or search beers with an abv of more than 4%? Well now your prayers have been answered!\"", + "homepage": "https://github.com/Oni-zerone/PunkAPI", + "license": { + "type": "MIT", + "file": "LICENSE" + }, + "authors": { + "Andrea Altea": "oni.zerone@gmail.com" + }, + "source": { + "git": "https://github.com/Oni-zerone/PunkAPI.git", + "tag": "0.1.0" + }, + "social_media_url": "https://twitter.com/Oni_zerone", + "platforms": { + "ios": "10.0" + }, + "source_files": "PunkAPI/Classes/**/*" +} diff --git a/Example/Pods/Manifest.lock b/Example/Pods/Manifest.lock new file mode 100644 index 0000000..cf454a6 --- /dev/null +++ b/Example/Pods/Manifest.lock @@ -0,0 +1,16 @@ +PODS: + - PunkAPI (0.1.0) + +DEPENDENCIES: + - PunkAPI (from `../`) + +EXTERNAL SOURCES: + PunkAPI: + :path: "../" + +SPEC CHECKSUMS: + PunkAPI: c9891a38a2efa7a052f02d02decceb58ca87b5ed + +PODFILE CHECKSUM: 77a7edfbda92bc42f026175f2a4105df175a2c99 + +COCOAPODS: 1.5.3 diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj new file mode 100644 index 0000000..1f6f8ef --- /dev/null +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -0,0 +1,889 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 040633ED2DA398496AD631E73B9CB953 /* Beer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C6F916B3844F173B183C5BC45E825DC /* Beer.swift */; }; + 0706F758C5F2CE0E83E44396DE53B472 /* StringParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D332B9F96F752E235840BDE2286619A5 /* StringParameter.swift */; }; + 0C4C6C5EED9509237E097606FBBF2046 /* BeerRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6968BCE43B140E358870F66D7258F957 /* BeerRequest.swift */; }; + 156976A157354FAC4A76CDD07C60C630 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2718DFE97DA930B98881C184088EFA6B /* Errors.swift */; }; + 1DEF7BF616CC3F2EF46A7F9E5514F9AC /* Pods-PunkAPI_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 34E9F6D3BEDEF11CDF5DC7C24AEF5989 /* Pods-PunkAPI_Tests-dummy.m */; }; + 1F269E313E3E5E6D95C7EA4117A4EF52 /* RequestParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E73CF54C263C0540BBD135CCBAE448F9 /* RequestParameter.swift */; }; + 4C4AB5D20013C59D1BE1A0DC0AA4A90E /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67F5B1D8A153F21971D389D7D78E3709 /* Request.swift */; }; + 4DE6F5415AA32E45E1A1B40AA8194B63 /* Pods-PunkAPI_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E322AC54183F0711E107C333BF42C3CF /* Pods-PunkAPI_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4F478C6F6571A694E377026C7020B987 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6DFF15000AFE2A371BF499E7AFDA808 /* Foundation.framework */; }; + 5563E1330468FB6D76F769A6697DF682 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6DFF15000AFE2A371BF499E7AFDA808 /* Foundation.framework */; }; + 567123199E19D2AF982C095A91F499E3 /* PunkAPI-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = AF457128C49817820875EFC37DDC2763 /* PunkAPI-dummy.m */; }; + 58196BD46A6A962CD2291747E891A4FF /* Recipe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FEECE1958551B13C700A5127274F0A0 /* Recipe.swift */; }; + 861F0ED5029160D63BEA52EEDC4F5B2D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6DFF15000AFE2A371BF499E7AFDA808 /* Foundation.framework */; }; + 8CA6935D75E79F06DC50B80FBFA04E52 /* BeersRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67A36C69522325B64312822D021FE1AA /* BeersRequest.swift */; }; + 94ACB62152B83DE972430EAA4B24D449 /* PunkAPI-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E6E75F5999AC210521146C7375A3313 /* PunkAPI-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9C1115413D21B46B31F5D70FE29CA857 /* Method.swift in Sources */ = {isa = PBXBuildFile; fileRef = 272E2F86C0B64A9624B4C3B045C95054 /* Method.swift */; }; + 9DEE51DC320AFD89F8CCE79E659D0E92 /* Pods-PunkAPI_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ABEAC72915A583BE08AF19F226F5157 /* Pods-PunkAPI_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9E26D0BC2A8D1AB927AD665EB5032162 /* PunkAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5EF39F3AF34782AC8545A51C195DF61 /* PunkAPI.swift */; }; + 9EB5A8CE4227261D6FDB84878505ACED /* RandomBeerRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCA6949E012F3A32EE618525D6C1C918 /* RandomBeerRequest.swift */; }; + 9F91EF3525A1E94F87950035B1DEF148 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06A91CE54D5004C034494C163FD6F954 /* Result.swift */; }; + A2A4C282870BFE912F85DB1151BC24B3 /* DateParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E53AB03421ECCCAC36BA6463E532AF2D /* DateParameter.swift */; }; + AA5C8E19C31A6A5CDAD11062F1625806 /* URLBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F1A67AAC30418B7829B4645C698A64E /* URLBuilder.swift */; }; + ADCB0254782B197A401A2AAC39C0E882 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E63AF47725611B0A82E5D288783A976 /* Configuration.swift */; }; + B0D852DC953C7A0E2C1CB872F9E315BB /* Pods-PunkAPI_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A4E9F26077D1238C6BF679ED6AB0504D /* Pods-PunkAPI_Example-dummy.m */; }; + BBCC787A76C3C536D049EB6E228394FF /* Quantity.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0640B723338BC89B5BF58530FC5A3D0 /* Quantity.swift */; }; + EA2895A6DC98FCFBB5A54F5837E8304F /* FloatParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EB937A449C35D61D642784A44C83FF1 /* FloatParameter.swift */; }; + FAEC0D53EBA4A5BCFCDA4CB97EA975AA /* BeersRequestParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52B3CD426204500053E942213EDD6A6 /* BeersRequestParameter.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 1BD9253D912BA229A3617AE941991ACC /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 104A4972E6668483EF3BA6EE08D840AF; + remoteInfo = PunkAPI; + }; + 26AB40795B0BA17DA83D7BA25EA5107F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = C1DB41E820BFF9D57C1A713EEC3A7C98; + remoteInfo = "Pods-PunkAPI_Example"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 06A91CE54D5004C034494C163FD6F954 /* Result.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = ""; }; + 06BAF05CBDEA8E295E4784A5A5D4506C /* Pods-PunkAPI_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PunkAPI_Tests-acknowledgements.plist"; sourceTree = ""; }; + 073D13EDB6E52C7CA76600719DF8FCCA /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 08865B1A9072612C58080056C52A36BE /* Pods-PunkAPI_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PunkAPI_Example.modulemap"; sourceTree = ""; }; + 0C6F916B3844F173B183C5BC45E825DC /* Beer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Beer.swift; sourceTree = ""; }; + 16EF8876C605E8EC561718EF37E64EF9 /* PunkAPI-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PunkAPI-prefix.pch"; sourceTree = ""; }; + 1E8F3184E27473ACF2CB0ECC931D49B9 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = ""; }; + 2718DFE97DA930B98881C184088EFA6B /* Errors.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = ""; }; + 272E2F86C0B64A9624B4C3B045C95054 /* Method.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Method.swift; sourceTree = ""; }; + 2EC29BADC6D4B129C97F077B8D1AAD24 /* Pods-PunkAPI_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PunkAPI_Example-frameworks.sh"; sourceTree = ""; }; + 34E9F6D3BEDEF11CDF5DC7C24AEF5989 /* Pods-PunkAPI_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PunkAPI_Tests-dummy.m"; sourceTree = ""; }; + 3CA7DD0E0D9E3D052F0DA83C7B3B79FC /* Pods_PunkAPI_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_PunkAPI_Tests.framework; path = "Pods-PunkAPI_Tests.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 3EB937A449C35D61D642784A44C83FF1 /* FloatParameter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = FloatParameter.swift; sourceTree = ""; }; + 492C127C07A0D9D778B3D645FCDED6AC /* Pods-PunkAPI_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PunkAPI_Tests.release.xcconfig"; sourceTree = ""; }; + 4F1A67AAC30418B7829B4645C698A64E /* URLBuilder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = URLBuilder.swift; sourceTree = ""; }; + 5E6E75F5999AC210521146C7375A3313 /* PunkAPI-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PunkAPI-umbrella.h"; sourceTree = ""; }; + 5FEECE1958551B13C700A5127274F0A0 /* Recipe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Recipe.swift; sourceTree = ""; }; + 608E9332AF8468043B49B03317025805 /* Pods-PunkAPI_Tests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PunkAPI_Tests-frameworks.sh"; sourceTree = ""; }; + 67A36C69522325B64312822D021FE1AA /* BeersRequest.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BeersRequest.swift; sourceTree = ""; }; + 67F5B1D8A153F21971D389D7D78E3709 /* Request.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Request.swift; sourceTree = ""; }; + 6968BCE43B140E358870F66D7258F957 /* BeerRequest.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BeerRequest.swift; sourceTree = ""; }; + 6ABEAC72915A583BE08AF19F226F5157 /* Pods-PunkAPI_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-PunkAPI_Example-umbrella.h"; sourceTree = ""; }; + 6EDD1194CE9C142C26AD6C6803C306E4 /* Pods-PunkAPI_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PunkAPI_Tests.debug.xcconfig"; sourceTree = ""; }; + 7F7764549D1799C2D5D6A7B2D65E3550 /* Pods-PunkAPI_Example-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PunkAPI_Example-resources.sh"; sourceTree = ""; }; + 8342B62283B06E1CA90A14E1BCB6D62B /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 8458C84A594F726E1A8DB6294F78DB73 /* Pods-PunkAPI_Tests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PunkAPI_Tests-resources.sh"; sourceTree = ""; }; + 92229C81AD3A318707A49C8449AEB2F5 /* Pods-PunkAPI_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PunkAPI_Example-acknowledgements.plist"; sourceTree = ""; }; + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 9A4A66A2F2CD393AE19E9C41284E7A10 /* PunkAPI.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; path = PunkAPI.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 9D14926C4AE138B3C55CE27E18BE194D /* Pods-PunkAPI_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PunkAPI_Tests.modulemap"; sourceTree = ""; }; + 9DDE148E1E89B985353411506461E509 /* Pods_PunkAPI_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_PunkAPI_Example.framework; path = "Pods-PunkAPI_Example.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 9E63AF47725611B0A82E5D288783A976 /* Configuration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Configuration.swift; path = PunkAPI/Classes/Configuration.swift; sourceTree = ""; }; + A4E9F26077D1238C6BF679ED6AB0504D /* Pods-PunkAPI_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PunkAPI_Example-dummy.m"; sourceTree = ""; }; + A52B3CD426204500053E942213EDD6A6 /* BeersRequestParameter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BeersRequestParameter.swift; sourceTree = ""; }; + A5D146483FC9684CF2C15F85C081EF35 /* Pods-PunkAPI_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PunkAPI_Example.release.xcconfig"; sourceTree = ""; }; + AF457128C49817820875EFC37DDC2763 /* PunkAPI-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PunkAPI-dummy.m"; sourceTree = ""; }; + C0640B723338BC89B5BF58530FC5A3D0 /* Quantity.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Quantity.swift; sourceTree = ""; }; + D332B9F96F752E235840BDE2286619A5 /* StringParameter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StringParameter.swift; sourceTree = ""; }; + D5EF39F3AF34782AC8545A51C195DF61 /* PunkAPI.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PunkAPI.swift; path = PunkAPI/Classes/PunkAPI.swift; sourceTree = ""; }; + D6DFF15000AFE2A371BF499E7AFDA808 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + DEC567BAB5C34B4B7667B6C1478CE2DA /* PunkAPI.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = PunkAPI.modulemap; sourceTree = ""; }; + E322AC54183F0711E107C333BF42C3CF /* Pods-PunkAPI_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-PunkAPI_Tests-umbrella.h"; sourceTree = ""; }; + E53AB03421ECCCAC36BA6463E532AF2D /* DateParameter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DateParameter.swift; sourceTree = ""; }; + E722B264627A535D845CCF418E225784 /* Pods-PunkAPI_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PunkAPI_Tests-acknowledgements.markdown"; sourceTree = ""; }; + E73CF54C263C0540BBD135CCBAE448F9 /* RequestParameter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = RequestParameter.swift; sourceTree = ""; }; + E816F7DA6C1CBE532E1590E0F05B9532 /* Pods-PunkAPI_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PunkAPI_Example.debug.xcconfig"; sourceTree = ""; }; + EAE741F8D3D7DED0544AD07D421892ED /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + F5FCAD7EA85132D2D8D1388DA3081592 /* PunkAPI.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = PunkAPI.xcconfig; sourceTree = ""; }; + FA66D5ED6E33AA7DD32A8C962841F3B0 /* PunkAPI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = PunkAPI.framework; path = PunkAPI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + FAD9273D9A1D66770D45A643EDA9E88E /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; + FB1D3C212D7A0519F22CF554E249675E /* Pods-PunkAPI_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PunkAPI_Example-acknowledgements.markdown"; sourceTree = ""; }; + FCA6949E012F3A32EE618525D6C1C918 /* RandomBeerRequest.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = RandomBeerRequest.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 2AC16E9D9907618B6A4F41C69D4587F0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4F478C6F6571A694E377026C7020B987 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64469F9A8CDA0C6CFDD8BA665E002A2F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5563E1330468FB6D76F769A6697DF682 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 76E7A3CBB25A47B13596EDBA2CE7AB07 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 861F0ED5029160D63BEA52EEDC4F5B2D /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0514815A5F57F1358DA701F5C9BCA5D2 /* Results */ = { + isa = PBXGroup; + children = ( + 2718DFE97DA930B98881C184088EFA6B /* Errors.swift */, + 06A91CE54D5004C034494C163FD6F954 /* Result.swift */, + ); + name = Results; + path = PunkAPI/Classes/Results; + sourceTree = ""; + }; + 090992C0DECBC3153B28556E0B42A41B /* Request */ = { + isa = PBXGroup; + children = ( + 6968BCE43B140E358870F66D7258F957 /* BeerRequest.swift */, + 67A36C69522325B64312822D021FE1AA /* BeersRequest.swift */, + FCA6949E012F3A32EE618525D6C1C918 /* RandomBeerRequest.swift */, + 67F5B1D8A153F21971D389D7D78E3709 /* Request.swift */, + 4F1A67AAC30418B7829B4645C698A64E /* URLBuilder.swift */, + 64A82D6E12F29B9C311952C99CAAF80D /* Parameter */, + ); + name = Request; + path = PunkAPI/Classes/Request; + sourceTree = ""; + }; + 1EAE5A66A94268C182B75D7DB0BFCB3F /* Pod */ = { + isa = PBXGroup; + children = ( + FAD9273D9A1D66770D45A643EDA9E88E /* LICENSE */, + 9A4A66A2F2CD393AE19E9C41284E7A10 /* PunkAPI.podspec */, + 1E8F3184E27473ACF2CB0ECC931D49B9 /* README.md */, + ); + name = Pod; + sourceTree = ""; + }; + 3C48D264DEAC135E647F4628351B96D3 /* Development Pods */ = { + isa = PBXGroup; + children = ( + F7A6E9EE825581F4F5E91FACA3E20C0F /* PunkAPI */, + ); + name = "Development Pods"; + sourceTree = ""; + }; + 44D5347904CF754D6785B84253F2574A /* iOS */ = { + isa = PBXGroup; + children = ( + D6DFF15000AFE2A371BF499E7AFDA808 /* Foundation.framework */, + ); + name = iOS; + sourceTree = ""; + }; + 5E6C37C04887F82A8C550F9B76E5B746 /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + 9BFECB8663CD309F9214B4311C96BCB5 /* Pods-PunkAPI_Example */, + B2D5CC793D96E6B1A0442EA2481F7DF2 /* Pods-PunkAPI_Tests */, + ); + name = "Targets Support Files"; + sourceTree = ""; + }; + 64A82D6E12F29B9C311952C99CAAF80D /* Parameter */ = { + isa = PBXGroup; + children = ( + A52B3CD426204500053E942213EDD6A6 /* BeersRequestParameter.swift */, + E53AB03421ECCCAC36BA6463E532AF2D /* DateParameter.swift */, + 3EB937A449C35D61D642784A44C83FF1 /* FloatParameter.swift */, + E73CF54C263C0540BBD135CCBAE448F9 /* RequestParameter.swift */, + D332B9F96F752E235840BDE2286619A5 /* StringParameter.swift */, + ); + name = Parameter; + path = Parameter; + sourceTree = ""; + }; + 6C92B5E2C39B71B9A3D59EB753CF598A /* Products */ = { + isa = PBXGroup; + children = ( + 9DDE148E1E89B985353411506461E509 /* Pods_PunkAPI_Example.framework */, + 3CA7DD0E0D9E3D052F0DA83C7B3B79FC /* Pods_PunkAPI_Tests.framework */, + FA66D5ED6E33AA7DD32A8C962841F3B0 /* PunkAPI.framework */, + ); + name = Products; + sourceTree = ""; + }; + 7DB346D0F39D3F0E887471402A8071AB = { + isa = PBXGroup; + children = ( + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, + 3C48D264DEAC135E647F4628351B96D3 /* Development Pods */, + BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */, + 6C92B5E2C39B71B9A3D59EB753CF598A /* Products */, + 5E6C37C04887F82A8C550F9B76E5B746 /* Targets Support Files */, + ); + sourceTree = ""; + }; + 883B8E4B6F6171944650345EDD78EC6C /* Content */ = { + isa = PBXGroup; + children = ( + 0C6F916B3844F173B183C5BC45E825DC /* Beer.swift */, + 272E2F86C0B64A9624B4C3B045C95054 /* Method.swift */, + C0640B723338BC89B5BF58530FC5A3D0 /* Quantity.swift */, + 5FEECE1958551B13C700A5127274F0A0 /* Recipe.swift */, + ); + name = Content; + path = PunkAPI/Classes/Content; + sourceTree = ""; + }; + 9BFECB8663CD309F9214B4311C96BCB5 /* Pods-PunkAPI_Example */ = { + isa = PBXGroup; + children = ( + 8342B62283B06E1CA90A14E1BCB6D62B /* Info.plist */, + 08865B1A9072612C58080056C52A36BE /* Pods-PunkAPI_Example.modulemap */, + FB1D3C212D7A0519F22CF554E249675E /* Pods-PunkAPI_Example-acknowledgements.markdown */, + 92229C81AD3A318707A49C8449AEB2F5 /* Pods-PunkAPI_Example-acknowledgements.plist */, + A4E9F26077D1238C6BF679ED6AB0504D /* Pods-PunkAPI_Example-dummy.m */, + 2EC29BADC6D4B129C97F077B8D1AAD24 /* Pods-PunkAPI_Example-frameworks.sh */, + 7F7764549D1799C2D5D6A7B2D65E3550 /* Pods-PunkAPI_Example-resources.sh */, + 6ABEAC72915A583BE08AF19F226F5157 /* Pods-PunkAPI_Example-umbrella.h */, + E816F7DA6C1CBE532E1590E0F05B9532 /* Pods-PunkAPI_Example.debug.xcconfig */, + A5D146483FC9684CF2C15F85C081EF35 /* Pods-PunkAPI_Example.release.xcconfig */, + ); + name = "Pods-PunkAPI_Example"; + path = "Target Support Files/Pods-PunkAPI_Example"; + sourceTree = ""; + }; + B2D5CC793D96E6B1A0442EA2481F7DF2 /* Pods-PunkAPI_Tests */ = { + isa = PBXGroup; + children = ( + EAE741F8D3D7DED0544AD07D421892ED /* Info.plist */, + 9D14926C4AE138B3C55CE27E18BE194D /* Pods-PunkAPI_Tests.modulemap */, + E722B264627A535D845CCF418E225784 /* Pods-PunkAPI_Tests-acknowledgements.markdown */, + 06BAF05CBDEA8E295E4784A5A5D4506C /* Pods-PunkAPI_Tests-acknowledgements.plist */, + 34E9F6D3BEDEF11CDF5DC7C24AEF5989 /* Pods-PunkAPI_Tests-dummy.m */, + 608E9332AF8468043B49B03317025805 /* Pods-PunkAPI_Tests-frameworks.sh */, + 8458C84A594F726E1A8DB6294F78DB73 /* Pods-PunkAPI_Tests-resources.sh */, + E322AC54183F0711E107C333BF42C3CF /* Pods-PunkAPI_Tests-umbrella.h */, + 6EDD1194CE9C142C26AD6C6803C306E4 /* Pods-PunkAPI_Tests.debug.xcconfig */, + 492C127C07A0D9D778B3D645FCDED6AC /* Pods-PunkAPI_Tests.release.xcconfig */, + ); + name = "Pods-PunkAPI_Tests"; + path = "Target Support Files/Pods-PunkAPI_Tests"; + sourceTree = ""; + }; + BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */ = { + isa = PBXGroup; + children = ( + 44D5347904CF754D6785B84253F2574A /* iOS */, + ); + name = Frameworks; + sourceTree = ""; + }; + CB553B8B7B06165B82FCA92BD5137F9D /* Support Files */ = { + isa = PBXGroup; + children = ( + 073D13EDB6E52C7CA76600719DF8FCCA /* Info.plist */, + DEC567BAB5C34B4B7667B6C1478CE2DA /* PunkAPI.modulemap */, + F5FCAD7EA85132D2D8D1388DA3081592 /* PunkAPI.xcconfig */, + AF457128C49817820875EFC37DDC2763 /* PunkAPI-dummy.m */, + 16EF8876C605E8EC561718EF37E64EF9 /* PunkAPI-prefix.pch */, + 5E6E75F5999AC210521146C7375A3313 /* PunkAPI-umbrella.h */, + ); + name = "Support Files"; + path = "Example/Pods/Target Support Files/PunkAPI"; + sourceTree = ""; + }; + F7A6E9EE825581F4F5E91FACA3E20C0F /* PunkAPI */ = { + isa = PBXGroup; + children = ( + 9E63AF47725611B0A82E5D288783A976 /* Configuration.swift */, + D5EF39F3AF34782AC8545A51C195DF61 /* PunkAPI.swift */, + 883B8E4B6F6171944650345EDD78EC6C /* Content */, + 1EAE5A66A94268C182B75D7DB0BFCB3F /* Pod */, + 090992C0DECBC3153B28556E0B42A41B /* Request */, + 0514815A5F57F1358DA701F5C9BCA5D2 /* Results */, + CB553B8B7B06165B82FCA92BD5137F9D /* Support Files */, + ); + name = PunkAPI; + path = ../..; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 6BAF60135FDFD6B381631C7BED9969B3 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 94ACB62152B83DE972430EAA4B24D449 /* PunkAPI-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 88CEDC5C00738D5465027D297EB9644D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 4DE6F5415AA32E45E1A1B40AA8194B63 /* Pods-PunkAPI_Tests-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E95C4D0DC25D5A98B2A4C4AAFDAD0596 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 9DEE51DC320AFD89F8CCE79E659D0E92 /* Pods-PunkAPI_Example-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 104A4972E6668483EF3BA6EE08D840AF /* PunkAPI */ = { + isa = PBXNativeTarget; + buildConfigurationList = C5CFB8D87EAAD43FF2A708011ADF9DF5 /* Build configuration list for PBXNativeTarget "PunkAPI" */; + buildPhases = ( + 6BAF60135FDFD6B381631C7BED9969B3 /* Headers */, + 86F73B177785FEBCB3F340D791903737 /* Sources */, + 64469F9A8CDA0C6CFDD8BA665E002A2F /* Frameworks */, + 971F83F24AFBDD4CF88BD6ED289EEB1C /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PunkAPI; + productName = PunkAPI; + productReference = FA66D5ED6E33AA7DD32A8C962841F3B0 /* PunkAPI.framework */; + productType = "com.apple.product-type.framework"; + }; + C1DB41E820BFF9D57C1A713EEC3A7C98 /* Pods-PunkAPI_Example */ = { + isa = PBXNativeTarget; + buildConfigurationList = B97836D74BBC103F707A992128BA2EBA /* Build configuration list for PBXNativeTarget "Pods-PunkAPI_Example" */; + buildPhases = ( + E95C4D0DC25D5A98B2A4C4AAFDAD0596 /* Headers */, + AEF952ACEC65192DB68BBAE0B794131A /* Sources */, + 2AC16E9D9907618B6A4F41C69D4587F0 /* Frameworks */, + C0A4E0BED8488FF565D86ADC701B8084 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + AC80DFE7429FC940D34413A8CD236866 /* PBXTargetDependency */, + ); + name = "Pods-PunkAPI_Example"; + productName = "Pods-PunkAPI_Example"; + productReference = 9DDE148E1E89B985353411506461E509 /* Pods_PunkAPI_Example.framework */; + productType = "com.apple.product-type.framework"; + }; + D4B40E035E9C8A43CF581FE371EB5EA1 /* Pods-PunkAPI_Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 418812EEE776D4446934FDEFBBAAB6E0 /* Build configuration list for PBXNativeTarget "Pods-PunkAPI_Tests" */; + buildPhases = ( + 88CEDC5C00738D5465027D297EB9644D /* Headers */, + 7D76001470C4ECFAD45A4E50C07DF2B8 /* Sources */, + 76E7A3CBB25A47B13596EDBA2CE7AB07 /* Frameworks */, + 6822401903D7AFC3F5ECA9D7C022FFB9 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 4F84539F116C2CCA3F4B274DE3A3066E /* PBXTargetDependency */, + ); + name = "Pods-PunkAPI_Tests"; + productName = "Pods-PunkAPI_Tests"; + productReference = 3CA7DD0E0D9E3D052F0DA83C7B3B79FC /* Pods_PunkAPI_Tests.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0930; + LastUpgradeCheck = 0930; + }; + buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 7DB346D0F39D3F0E887471402A8071AB; + productRefGroup = 6C92B5E2C39B71B9A3D59EB753CF598A /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + C1DB41E820BFF9D57C1A713EEC3A7C98 /* Pods-PunkAPI_Example */, + D4B40E035E9C8A43CF581FE371EB5EA1 /* Pods-PunkAPI_Tests */, + 104A4972E6668483EF3BA6EE08D840AF /* PunkAPI */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 6822401903D7AFC3F5ECA9D7C022FFB9 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 971F83F24AFBDD4CF88BD6ED289EEB1C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C0A4E0BED8488FF565D86ADC701B8084 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7D76001470C4ECFAD45A4E50C07DF2B8 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1DEF7BF616CC3F2EF46A7F9E5514F9AC /* Pods-PunkAPI_Tests-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 86F73B177785FEBCB3F340D791903737 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 040633ED2DA398496AD631E73B9CB953 /* Beer.swift in Sources */, + 0C4C6C5EED9509237E097606FBBF2046 /* BeerRequest.swift in Sources */, + 8CA6935D75E79F06DC50B80FBFA04E52 /* BeersRequest.swift in Sources */, + FAEC0D53EBA4A5BCFCDA4CB97EA975AA /* BeersRequestParameter.swift in Sources */, + ADCB0254782B197A401A2AAC39C0E882 /* Configuration.swift in Sources */, + A2A4C282870BFE912F85DB1151BC24B3 /* DateParameter.swift in Sources */, + 156976A157354FAC4A76CDD07C60C630 /* Errors.swift in Sources */, + EA2895A6DC98FCFBB5A54F5837E8304F /* FloatParameter.swift in Sources */, + 9C1115413D21B46B31F5D70FE29CA857 /* Method.swift in Sources */, + 567123199E19D2AF982C095A91F499E3 /* PunkAPI-dummy.m in Sources */, + 9E26D0BC2A8D1AB927AD665EB5032162 /* PunkAPI.swift in Sources */, + BBCC787A76C3C536D049EB6E228394FF /* Quantity.swift in Sources */, + 9EB5A8CE4227261D6FDB84878505ACED /* RandomBeerRequest.swift in Sources */, + 58196BD46A6A962CD2291747E891A4FF /* Recipe.swift in Sources */, + 4C4AB5D20013C59D1BE1A0DC0AA4A90E /* Request.swift in Sources */, + 1F269E313E3E5E6D95C7EA4117A4EF52 /* RequestParameter.swift in Sources */, + 9F91EF3525A1E94F87950035B1DEF148 /* Result.swift in Sources */, + 0706F758C5F2CE0E83E44396DE53B472 /* StringParameter.swift in Sources */, + AA5C8E19C31A6A5CDAD11062F1625806 /* URLBuilder.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AEF952ACEC65192DB68BBAE0B794131A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B0D852DC953C7A0E2C1CB872F9E315BB /* Pods-PunkAPI_Example-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 4F84539F116C2CCA3F4B274DE3A3066E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Pods-PunkAPI_Example"; + target = C1DB41E820BFF9D57C1A713EEC3A7C98 /* Pods-PunkAPI_Example */; + targetProxy = 26AB40795B0BA17DA83D7BA25EA5107F /* PBXContainerItemProxy */; + }; + AC80DFE7429FC940D34413A8CD236866 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = PunkAPI; + target = 104A4972E6668483EF3BA6EE08D840AF /* PunkAPI */; + targetProxy = 1BD9253D912BA229A3617AE941991ACC /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 0B544C28097B1323AC34E22808695EB6 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F5FCAD7EA85132D2D8D1388DA3081592 /* PunkAPI.xcconfig */; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/PunkAPI/PunkAPI-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/PunkAPI/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/PunkAPI/PunkAPI.modulemap"; + PRODUCT_MODULE_NAME = PunkAPI; + PRODUCT_NAME = PunkAPI; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 0F7F14A2385ED2D3C3346A495562A023 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E816F7DA6C1CBE532E1590E0F05B9532 /* Pods-PunkAPI_Example.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PunkAPI_Example/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 8D795C21A9507CA6A9E811BFB95FEAC5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6EDD1194CE9C142C26AD6C6803C306E4 /* Pods-PunkAPI_Tests.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PunkAPI_Tests/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 8DDFA5FA8D4131BFD96E5E26F3672644 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_ALLOWED = NO; + CODE_SIGNING_REQUIRED = NO; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.2; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; + A6182063646965CD3A9B8CBF97BA24A3 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A5D146483FC9684CF2C15F85C081EF35 /* Pods-PunkAPI_Example.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PunkAPI_Example/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + D44F402051D76F6439E6BA95C278A702 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 492C127C07A0D9D778B3D645FCDED6AC /* Pods-PunkAPI_Tests.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PunkAPI_Tests/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + D5F759C82752B2EB010DB3CD3D69707C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_ALLOWED = NO; + CODE_SIGNING_REQUIRED = NO; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_RELEASE=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 4.2; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Release; + }; + E478EE7340C05210B36C506ACA88CC8F /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F5FCAD7EA85132D2D8D1388DA3081592 /* PunkAPI.xcconfig */; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/PunkAPI/PunkAPI-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/PunkAPI/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/PunkAPI/PunkAPI.modulemap"; + PRODUCT_MODULE_NAME = PunkAPI; + PRODUCT_NAME = PunkAPI; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8DDFA5FA8D4131BFD96E5E26F3672644 /* Debug */, + D5F759C82752B2EB010DB3CD3D69707C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 418812EEE776D4446934FDEFBBAAB6E0 /* Build configuration list for PBXNativeTarget "Pods-PunkAPI_Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8D795C21A9507CA6A9E811BFB95FEAC5 /* Debug */, + D44F402051D76F6439E6BA95C278A702 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B97836D74BBC103F707A992128BA2EBA /* Build configuration list for PBXNativeTarget "Pods-PunkAPI_Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0F7F14A2385ED2D3C3346A495562A023 /* Debug */, + A6182063646965CD3A9B8CBF97BA24A3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C5CFB8D87EAAD43FF2A708011ADF9DF5 /* Build configuration list for PBXNativeTarget "PunkAPI" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E478EE7340C05210B36C506ACA88CC8F /* Debug */, + 0B544C28097B1323AC34E22808695EB6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; +} diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Info.plist b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Info.plist new file mode 100644 index 0000000..2243fe6 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-acknowledgements.markdown b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-acknowledgements.markdown new file mode 100644 index 0000000..d23ace9 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-acknowledgements.markdown @@ -0,0 +1,26 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## PunkAPI + +Copyright (c) 2019 acct= + +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. + +Generated by CocoaPods - https://cocoapods.org diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-acknowledgements.plist b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-acknowledgements.plist new file mode 100644 index 0000000..8ef8216 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-acknowledgements.plist @@ -0,0 +1,58 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2019 acct<blob>=<NULL> <oni.zerone@gmail.com> + +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. + + License + MIT + Title + PunkAPI + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-dummy.m b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-dummy.m new file mode 100644 index 0000000..34e855b --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_PunkAPI_Example : NSObject +@end +@implementation PodsDummy_Pods_PunkAPI_Example +@end diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-frameworks.sh b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-frameworks.sh new file mode 100755 index 0000000..7684ffc --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-frameworks.sh @@ -0,0 +1,153 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then + # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy + # frameworks to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" + +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} + +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + if [ -r "$source" ]; then + # Copy the dSYM into a the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .framework.dSYM "$source")" + binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then + strip_invalid_archs "$binary" + fi + + if [[ $STRIP_BINARY_RETVAL == 1 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" + fi + fi +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identitiy + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + STRIP_BINARY_RETVAL=0 + return + fi + stripped="" + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" || exit 1 + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi + STRIP_BINARY_RETVAL=1 +} + + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/PunkAPI/PunkAPI.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/PunkAPI/PunkAPI.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-resources.sh b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-resources.sh new file mode 100755 index 0000000..345301f --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-resources.sh @@ -0,0 +1,118 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then + # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy + # resources to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + +RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt +> "$RESOURCES_TO_COPY" + +XCASSET_FILES=() + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +case "${TARGETED_DEVICE_FAMILY:-}" in + 1,2) + TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" + ;; + 1) + TARGET_DEVICE_ARGS="--target-device iphone" + ;; + 2) + TARGET_DEVICE_ARGS="--target-device ipad" + ;; + 3) + TARGET_DEVICE_ARGS="--target-device tv" + ;; + 4) + TARGET_DEVICE_ARGS="--target-device watch" + ;; + *) + TARGET_DEVICE_ARGS="--target-device mac" + ;; +esac + +install_resource() +{ + if [[ "$1" = /* ]] ; then + RESOURCE_PATH="$1" + else + RESOURCE_PATH="${PODS_ROOT}/$1" + fi + if [[ ! -e "$RESOURCE_PATH" ]] ; then + cat << EOM +error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. +EOM + exit 1 + fi + case $RESOURCE_PATH in + *.storyboard) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.xib) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.framework) + echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + ;; + *.xcdatamodel) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" + ;; + *.xcdatamodeld) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" + ;; + *.xcmappingmodel) + echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true + xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" + ;; + *.xcassets) + ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" + XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") + ;; + *) + echo "$RESOURCE_PATH" || true + echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" + ;; + esac +} + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then + mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +fi +rm -f "$RESOURCES_TO_COPY" + +if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] +then + # Find all other xcassets (this unfortunately includes those of path pods and other targets). + OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) + while read line; do + if [[ $line != "${PODS_ROOT}*" ]]; then + XCASSET_FILES+=("$line") + fi + done <<<"$OTHER_XCASSETS" + + if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + else + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" + fi +fi diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-umbrella.h b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-umbrella.h new file mode 100644 index 0000000..280b7e1 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_PunkAPI_ExampleVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_PunkAPI_ExampleVersionString[]; + diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.debug.xcconfig b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.debug.xcconfig new file mode 100644 index 0000000..b09d6b7 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.debug.xcconfig @@ -0,0 +1,11 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PunkAPI" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PunkAPI/PunkAPI.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "PunkAPI" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.modulemap b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.modulemap new file mode 100644 index 0000000..d58ae30 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.modulemap @@ -0,0 +1,6 @@ +framework module Pods_PunkAPI_Example { + umbrella header "Pods-PunkAPI_Example-umbrella.h" + + export * + module * { export * } +} diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.release.xcconfig b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.release.xcconfig new file mode 100644 index 0000000..b09d6b7 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.release.xcconfig @@ -0,0 +1,11 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PunkAPI" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PunkAPI/PunkAPI.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "PunkAPI" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Info.plist b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Info.plist new file mode 100644 index 0000000..2243fe6 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-acknowledgements.markdown b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-acknowledgements.markdown new file mode 100644 index 0000000..102af75 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-acknowledgements.markdown @@ -0,0 +1,3 @@ +# Acknowledgements +This application makes use of the following third party libraries: +Generated by CocoaPods - https://cocoapods.org diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-acknowledgements.plist b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-acknowledgements.plist new file mode 100644 index 0000000..7acbad1 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-acknowledgements.plist @@ -0,0 +1,29 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-dummy.m b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-dummy.m new file mode 100644 index 0000000..32454a2 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_PunkAPI_Tests : NSObject +@end +@implementation PodsDummy_Pods_PunkAPI_Tests +@end diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-frameworks.sh b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-frameworks.sh new file mode 100755 index 0000000..08e3eaa --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-frameworks.sh @@ -0,0 +1,146 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then + # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy + # frameworks to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" + +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} + +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + if [ -r "$source" ]; then + # Copy the dSYM into a the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .framework.dSYM "$source")" + binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then + strip_invalid_archs "$binary" + fi + + if [[ $STRIP_BINARY_RETVAL == 1 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" + fi + fi +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identitiy + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + STRIP_BINARY_RETVAL=0 + return + fi + stripped="" + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" || exit 1 + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi + STRIP_BINARY_RETVAL=1 +} + +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-resources.sh b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-resources.sh new file mode 100755 index 0000000..345301f --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-resources.sh @@ -0,0 +1,118 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then + # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy + # resources to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + +RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt +> "$RESOURCES_TO_COPY" + +XCASSET_FILES=() + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +case "${TARGETED_DEVICE_FAMILY:-}" in + 1,2) + TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" + ;; + 1) + TARGET_DEVICE_ARGS="--target-device iphone" + ;; + 2) + TARGET_DEVICE_ARGS="--target-device ipad" + ;; + 3) + TARGET_DEVICE_ARGS="--target-device tv" + ;; + 4) + TARGET_DEVICE_ARGS="--target-device watch" + ;; + *) + TARGET_DEVICE_ARGS="--target-device mac" + ;; +esac + +install_resource() +{ + if [[ "$1" = /* ]] ; then + RESOURCE_PATH="$1" + else + RESOURCE_PATH="${PODS_ROOT}/$1" + fi + if [[ ! -e "$RESOURCE_PATH" ]] ; then + cat << EOM +error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. +EOM + exit 1 + fi + case $RESOURCE_PATH in + *.storyboard) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.xib) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.framework) + echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + ;; + *.xcdatamodel) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" + ;; + *.xcdatamodeld) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" + ;; + *.xcmappingmodel) + echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true + xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" + ;; + *.xcassets) + ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" + XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") + ;; + *) + echo "$RESOURCE_PATH" || true + echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" + ;; + esac +} + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then + mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +fi +rm -f "$RESOURCES_TO_COPY" + +if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] +then + # Find all other xcassets (this unfortunately includes those of path pods and other targets). + OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) + while read line; do + if [[ $line != "${PODS_ROOT}*" ]]; then + XCASSET_FILES+=("$line") + fi + done <<<"$OTHER_XCASSETS" + + if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + else + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" + fi +fi diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-umbrella.h b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-umbrella.h new file mode 100644 index 0000000..f7d6167 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_PunkAPI_TestsVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_PunkAPI_TestsVersionString[]; + diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.debug.xcconfig b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.debug.xcconfig new file mode 100644 index 0000000..179485a --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.debug.xcconfig @@ -0,0 +1,8 @@ +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PunkAPI" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PunkAPI/PunkAPI.framework/Headers" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.modulemap b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.modulemap new file mode 100644 index 0000000..ec6f6fd --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.modulemap @@ -0,0 +1,6 @@ +framework module Pods_PunkAPI_Tests { + umbrella header "Pods-PunkAPI_Tests-umbrella.h" + + export * + module * { export * } +} diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.release.xcconfig b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.release.xcconfig new file mode 100644 index 0000000..179485a --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.release.xcconfig @@ -0,0 +1,8 @@ +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PunkAPI" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PunkAPI/PunkAPI.framework/Headers" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods diff --git a/Example/Pods/Target Support Files/PunkAPI/Info.plist b/Example/Pods/Target Support Files/PunkAPI/Info.plist new file mode 100644 index 0000000..161a9d3 --- /dev/null +++ b/Example/Pods/Target Support Files/PunkAPI/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 0.1.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Example/Pods/Target Support Files/PunkAPI/PunkAPI-dummy.m b/Example/Pods/Target Support Files/PunkAPI/PunkAPI-dummy.m new file mode 100644 index 0000000..d5552c2 --- /dev/null +++ b/Example/Pods/Target Support Files/PunkAPI/PunkAPI-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_PunkAPI : NSObject +@end +@implementation PodsDummy_PunkAPI +@end diff --git a/Example/Pods/Target Support Files/PunkAPI/PunkAPI-prefix.pch b/Example/Pods/Target Support Files/PunkAPI/PunkAPI-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Example/Pods/Target Support Files/PunkAPI/PunkAPI-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Example/Pods/Target Support Files/PunkAPI/PunkAPI-umbrella.h b/Example/Pods/Target Support Files/PunkAPI/PunkAPI-umbrella.h new file mode 100644 index 0000000..77f87f6 --- /dev/null +++ b/Example/Pods/Target Support Files/PunkAPI/PunkAPI-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double PunkAPIVersionNumber; +FOUNDATION_EXPORT const unsigned char PunkAPIVersionString[]; + diff --git a/Example/Pods/Target Support Files/PunkAPI/PunkAPI.modulemap b/Example/Pods/Target Support Files/PunkAPI/PunkAPI.modulemap new file mode 100644 index 0000000..cc71a00 --- /dev/null +++ b/Example/Pods/Target Support Files/PunkAPI/PunkAPI.modulemap @@ -0,0 +1,6 @@ +framework module PunkAPI { + umbrella header "PunkAPI-umbrella.h" + + export * + module * { export * } +} diff --git a/Example/Pods/Target Support Files/PunkAPI/PunkAPI.xcconfig b/Example/Pods/Target Support Files/PunkAPI/PunkAPI.xcconfig new file mode 100644 index 0000000..c450857 --- /dev/null +++ b/Example/Pods/Target Support Files/PunkAPI/PunkAPI.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/PunkAPI +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/Example/PunkAPI.xcodeproj/project.pbxproj b/Example/PunkAPI.xcodeproj/project.pbxproj index a2f9776..eb12836 100644 --- a/Example/PunkAPI.xcodeproj/project.pbxproj +++ b/Example/PunkAPI.xcodeproj/project.pbxproj @@ -13,7 +13,14 @@ 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; }; 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; }; 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; - 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* Tests.swift */; }; + 9761024E222B328F00C3BD6B /* BeersRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9761024D222B328F00C3BD6B /* BeersRequestTests.swift */; }; + 9767CBF7221993F900E684C4 /* BeerParsingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBF6221993F800E684C4 /* BeerParsingTests.swift */; }; + 9767CBFA2219958F00E684C4 /* BeerStubs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBF82219958800E684C4 /* BeerStubs.swift */; }; + 9767CC092222B63700E684C4 /* URLBuildTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC072222B60F00E684C4 /* URLBuildTests.swift */; }; + 9767CC0B2222BB1E00E684C4 /* MockSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC0A2222BB1E00E684C4 /* MockSession.swift */; }; + 9767CC0D2222BDD000E684C4 /* BeerRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC0C2222BDD000E684C4 /* BeerRequestTests.swift */; }; + 9767CC0F2223550E00E684C4 /* ConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC0E2223550E00E684C4 /* ConfigurationTests.swift */; }; + 9767CC27222B299300E684C4 /* BeersRequestParametersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC25222B286F00E684C4 /* BeersRequestParametersTests.swift */; }; EBB1B4D6901624C6A90359CA /* Pods_PunkAPI_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46341D8F014E1940E53D4F02 /* Pods_PunkAPI_Tests.framework */; }; /* End PBXBuildFile section */ @@ -29,8 +36,8 @@ /* Begin PBXFileReference section */ 00C6BA9ADC6CC9CF141BE6E8 /* Pods_PunkAPI_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PunkAPI_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 0CA29904BB7426E73CC31E50 /* PunkAPI.podspec */ = {isa = PBXFileReference; includeInIndex = 1; name = PunkAPI.podspec; path = ../PunkAPI.podspec; sourceTree = ""; }; - 19516DEBCED4A6F0ADCEC345 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; + 0CA29904BB7426E73CC31E50 /* PunkAPI.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = PunkAPI.podspec; path = ../PunkAPI.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 19516DEBCED4A6F0ADCEC345 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; 46341D8F014E1940E53D4F02 /* Pods_PunkAPI_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PunkAPI_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 607FACD01AFB9204008FA782 /* PunkAPI_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PunkAPI_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -41,9 +48,16 @@ 607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 607FACE51AFB9204008FA782 /* PunkAPI_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PunkAPI_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 607FACEB1AFB9204008FA782 /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = ""; }; 613B14F018C28CF1557EC3D5 /* Pods-PunkAPI_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.debug.xcconfig"; sourceTree = ""; }; - 9A440A355337DF96D159D208 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; name = README.md; path = ../README.md; sourceTree = ""; }; + 9761024D222B328F00C3BD6B /* BeersRequestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeersRequestTests.swift; sourceTree = ""; }; + 9767CBF6221993F800E684C4 /* BeerParsingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeerParsingTests.swift; sourceTree = ""; }; + 9767CBF82219958800E684C4 /* BeerStubs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeerStubs.swift; sourceTree = ""; }; + 9767CC072222B60F00E684C4 /* URLBuildTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLBuildTests.swift; sourceTree = ""; }; + 9767CC0A2222BB1E00E684C4 /* MockSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSession.swift; sourceTree = ""; }; + 9767CC0C2222BDD000E684C4 /* BeerRequestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeerRequestTests.swift; sourceTree = ""; }; + 9767CC0E2223550E00E684C4 /* ConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationTests.swift; sourceTree = ""; }; + 9767CC25222B286F00E684C4 /* BeersRequestParametersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeersRequestParametersTests.swift; sourceTree = ""; }; + 9A440A355337DF96D159D208 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; A4CA42C1E1AE14F816574722 /* Pods-PunkAPI_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.debug.xcconfig"; sourceTree = ""; }; E294694CD6DD5DA5A6B471F1 /* Pods-PunkAPI_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.release.xcconfig"; sourceTree = ""; }; F793434367F74B6D00F77A47 /* Pods-PunkAPI_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.release.xcconfig"; sourceTree = ""; }; @@ -124,7 +138,8 @@ 607FACE81AFB9204008FA782 /* Tests */ = { isa = PBXGroup; children = ( - 607FACEB1AFB9204008FA782 /* Tests.swift */, + 9767CC032222B0C900E684C4 /* Request */, + 9767CBF5221993DA00E684C4 /* BeerParsing */, 607FACE91AFB9204008FA782 /* Supporting Files */, ); path = Tests; @@ -159,6 +174,28 @@ name = Pods; sourceTree = ""; }; + 9767CBF5221993DA00E684C4 /* BeerParsing */ = { + isa = PBXGroup; + children = ( + 9767CBF6221993F800E684C4 /* BeerParsingTests.swift */, + 9767CBF82219958800E684C4 /* BeerStubs.swift */, + ); + name = BeerParsing; + sourceTree = ""; + }; + 9767CC032222B0C900E684C4 /* Request */ = { + isa = PBXGroup; + children = ( + 9767CC072222B60F00E684C4 /* URLBuildTests.swift */, + 9767CC0C2222BDD000E684C4 /* BeerRequestTests.swift */, + 9761024D222B328F00C3BD6B /* BeersRequestTests.swift */, + 9767CC25222B286F00E684C4 /* BeersRequestParametersTests.swift */, + 9767CC0A2222BB1E00E684C4 /* MockSession.swift */, + 9767CC0E2223550E00E684C4 /* ConfigurationTests.swift */, + ); + name = Request; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -167,6 +204,8 @@ buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "PunkAPI_Example" */; buildPhases = ( 44318C15D7E57EAD731D7620 /* [CP] Check Pods Manifest.lock */, + 9767CC15222AC06A00E684C4 /* SwiftLint */, + 9767CBEB2219750F00E684C4 /* ShellScript */, 607FACCC1AFB9204008FA782 /* Sources */, 607FACCD1AFB9204008FA782 /* Frameworks */, 607FACCE1AFB9204008FA782 /* Resources */, @@ -207,16 +246,17 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0830; - LastUpgradeCheck = 0830; + LastUpgradeCheck = 1010; ORGANIZATIONNAME = CocoaPods; TargetAttributes = { 607FACCF1AFB9204008FA782 = { CreatedOnToolsVersion = 6.3.1; - LastSwiftMigration = 0900; + DevelopmentTeam = 6RS7DS4QV5; + LastSwiftMigration = 1010; }; 607FACE41AFB9204008FA782 = { CreatedOnToolsVersion = 6.3.1; - LastSwiftMigration = 0900; + LastSwiftMigration = 1010; TestTargetID = 607FACCF1AFB9204008FA782; }; }; @@ -305,6 +345,41 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + 9767CBEB2219750F00E684C4 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export PATH=\"/usr/local/bin:$PATH\"\nexport LANG=en_US.UTF-8\n\nif which swiftlint >/dev/null; then\n\nif [ \"$CI\" == true ]; then\necho swiftlint lint --strict\nelse\necho swiftlint\nfi\n\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; + }; + 9767CC15222AC06A00E684C4 /* SwiftLint */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = SwiftLint; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export PATH=\"/usr/local/bin:$PATH\"\nexport LANG=en_US.UTF-8\n\nif which swiftlint >/dev/null; then\n\nif [ \"$CI\" == true ]; then\necho swiftlint lint --strict\nelse\necho swiftlint\nfi\n\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n\n"; + }; E502466B5504391CFC64510C /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -343,7 +418,14 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */, + 9767CC0D2222BDD000E684C4 /* BeerRequestTests.swift in Sources */, + 9767CC27222B299300E684C4 /* BeersRequestParametersTests.swift in Sources */, + 9767CBF7221993F900E684C4 /* BeerParsingTests.swift in Sources */, + 9767CC0F2223550E00E684C4 /* ConfigurationTests.swift in Sources */, + 9767CBFA2219958F00E684C4 /* BeerStubs.swift in Sources */, + 9767CC0B2222BB1E00E684C4 /* MockSession.swift in Sources */, + 9767CC092222B63700E684C4 /* URLBuildTests.swift in Sources */, + 9761024E222B328F00C3BD6B /* BeersRequestTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -389,12 +471,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -422,7 +506,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -442,12 +526,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -468,7 +554,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; @@ -481,13 +567,14 @@ baseConfigurationReference = A4CA42C1E1AE14F816574722 /* Pods-PunkAPI_Example.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = 6RS7DS4QV5; INFOPLIST_FILE = PunkAPI/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -496,13 +583,14 @@ baseConfigurationReference = E294694CD6DD5DA5A6B471F1 /* Pods-PunkAPI_Example.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = 6RS7DS4QV5; INFOPLIST_FILE = PunkAPI/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Release; }; @@ -522,8 +610,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PunkAPI_Example.app/PunkAPI_Example"; }; name = Debug; @@ -540,8 +627,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PunkAPI_Example.app/PunkAPI_Example"; }; name = Release; diff --git a/Example/PunkAPI.xcodeproj/xcshareddata/xcschemes/PunkAPI-Example.xcscheme b/Example/PunkAPI.xcodeproj/xcshareddata/xcschemes/PunkAPI-Example.xcscheme index 9599202..c7c42dd 100644 --- a/Example/PunkAPI.xcodeproj/xcshareddata/xcschemes/PunkAPI-Example.xcscheme +++ b/Example/PunkAPI.xcodeproj/xcshareddata/xcschemes/PunkAPI-Example.xcscheme @@ -1,6 +1,6 @@ + + + + @@ -70,7 +80,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/Example/PunkAPI.xcworkspace/contents.xcworkspacedata b/Example/PunkAPI.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..02ad899 --- /dev/null +++ b/Example/PunkAPI.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Example/PunkAPI.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Example/PunkAPI.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Example/PunkAPI.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Example/PunkAPI.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Example/PunkAPI.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..0c67376 --- /dev/null +++ b/Example/PunkAPI.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,5 @@ + + + + + diff --git a/Example/PunkAPI/AppDelegate.swift b/Example/PunkAPI/AppDelegate.swift index 423b922..b33b55a 100644 --- a/Example/PunkAPI/AppDelegate.swift +++ b/Example/PunkAPI/AppDelegate.swift @@ -14,7 +14,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } diff --git a/Example/PunkAPI/Base.lproj/Main.storyboard b/Example/PunkAPI/Base.lproj/Main.storyboard index 5cd6b8d..39512a4 100644 --- a/Example/PunkAPI/Base.lproj/Main.storyboard +++ b/Example/PunkAPI/Base.lproj/Main.storyboard @@ -1,11 +1,11 @@ - + - + @@ -20,11 +20,38 @@ + + + + + + + + + + + + + + + + diff --git a/Example/PunkAPI/ViewController.swift b/Example/PunkAPI/ViewController.swift index ac487a3..74c7deb 100644 --- a/Example/PunkAPI/ViewController.swift +++ b/Example/PunkAPI/ViewController.swift @@ -7,18 +7,43 @@ // import UIKit +import PunkAPI class ViewController: UIViewController { + @IBOutlet weak var label: UILabel! + override func viewDidLoad() { super.viewDidLoad() - // 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 loadBeerAction(_ sender: Any) { + + let request = BeersRequest(filter: [.abv(condition: .more, value: 3)]) + + PunkAPI().get(request, queue: .main) { [weak self] beersResult in + + guard let strongSelf = self else { return } + switch beersResult { + + case .success(let beers): + let string = beers.reduce(into: "", { (result, beer) in + + guard let name = beer.name else { return } + if result.isEmpty { + result = name + return + } + return result.append(contentsOf: ", \(name)") + }) + + strongSelf.label.text = string.isEmpty ? "Not Found" : string + + case .failure(let error): + strongSelf.label.text = error.localizedDescription + } + } + } } - diff --git a/Example/Tests/BeerParsingTests.swift b/Example/Tests/BeerParsingTests.swift new file mode 100644 index 0000000..780c947 --- /dev/null +++ b/Example/Tests/BeerParsingTests.swift @@ -0,0 +1,73 @@ +// +// BeerParsingTests.swift +// PunkAPI_Tests +// +// Created by Andrea Altea on 17/02/2019. +// Copyright © 2019 CocoaPods. All rights reserved. +// + +import XCTest +@testable import PunkAPI + +class BeerParsingTests: XCTestCase { + + var parser: JSONDecoder! + + override func setUp() { + + let parser = JSONDecoder() + parser.keyDecodingStrategy = .convertFromSnakeCase + self.parser = parser + } + + override func tearDown() { + self.parser = nil + } + + func testFirst() { + self.decodeBeers(BeerStub.first) + } + + func testSecond() { + self.decodeBeers(BeerStub.second) + } + + func testThird() { + self.decodeBeers(BeerStub.third) + } + + func testFourth() { + self.decodeBeers(BeerStub.fourth) + } + + func testFifth() { + self.decodeBeers(BeerStub.fifth) + } + + func testSixth() { + self.decodeBeers(BeerStub.sixth) + } + + func testMultipleFirst() { + self.decodeBeers(BeerStub.multipleFirst) + } + + func testMultipleSecond() { + self.decodeBeers(BeerStub.multipleSecond) + } + + @discardableResult + func decodeBeers(_ json: String) -> [Beer]? { + + do { + guard let data = json.data(using: .utf8) else { + XCTFail("invalid stub") + return nil + } + return try self.parser.decode([Beer].self, from: data) + } catch let error { + XCTFail(error.localizedDescription) + return nil + } + } +} diff --git a/Example/Tests/BeerRequestTests.swift b/Example/Tests/BeerRequestTests.swift new file mode 100644 index 0000000..d95038f --- /dev/null +++ b/Example/Tests/BeerRequestTests.swift @@ -0,0 +1,40 @@ +// +// BeerRequestTests.swift +// PunkAPI_Tests +// +// Created by Andrea Altea on 24/02/2019. +// Copyright © 2019 CocoaPods. All rights reserved. +// + +import XCTest +@testable import PunkAPI + +class BeerRequestTest: XCTestCase { + + func testRandomBeerRequest() { + + let request = RandomBeerRequest() + XCTAssert(request.path == "beers/random") + XCTAssert(request.parameters == nil) + } + + func testBeerRequests() { + + self.testBeerRequest(with: 1) + self.testBeerRequest(with: 2) + self.testBeerRequest(with: 3) + self.testBeerRequest(with: 4) + self.testBeerRequest(with: 5) + self.testBeerRequest(with: 6) + self.testBeerRequest(with: 10) + self.testBeerRequest(with: 1000) + self.testBeerRequest(with: 165) + } + + func testBeerRequest(with id: Int) { + + let request = BeerRequest(id: id) + XCTAssert(request.path == "beers/\(id)") + XCTAssert(request.parameters == nil) + } +} diff --git a/Example/Tests/BeerStubs.swift b/Example/Tests/BeerStubs.swift new file mode 100644 index 0000000..9155c58 --- /dev/null +++ b/Example/Tests/BeerStubs.swift @@ -0,0 +1,45 @@ +// +// BeerStubs.swift +// PunkAPI_Example +// +// Created by Andrea Altea on 17/02/2019. +// Copyright © 2019 CocoaPods. All rights reserved. +// + + +import Foundation + +struct BeerStub { + + static let first = """ +[{"id":1,"name":"Buzz","tagline":"A Real Bitter Experience.","first_brewed":"09/2007","description":"A light, crisp and bitter IPA brewed with English and American hops. A small batch brewed only once.","image_url":"https://images.punkapi.com/v2/keg.png","abv":4.5,"ibu":60,"target_fg":1010,"target_og":1044,"ebc":20,"srm":10,"ph":4.4,"attenuation_level":75,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":64,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Maris Otter Extra Pale","amount":{"value":3.3,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.2,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.4,"unit":"kilograms"}}],"hops":[{"name":"Fuggles","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"First Gold","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Fuggles","amount":{"value":37.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"First Gold","amount":{"value":37.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Cascade","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Spicy chicken tikka masala","Grilled chicken quesadilla","Caramel toffee cake"],"brewers_tips":"The earthy and floral aromas from the hops can be overpowering. Drop a little Cascade in at the end of the boil to lift the profile with a bit of citrus.","contributed_by":"Sam Mason "}] +""" + + static let second = """ +[{"id":2,"name":"Trashy Blonde","tagline":"You Know You Shouldn't","first_brewed":"04/2008","description":"A titillating, neurotic, peroxide punk of a Pale Ale. Combining attitude, style, substance, and a little bit of low self esteem for good measure; what would your mother say? The seductive lure of the sassy passion fruit hop proves too much to resist. All that is even before we get onto the fact that there are no additives, preservatives, pasteurization or strings attached. All wrapped up with the customary BrewDog bite and imaginative twist.","image_url":"https://images.punkapi.com/v2/2.png","abv":4.1,"ibu":41.5,"target_fg":1010,"target_og":1041.7,"ebc":15,"srm":15,"ph":4.4,"attenuation_level":76,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":69,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":18,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Maris Otter Extra Pale","amount":{"value":3.25,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.2,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.4,"unit":"kilograms"}}],"hops":[{"name":"Amarillo","amount":{"value":13.8,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Simcoe","amount":{"value":13.8,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":26.3,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Motueka","amount":{"value":18.8,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Fresh crab with lemon","Garlic butter dipping sauce","Goats cheese salad","Creamy lemon bar doused in powdered sugar"],"brewers_tips":"Be careful not to collect too much wort from the mash. Once the sugars are all washed out there are some very unpleasant grainy tasting compounds that can be extracted into the wort.","contributed_by":"Sam Mason "}] +""" + + static let third = """ +[{"id":3,"name":"Berliner Weisse With Yuzu - B-Sides","tagline":"Japanese Citrus Berliner Weisse.","first_brewed":"11/2015","description":"Japanese citrus fruit intensifies the sour nature of this German classic.","image_url":"https://images.punkapi.com/v2/keg.png","abv":4.2,"ibu":8,"target_fg":1007,"target_og":1040,"ebc":8,"srm":4,"ph":3.2,"attenuation_level":83,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":60,"unit":"celsius"},"duration":10},{"temp":{"value":65,"unit":"celsius"},"duration":30},{"temp":{"value":72,"unit":"celsius"},"duration":10},{"temp":{"value":78,"unit":"celsius"},"duration":5}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Soured naturally using the kettle souring technique, Yuzu fruit: 50g at middle, Yuzu juice: 200ml at FV"},"ingredients":{"malt":[{"name":"Propino Pale Malt","amount":{"value":1.63,"unit":"kilograms"}},{"name":"Wheat Malt","amount":{"value":1.63,"unit":"kilograms"}},{"name":"Propino Pale Malt for kettle 0.03kg souring","amount":{"value":0.03,"unit":"kilograms"}},{"name":"Acidulated Malt for kettle souring","amount":{"value":0.03,"unit":"kilograms"}}],"hops":[{"name":"Bramling Cross","amount":{"value":10,"unit":"grams"},"add":"middle","attribute":"bitter"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Smoked chicken wings","Miso ramen","Yuzu cheesecake"],"brewers_tips":"Clean everything twice. All you want is the clean sourness of lactobacillus.","contributed_by":"Sam Mason "}] +""" + + static let fourth = """ +[{"id":4,"name":"Pilsen Lager","tagline":"Unleash the Yeast Series.","first_brewed":"09/2013","description":"Our Unleash the Yeast series was an epic experiment into the differences in aroma and flavour provided by switching up your yeast. We brewed up a wort with a light caramel note and some toasty biscuit flavour, and hopped it with Amarillo and Centennial for a citrusy bitterness. Everything else is down to the yeast. Pilsner yeast ferments with no fruity esters or spicy phenols, although it can add a hint of butterscotch.","image_url":"https://images.punkapi.com/v2/4.png","abv":6.3,"ibu":55,"target_fg":1012,"target_og":1060,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":80,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":9,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":4.58,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.25,"unit":"kilograms"}}],"hops":[{"name":"Centennial","amount":{"value":5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Centennial","amount":{"value":10,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Amarillo","amount":{"value":10,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Centennial","amount":{"value":17.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":17.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 2007 - Pilsen Lager™"},"food_pairing":["Spicy crab cakes","Spicy cucumber and carrot Thai salad","Sweet filled dumplings"],"brewers_tips":"Play around with the fermentation temperature to get the best flavour profile from the individual yeasts.","contributed_by":"Ali Skinner "}] +""" + + static let fifth = """ +[{"id":5,"name":"Avery Brown Dredge","tagline":"Bloggers' Imperial Pilsner.","first_brewed":"02/2011","description":"An Imperial Pilsner in collaboration with beer writers. Tradition. Homage. Revolution. We wanted to showcase the awesome backbone of the Czech brewing tradition, the noble Saaz hop, and also tip our hats to the modern beers that rock our world, and the people who make them.","image_url":"https://images.punkapi.com/v2/5.png","abv":7.2,"ibu":59,"target_fg":1027,"target_og":1069,"ebc":10,"srm":5,"ph":4.4,"attenuation_level":67,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":66,"unit":"celsius"},"duration":70}],"fermentation":{"temp":{"value":10,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Lager Malt","amount":{"value":6.63,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.38,"unit":"kilograms"}}],"hops":[{"name":"Saaz","amount":{"value":60,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Saaz","amount":{"value":60,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Saaz","amount":{"value":60,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast Pilsner Lager 2007™"},"food_pairing":["Vietnamese squid salad","Chargrilled corn on the cob with paprika butter","Strawberry and rhubarb pie"],"brewers_tips":"Make sure you have a big enough yeast starter to ferment through the OG and lager successfully.","contributed_by":"Sam Mason "}] +""" + + static let sixth = """ +[{"id":58,"name":"Coffee Imperial Stout","tagline":"Beats a Cup of Joe.","first_brewed":"11/2008","description":"This beer was released as both as Danish Beerhouse Coffee Imperial Stout and BrewDog Coffee Imperial Stout. Deep, dark, roasted flavours make this a perfect Sunday brunch beer.","image_url":"https://images.punkapi.com/v2/58.png","abv":9,"ibu":65,"target_fg":1019,"target_og":1080,"ebc":97,"srm":49,"ph":4.4,"attenuation_level":76,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":64,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":"Coffee added after boil. Aged on French oak chips., Dark muscovado sugar: 312.5g for 20mins"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":7.5,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Roast Barley","amount":{"value":0.31,"unit":"kilograms"}}],"hops":[{"name":"Chinook","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"First Gold","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Coffee","amount":{"value":9.4,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Coffee","amount":{"value":9.4,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Gooey chocolate brownies","Chicken fried steak with cheesy mash","Spicy chicken empanadas"],"brewers_tips":"Grind the coffee as if making an espresso to really get the most out of it.","contributed_by":"Sam Mason "}] +""" + + static let multipleFirst = """ +[{"id":26,"name":"Skull Candy","tagline":"Pacific Hopped Amber Bitter.","first_brewed":"02/2010","description":"The first beer that we brewed on our newly commissioned 5000 litre brewhouse in Fraserburgh 2009. A beer with the malt and body of an English bitter, but the heart and soul of vibrant citrus US hops.","image_url":"https://images.punkapi.com/v2/keg.png","abv":3.5,"ibu":33,"target_fg":1012,"target_og":1038,"ebc":50,"srm":25,"ph":4.4,"attenuation_level":68.4,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":2.81,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Crystal 120","amount":{"value":0.31,"unit":"kilograms"}}],"hops":[{"name":"Cascade","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Cascade","amount":{"value":18.8,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Centennial","amount":{"value":18.8,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":31.3,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Haggis bon bons","Rosemary and lemon roast chicken","Oatmeal and cranberry cookies"],"brewers_tips":"Make sure your hops are well broken up and mixed in when added to the kettle for aroma additions. The wort is not boiling so is not agitating the hops to allow mixing. If the hops aren't steeped properly in the wort you won't get the maximum flavour impact.","contributed_by":"Sam Mason "},{"id":27,"name":"Dog B","tagline":"Cacao, Coffee Chili Anniversary Stout.","first_brewed":"05/2013","description":"Our anniversary stout was based on AB:04, one of our most sought after beers ever. This beer is slightly different each year, with subtle variations coming into play purely down to environmental and fermentation factors. What doesn't change is the rich dark chocolate, bitter coffee and chilli warmth of this monumental Stout.","image_url":"https://images.punkapi.com/v2/27.png","abv":15,"ibu":90,"target_fg":1003,"target_og":1120,"ebc":100,"srm":50,"ph":4.4,"attenuation_level":98,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":"Based on AB:04, but with added vanilla and 3.5 times the chilli."},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":8,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":1.38,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.88,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 1","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 3","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Honey","amount":{"value":0.7,"unit":"kilograms"}}],"hops":[{"name":"Chinook","amount":{"value":50,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Cascade","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Fuggles","amount":{"value":25,"unit":"grams"},"add":"15","attribute":"bitter"},{"name":"Coffee","amount":{"value":12.5,"unit":"grams"},"add":"15","attribute":"twist"},{"name":"Fuggles","amount":{"value":25,"unit":"grams"},"add":"0","attribute":" aroma"},{"name":"Coffee","amount":{"value":12.5,"unit":"grams"},"add":"0","attribute":"twist"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Blackened cajun beef","Blue cheese","Flourless chocolate cheesecake"],"brewers_tips":"Be really careful when mashing, as this amount of malts can get tough to sparge! Add honey into the boil, and naga chili and vanilla in maturation (soak them in some neutral spirit to sanitise).","contributed_by":"Sam Mason "},{"id":28,"name":"HBC 369","tagline":"Single Hop India Pale Ale – 2012.","first_brewed":"02/2012","description":"HBC 369 brings rich fruity flavours with the tiniest layer of candy coating on top. HBC 369 (the hop) can bring notes of blueberries, pear, and possibly even sweet potato. HBC 369 (the beer) was balanced, with just one hop providing a complex aroma, and a dry bitterness.","image_url":"https://images.punkapi.com/v2/28.png","abv":6.7,"ibu":67,"target_fg":1064,"target_og":1013,"ebc":19,"srm":9.5,"ph":4.4,"attenuation_level":79.7,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":68,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale - Spring Blend","amount":{"value":5.87,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.37,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.19,"unit":"kilograms"}}],"hops":[{"name":"HBC 369","amount":{"value":40,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"HBC 369","amount":{"value":100,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"HBC 369","amount":{"value":250,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Spicy jalapeño & seared steak fajitas","Grilled spicy corn with feta crumbles","Blueberry pie"],"brewers_tips":"HBC 369 is now known as Mosaic!","contributed_by":"Sam Mason "},{"id":29,"name":"10 Heads High","tagline":"Imperial Red Ale.","first_brewed":"04/2013","description":"10 Heads High is loosely based on our awesome 2011 Prototype beer Hops Kill Nazis. This is an uncompromising 7.8% Imperial Red Ale loaded high with American Hops. Think of this as an Imperial India Red Ale, or a super-charged version of 5am Saint. Either way this is a seriously good beer!","image_url":"https://images.punkapi.com/v2/29.png","abv":7.8,"ibu":70,"target_fg":1015,"target_og":1074,"ebc":90,"srm":45,"ph":4.4,"attenuation_level":79.7,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":18,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":4.75,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"Chinook","amount":{"value":20,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Chinook","amount":{"value":5,"unit":"grams"},"add":"middle","attribute":"bitter"},{"name":"Centennial","amount":{"value":5,"unit":"grams"},"add":"middle","attribute":"bitter"},{"name":"Chinook","amount":{"value":62.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Centennial","amount":{"value":62.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Chinook","amount":{"value":100,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Arrabiata pasta","Mulled cheddar","Toasted almond cake"],"brewers_tips":"Achieve the red colour by using the ratio of Caramalt, Crystal and Dark Crystal malts. The trick is to get the colour, without too much dried fruit character.","contributed_by":"Sam Mason "},{"id":30,"name":"Dana - IPA Is Dead","tagline":"Single Hop India Pale Ale.","first_brewed":"02/2013","description":"Hailing from Slovenia, Dana was originally cross bred from the German Hallertau Magnum and native Slovenian varieties. Like any good faux noble hop should, it infuses a rustic, musty spiciness into a toasty beast of a malt base.","image_url":"https://images.punkapi.com/v2/30.png","abv":6.7,"ibu":70,"target_fg":1015,"target_og":1066,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":77.3,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":5,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.31,"unit":"kilograms"}}],"hops":[{"name":"Dana","amount":{"value":2.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Dana","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Dana","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Dana","amount":{"value":125,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Spicy Asian-style noodles","Smokey chipotle beef brisket tostada","Sweet potato pie"],"brewers_tips":"Noble hops (and their offspring) have a fundamentally different profile to many other hops, down to their different oil fractions. Chill your hops to retain all of the spicy, delicate volatile hop oils!","contributed_by":"Matt Ball "},{"id":31,"name":"Nanny State","tagline":"Alcohol Free Hoppy Ale.","first_brewed":"08/2009","description":"Brewing a full flavoured craft beer at 0.5% is no easy task. Packed with loads of Centennial, Amarillo, Columbus, Cascade and Simcoe hops, dry hopped to the brink and back and sitting at 55 IBUs, Nanny State is a force to be reckoned with. With a backbone of 8 different specialty malts, Nanny State will tantalise your taste buds and leave you yearning for more.","image_url":"https://images.punkapi.com/v2/31.png","abv":0.5,"ibu":55,"target_fg":1005,"target_og":1007,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":28.6,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":30}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Munich","amount":{"value":0.13,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.19,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.03,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.13,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Rye","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"Amarillo","amount":{"value":6.3,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Simcoe","amount":{"value":5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Centennial","amount":{"value":6.3,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":6.3,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Simcoe","amount":{"value":2.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Centennial","amount":{"value":6.3,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Amarillo","amount":{"value":5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Cascade","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Ahtanum","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Centennial","amount":{"value":50,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Cascade","amount":{"value":50,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Ahtanum","amount":{"value":25,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Simcoe","amount":{"value":25,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Columbus","amount":{"value":37.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Earthy mushroom pasta"],"brewers_tips":"Get hops in every stage of the brewing process - mash, run off boil and flame off. There's not too much malt body, so the more hops the better.","contributed_by":"Sam Mason "},{"id":32,"name":"AB:05","tagline":"Belgian Imperial Stout.","first_brewed":"12/2010","description":"Belgian Imperial Stout aged on toasted coconut and cacao. The Belgian yeast strain introduces a whole new dimension to the Imperial Stout style resulting in a beer that resembles a marshmallow toasted on a smouldering barbeque then smothered in dark chocolate. Massively seductive and encapsulating this blacker than midnight beer pours with coffee brown head so thick you could almost stand on it, and with an epic lacing on your glass.","image_url":"https://images.punkapi.com/v2/32.png","abv":12.5,"ibu":40,"target_fg":1030,"target_og":1126,"ebc":180,"srm":90,"ph":4.4,"attenuation_level":76,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":"Toasted coconut flakes: 75g, Cacao Nibs: 25g"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":10,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 1","amount":{"value":0.94,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 3","amount":{"value":0.94,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":1.88,"unit":"kilograms"}},{"name":"Pale Crystal","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.63,"unit":"kilograms"}}],"hops":[{"name":"First Gold","amount":{"value":50,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"First Gold","amount":{"value":50,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 3522 - Belgian Ardennes™"},"food_pairing":["Venison with cacao nibs","Apple upside-down cake","Toffee marshmallow pie"],"brewers_tips":"Add the coconut and cacao nibs after primary fermentation and let infuse for at least 6 months at a low temperature.","contributed_by":"Sam Mason "},{"id":33,"name":"Sorachi Ace","tagline":"Single Hop IPA Series - 2011.","first_brewed":"01/2011","description":"A hop that tastes of bubble gum? Seriously? No, we did not believe it either. But it does! This is one unique, son of a bitch of a hop. Lemony, deep, musty with a smoothness that belies its power. This hop is lemony like a lemon who was angry earlier but is now tired because of all the rage. This hop of Japanese origin is best enjoyed trying to make sushi from your gold fish, or trying to persuade your girlfriend (or boyfriend maybe) to dress up as a Geisha for Valentine’s Day.","image_url":"https://images.punkapi.com/v2/33.png","abv":7.5,"ibu":75,"target_fg":1013,"target_og":1068,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":82.1,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Xpale","amount":{"value":6.38,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.13,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.25,"unit":"kilograms"}}],"hops":[{"name":"Sorachi Ace","amount":{"value":14.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Sorachi Ace","amount":{"value":20,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Sashimi","Grilled salmon with a herb and citrus infused butter","Basil, lemon and pine nut angel hair pasta with grilled chicken"],"brewers_tips":"Sorachi Ace is hop best handled with care. Too much and your beer may taste like dill pickle and lemons.","contributed_by":"Sam Mason "},{"id":34,"name":"Bourbon Baby","tagline":"Barrel-Aged Scotch Ale.","first_brewed":"01/2014","description":"Santa Paws Scotch ale aged in bourbon barrels - light, dry and toasty, with vanilla, hints of chocolate and ginger biscuit, and a faint spicy hoppiness.","image_url":"https://images.punkapi.com/v2/34.png","abv":5.8,"ibu":35,"target_fg":1005,"target_og":1049,"ebc":44,"srm":22,"ph":4.4,"attenuation_level":90,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":1.75,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.44,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.56,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":0.56,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 3","amount":{"value":0.13,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Weyermann Beech Smoked","amount":{"value":0.06,"unit":"kilograms"}}],"hops":[{"name":"First Gold","amount":{"value":18.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Willamette","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Hallertauer Mittelfrüh","amount":{"value":6,"unit":"grams"},"add":"middle","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Blackened cajun beef","Pulled pork","Millionaire's shortbread"],"brewers_tips":"Use bourbon-soaked oak chips in secondary to achieve barrel character.","contributed_by":"Ali Skinner "},{"id":35,"name":"Berliner Weisse With Raspberries And Rhubarb - B-Sides","tagline":"Fruity Berliner Weisse.","first_brewed":"11/2015","description":"Tart, dry and acidic with a punch of summer berry as rhubarb crumble.","image_url":"https://images.punkapi.com/v2/keg.png","abv":3.6,"ibu":8,"target_fg":1007,"target_og":1040,"ebc":null,"srm":null,"ph":3.2,"attenuation_level":83,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":60,"unit":"celsius"},"duration":10},{"temp":{"value":65,"unit":"celsius"},"duration":30},{"temp":{"value":72,"unit":"celsius"},"duration":10},{"temp":{"value":78,"unit":"celsius"},"duration":5}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Raspberries in the boil, rhubarb at maturation. Soured naturally using the kettle souring technique, Raspberries at middle"},"ingredients":{"malt":[{"name":"Propino Pale Malt","amount":{"value":1.63,"unit":"kilograms"}},{"name":"Wheat Malt","amount":{"value":1.63,"unit":"kilograms"}},{"name":"Propino Pale Malt for kettle souring","amount":{"value":0.03,"unit":"kilograms"}},{"name":"Acidulated Malt for kettle souring","amount":{"value":0.03,"unit":"kilograms"}}],"hops":[{"name":"Bramling Cross","amount":{"value":10,"unit":"grams"},"add":"middle","attribute":"bitter"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Grilled salmon","Mac and cheese fries","Cheesecake with raspberry coulis"],"brewers_tips":"Fruits added at the end of the boil for 10 mins and additional added in maturation. Boil for no more than 15 mins.","contributed_by":"Sam Mason "},{"id":36,"name":"Shipwrecker Circus (w/ Oskar Blues)","tagline":"American Barley Wine - Oskar Blues Collab.","first_brewed":"09/2013","description":"In collaboration with the awesome Oskar Blues from Colorado, we created this big, twisted 10.5% American style barley wine. Big boozy aromas and a sweet viscosity, packed in with some heavy-hitting C-hops, for an intense bitterness to balance this full-bodied malt monster.","image_url":"https://images.punkapi.com/v2/36.png","abv":10.5,"ibu":85,"target_fg":1022,"target_og":1102,"ebc":64,"srm":32,"ph":4.4,"attenuation_level":102,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":9.35,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":1,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.06,"unit":"kilograms"}}],"hops":[{"name":"Chinook","amount":{"value":50,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Cascade","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Citra","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Chinook","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Chinook","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Citra","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Cascade","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Cascade","amount":{"value":125,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Chinook","amount":{"value":125,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Citra","amount":{"value":125,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Stilton","Pan seared steak","Dark Chocolate Fondant"],"brewers_tips":"Age this beer in the cellar for a few months to allow the warm alcohol flavours to reduce.","contributed_by":"Ali Skinner "},{"id":37,"name":"Zephyr","tagline":"There’s A Storm Brewing.","first_brewed":"10/2008","description":"A 9.2% Double IPA aged for 21 months in a 1965 Invergordon cask with 30 kg of fresh highland strawberries. This beer is a riot of whisky, caramel and strawberry, all tempered by a toe curling bitterness enducing rapture in all who taste it. Who needs champagne?","image_url":"https://images.punkapi.com/v2/37.png","abv":12.5,"ibu":125,"target_fg":1016,"target_og":1087,"ebc":40,"srm":20,"ph":4.4,"attenuation_level":81.2,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Oak chips: 15g, Fresh strawberries: 3kg"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":6.3,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.38,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.29,"unit":"kilograms"}}],"hops":[{"name":"Columbus Extract","amount":{"value":31,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Columbus","amount":{"value":19.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Columbus","amount":{"value":19.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Centennial","amount":{"value":19.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Simcoe","amount":{"value":19.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Columbus","amount":{"value":19.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Centennial","amount":{"value":19.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Centennial","amount":{"value":115.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Columbus","amount":{"value":96,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Simcoe","amount":{"value":96,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Amarillo","amount":{"value":77,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Poached eggs and smoked salmon","Salt and pepper squid","Key Lime Pie"],"brewers_tips":"Rack into a secondary fermenter and add your strawberries. Use a blow-off rather than an airlock as the fermentation can get pretty wild as the yeast starts using the sugar from the strawberries.","contributed_by":"Sam Mason "},{"id":38,"name":"Belgian Trappist","tagline":"Unleash the Yeast Series.","first_brewed":"09/2013","description":"Our Unleash the Yeast series was an epic experiment into the differences in aroma and flavour provided by switching up your yeast. We brewed up a wort with a light caramel note and some toasty biscuit flavour, and hopped it with Amarillo and Centennial for a citrusy bitterness. Everything else is down to the yeast. Abbey style yeasts add distinctive spicy and fruity notes, and dry out the finished beer.","image_url":"https://images.punkapi.com/v2/38.png","abv":6.3,"ibu":55,"target_fg":1012,"target_og":1060,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":80,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":25,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":4.58,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.25,"unit":"kilograms"}}],"hops":[{"name":"Centennial","amount":{"value":5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Centennial","amount":{"value":10,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Amarillo","amount":{"value":10,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Centennial","amount":{"value":17.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":17.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"WLP500 Monastery Ale"},"food_pairing":["Roast beef with spicy jus","Ginger bread cookies","Orange tart"],"brewers_tips":"Play around with the fermentation temperature to get the best flavour profile from the individual yeasts.","contributed_by":"Ali Skinner "},{"id":39,"name":"Kohatu - IPA Is Dead","tagline":"Single Hop India Pale Ale.","first_brewed":"02/2014","description":"As you’d expect from a New Zealand hop variety, Kohatu contributes bags of tropical fruit, but with loads of lime notes, & pineapple hits. Seriously fruity, with sweet, juicy melon and stonefruit notes.","image_url":"https://images.punkapi.com/v2/39.png","abv":7.2,"ibu":70,"target_fg":1012,"target_og":1067,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":82.1,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":5.65,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.06,"unit":"kilograms"}}],"hops":[{"name":"Kohatu","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Kohatu","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Kohatu","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Kohatu","amount":{"value":250,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Tuna sushi roll with spicy mayonnaise sauce","Thai green curry","Pineapple upside down cake"],"brewers_tips":"New Zealand hops are in short supply - club together with other brewers to try and get hold of some, or ask your local brewery if you can buy small amounts from them.","contributed_by":"Sam Mason "},{"id":40,"name":"Hello My Name is Vladimir","tagline":"Limonnik Infused Imperial IPA (Not for Gays).","first_brewed":"01/2014","description":"A Limonnik-infused, triple dry- hopped double IPA. Dry berry tartness and intense citrus hop character meld with a dry bready malt base, boosted by a hint of alcohol warmth. This beer was brewed as a protest against the anti-LGBT legislation in Russia surrounding the Sochi Olympics.","image_url":"https://images.punkapi.com/v2/40.png","abv":8.2,"ibu":70,"target_fg":1013,"target_og":1076,"ebc":16,"srm":8,"ph":4.4,"attenuation_level":83,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Fruit in the boil, berries in the fermenter. Limonnik Berries: 2.5, Twist."},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":5.77,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.63,"unit":"kilograms"}}],"hops":[{"name":"Citra","amount":{"value":4,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Citra","amount":{"value":37.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Citra","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Blackberry Concentrate","amount":{"value":62.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Sour Cherry Puree","amount":{"value":250,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Citra","amount":{"value":112.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Mosaic","amount":{"value":200,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Centennial","amount":{"value":187.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Russian mini pork pies","Beef Stroganoff","Chocolate and fruit cake"],"brewers_tips":"If you can't get hold of Limonnik berries, rose hips make an accessible alternative!","contributed_by":"Ali Skinner "},{"id":41,"name":"AB:17","tagline":"Three Coffee Rye Imperial Porter.","first_brewed":"10/2014","description":"A triple whammy of coffee from HasBean gives our 17th Abstrakt concept beer an intense and roasty, dark mocha character. We brewed with espresso in the mash, cafetiere in the boil, and whole roast beans in the whirlpool and the fermenter.","image_url":"https://images.punkapi.com/v2/41.png","abv":10.7,"ibu":100,"target_fg":1025,"target_og":1105,"ebc":300,"srm":150,"ph":4.3,"attenuation_level":76.2,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Coffee: 25g at end, Coffee: 25g at end, Dark Muscavado Sugar: 250g at end"},"ingredients":{"malt":[{"name":"Pale Ale","amount":{"value":9,"unit":"kilograms"}},{"name":"Rye","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.38,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.88,"unit":"kilograms"}},{"name":"Roasted Barley","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 1","amount":{"value":0.25,"unit":"kilograms"}}],"hops":[{"name":"CO2 Extract","amount":{"value":20,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Willamette","amount":{"value":50,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["12hr smoked brisket","Chocolate pistachio cakes","Dulche de leche"],"brewers_tips":"Use freshly ground coffee for the best aromatic hit.","contributed_by":"Sam Mason "},{"id":42,"name":"Hardcore IPA","tagline":"Explicit Imperial Ale. Citrusy. Resinous. Intense.","first_brewed":"12/2009","description":"Pounding a triple payload of the biggest North American hops humanity has devised, braced by a backbone of caramel malt, this beer is deep, astringent and resinous, pushing to the extremes of lupulin thresholds. There’s nothing inscrutable going on; no mystery in the backstory. It doesn’t seek to be understood. A beer incapable of empathy; only hop overload.","image_url":"https://images.punkapi.com/v2/42.png","abv":9.2,"ibu":125,"target_fg":1016,"target_og":1085,"ebc":40,"srm":20,"ph":4.4,"attenuation_level":81.2,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":7.4,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.38,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.29,"unit":"kilograms"}}],"hops":[{"name":"Columbus Extract","amount":{"value":30.8,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Columbus","amount":{"value":19.2,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Columbus","amount":{"value":19.2,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Centennial","amount":{"value":19.2,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Simcoe","amount":{"value":19.2,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Columbus","amount":{"value":19.2,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Centennial","amount":{"value":19.2,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":19.2,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Centennial","amount":{"value":115.4,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Columbus","amount":{"value":96.2,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Simcoe","amount":{"value":96.2,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Amarillo","amount":{"value":76.9,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Spicy wings with blue cheese dip","Pan seared scallops with a chilli sauce","Creamy chocolate and caramel cheesecake"],"brewers_tips":"There are so much hops in this beer it may break your gear! Watch out for the end of casting (or knockout for our American brethern), you don’t want to pull too much trub into the fermenter.","contributed_by":"Sam Mason "},{"id":43,"name":"American Wheat","tagline":"Hoppy American Wheat.","first_brewed":"07/2014","description":"A luscious blend of peach, blood orange and banana to make a suitably refreshing beverage that happily straddles the Atlantic.","image_url":"https://images.punkapi.com/v2/keg.png","abv":4.5,"ibu":17,"target_fg":1013,"target_og":1047,"ebc":10,"srm":5,"ph":5.3,"attenuation_level":72,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":64,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":2.13,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":2.5,"unit":"kilograms"}},{"name":"Pale Crystal","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"Ahtanum","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Ahtanum","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1010 American Wheat™"},"food_pairing":["Strawberry and citrus salad","Fish corn tacos with pomegranate salsa","Summer berry fruit parfait"],"brewers_tips":"Using a starter to get your yeast as vibrant and healthy as possible will make all the difference here.","contributed_by":"Sam Mason "},{"id":44,"name":"Dog Wired (w/8 Wired)","tagline":"New Zealand Imperial Pilsner.","first_brewed":"06/2013","description":"Brewed in collaboration with Soren from New Zealand’s stellar 8-Wired brewery, this is an Imperial Pilsner featuring two of our favourite New Zealand hops: Nelson Sauvin and Motueka. Sitting at a dangerously drinkable 7.1% ABV there’s a touch of Munich malt which gives this beer that little extra caramel biscuit bite to compliment the lip smackingly tropical hops. Expect an all out NZ hoppy riot.","image_url":"https://images.punkapi.com/v2/44.png","abv":7.1,"ibu":65,"target_fg":1010,"target_og":1065,"ebc":13,"srm":6.5,"ph":4.4,"attenuation_level":85,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":64,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":9,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":4.7,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.38,"unit":"kilograms"}},{"name":"Acidulated Malt","amount":{"value":0.63,"unit":"kilograms"}}],"hops":[{"name":"Nelson Sauvin","amount":{"value":20,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Motueka","amount":{"value":20,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Nelson Sauvin","amount":{"value":10,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Motueka","amount":{"value":10,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Nelson Sauvin","amount":{"value":20,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Motueka","amount":{"value":20,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Motueka","amount":{"value":100,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Nelson Sauvin","amount":{"value":87.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 2007 - Pilsen Lager™"},"food_pairing":["Spiced and blackened cajun chicken","Pork belly vindaloo","Rhubarb pie"],"brewers_tips":"Hold the mash for longer at 63-64°C to get more fermentability from the wort.","contributed_by":"Sam Mason "},{"id":45,"name":"The Physics","tagline":"Laid Back Amber Beer.","first_brewed":"04/2007","description":"A hoppy Amber Ale that won World's Best Amber Beer in the World Beer Awards 2007. Malt and hops are in perfect harmony in this incredibly balanced beer. Biscuity, bitter and packing a surprisingly hoppy punch, this beer ultimately morphed into 5AM Saint.","image_url":"https://images.punkapi.com/v2/45.png","abv":5,"ibu":47,"target_fg":1010,"target_og":1048.5,"ebc":65,"srm":32.5,"ph":4.4,"attenuation_level":79.4,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":4.06,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Crystal 120","amount":{"value":0.23,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.94,"unit":"kilograms"}}],"hops":[{"name":"Amarillo","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Bramling Cross","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":50,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Barbecue pulled pork on sourdough bread","Roast turkey with a honey and herb marinade and roasted vegetables","Banana walnut loaf with chocolate chips"],"brewers_tips":"Keep the fermentation temperature as close to 19°C as possible. This will ensure the yeast creates a more neutral flavour profile, allowing the hops to really shine through.","contributed_by":"Sam Mason "},{"id":46,"name":"Anarchist Alchemist","tagline":"Triple Hopped Triple Ipa.","first_brewed":"03/2012","description":"About as far as you can push an IPA; Anarchist Alchemist packs in three times the malt and three of our favourite hops. Nelson Sauvin, Amarillo and Centennial bring a range of flavours, touching on tropical fruit, white grape, tangerine, grapefruit, pine, spiced orange... the list goes on!","image_url":"https://images.punkapi.com/v2/46.png","abv":16.5,"ibu":20.5,"target_fg":1000,"target_og":1112,"ebc":20,"srm":10,"ph":4.4,"attenuation_level":100,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":20,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":12.5,"unit":"kilograms"}}],"hops":[{"name":"Nelson Sauvin","amount":{"value":6.25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Centennial","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Nelson Sauvin","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Centennial","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Nelson Sauvin","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Amarillo","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Centennial","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Blue cheese & onion tart","Goan goat curry","Sugar-poached kumquat rice pudding"],"brewers_tips":"The biggest challenge with this beer is getting it to ferment out entirely. Hold mash temp at 65°C for 90 mins to ensure maximum fermentability. Use super high gravity yeast or champagne yeast to achieve the last few gravity points.","contributed_by":"Sam Mason "},{"id":47,"name":"AB:15","tagline":"Salted Caramel Popcorn Strong Ale.","first_brewed":"03/2013","description":"A salted caramel popcorn Imperial Ale. Bourbon and Rum barrel aged, this 12.8% ale has complex and twisting flavours. Bitter caramel, wood, smoke, spice, treacle and vanilla are all present and intertwine against a smooth and lightly chewy mouthfeel. The salted caramel popcorn lends subtle hints of a smoky brininess.","image_url":"https://images.punkapi.com/v2/47.png","abv":12.8,"ibu":50,"target_fg":1020,"target_og":1096,"ebc":111,"srm":55.5,"ph":4.4,"attenuation_level":79.17,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":68,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Adding popped popcorn into the mash, then barrel ageing in fresh bourbon barrels"},"ingredients":{"malt":[{"name":"Maris Otter Extra Pale","amount":{"value":6.5625,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.3125,"unit":"kilograms"}},{"name":"Munich","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.3125,"unit":"kilograms"}},{"name":"Popcorn","amount":{"value":0.00625,"unit":"kilograms"}}],"hops":[{"name":"Sorachi Ace","amount":{"value":62.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Willamette","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"aroma"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Crispy bacon on flat bread","Glazed ham with crackling coating","Popcorn caramel and chocolate cake"],"brewers_tips":"By soaking some oak chips in bourbon, then steeping in the beer you not only get an authentic Bourbon taste - the beer will also gain ABV! Add salt to taste, too much will totally ruin the balance of the beer.","contributed_by":"Sam Mason "},{"id":48,"name":"Goldings - IPA Is Dead","tagline":"Single Hop India Pale Ale.","first_brewed":"02/2013","description":"This is East Kent Goldings re- invented and re-imagined and shows just what can be done with English hops if you use enough of them. In this amped up Goldings reincarnation expect to be slammed with floral lavender, a fruity riot of blackberries and spiced pears, bubblegum, plums and the illusion of thyme.","image_url":"https://images.punkapi.com/v2/48.png","abv":6.7,"ibu":70,"target_fg":1015,"target_og":1066,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":77.3,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":5,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.31,"unit":"kilograms"}}],"hops":[{"name":"Goldings","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Goldings","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Goldings","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Goldings","amount":{"value":125,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Rosemary and thyme marinated venison","Fish and chips","Lavender chocolate chip cookies"],"brewers_tips":"Take a read through each year’s hop harvest that is available. Some years are better than others.","contributed_by":"Matt Ball "},{"id":49,"name":"AB:14","tagline":"Oak-Aged Imperial Weizenbock.","first_brewed":"02/2013","description":"Think banoffee pie; loads of creamy sweet banana, and sticky warm toffee. This beer is super complex, and one for the sweet-toothed!","image_url":"https://images.punkapi.com/v2/49.png","abv":10,"ibu":30,"target_fg":1016,"target_og":1094,"ebc":20,"srm":10,"ph":4.4,"attenuation_level":83,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":120}],"fermentation":{"temp":{"value":23,"unit":"celsius"}},"twist":"Oak chips: 25g at end"},"ingredients":{"malt":[{"name":"Wheat","amount":{"value":5,"unit":"kilograms"}},{"name":"Extra Pale","amount":{"value":2,"unit":"kilograms"}},{"name":"Munich","amount":{"value":2,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":1.13,"unit":"kilograms"}}],"hops":[{"name":"Bramling Cross","amount":{"value":30,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Simcoe","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Saaz","amount":{"value":15,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Simcoe","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Saaz","amount":{"value":15,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 3638 - Bavarian Wheat™"},"food_pairing":["Sweet pork Chinese dumplings","Caramelised onion venison burger","Banoffee pie"],"brewers_tips":"Boil for even longer to get more caramelised flavours in the beer.","contributed_by":"Sam Mason "},{"id":50,"name":"Lost Dog (w/Lost Abbey)","tagline":"Rum-Aged Imperial Porter - Lost Abbey Collab.","first_brewed":"11/2011","description":"Our first beer aged in rum casks, Lost Dog saw us brew a collaboration imperial porter with our friends at Lost Abbey. The base beer was packed with toffee, chocolate and roasty notes, balanced with a subtle spicy hop character. The rum casks add a warming, spiced vanilla edge.","image_url":"https://images.punkapi.com/v2/50.png","abv":10,"ibu":35,"target_fg":1012,"target_og":1080,"ebc":80,"srm":40,"ph":4.4,"attenuation_level":85,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":"Aged in rum casks for 12 months"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":4.69,"unit":"kilograms"}},{"name":"Pale Chocolate","amount":{"value":0.23,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.7,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.35,"unit":"kilograms"}},{"name":"Oats","amount":{"value":0.47,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.35,"unit":"kilograms"}}],"hops":[{"name":"First Gold","amount":{"value":35,"unit":"grams"},"add":"start","attribute":"bitter"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Beef satay skewers","Venison & cranberry pie","Blackberry mocha gateaux"],"brewers_tips":"Ageing in barrels brings the ABV up. Recreate rum cask ageing by soaking oak chips in rum then adding to the maturing beer.","contributed_by":"Sam Mason "}] +""" + + static let multipleSecond = """ +[{"id":51,"name":"TM10","tagline":"Liquid Art.","first_brewed":"04/2010","description":"Brewed for the Tate Modern’s 10th Anniversary. A saison style beer brewed with ginger and orange peel. Very limited batch of 4000 cork and caged bottles with a silk screened label designed by Johanna Basford. Only available at the Tate Modern.","image_url":"https://images.punkapi.com/v2/51.png","abv":5.5,"ibu":20,"target_fg":1005,"target_og":1048,"ebc":14,"srm":7,"ph":4.2,"attenuation_level":89.6,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":63,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":22,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Pale Ale Malt","amount":{"value":5.3,"unit":"kilograms"}}],"hops":[{"name":"Bobek","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Bobek","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Bobek","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Ginger","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Orange Peel","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 3711 - French Saison™"},"food_pairing":["Tom yum soup","Andhra chicken pickle curry","Butterscotch tart"],"brewers_tips":"For a fresh and fiery hit, put some ginger into the cold conditioning phase as well.","contributed_by":"Sam Mason "},{"id":52,"name":"Paradox Islay","tagline":"Ubiquitous Imperial Stout.","first_brewed":"04/2007","description":"In 2006 James and Martin hijacked a beer dinner run by Michael Jackson, the acclaimed beer and whisky writer, and convinced him to taste one of their home brews. This was a defining moment in BrewDog prehistory, and that beer was the first incarnation of the ubiquitous Paradox. Aged in a variety of casks over the years, Paradox is dark, decadent and encapsulating. Can be enjoyed fresh; phenomenal when aged.","image_url":"https://images.punkapi.com/v2/52.png","abv":10,"ibu":55,"target_fg":1014,"target_og":1090,"ebc":300,"srm":152,"ph":4.4,"attenuation_level":84.4,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Try ageing on oak chips, infusing with rum raisins, or vanilla pods"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":4.5,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.55,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.33,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":1.35,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.55,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 1","amount":{"value":0.18,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 3","amount":{"value":0.33,"unit":"kilograms"}}],"hops":[{"name":"Columbus","amount":{"value":75,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Columbus","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Saaz","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"First Gold","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Ancho chilli beef taco","Chocolate gateaux","Rum poached pears with dark chocolate sauce"],"brewers_tips":"The beauty of this beer is in how brilliantly it lends itself to infusing or ageing. Experiment with different additions when the beer is ageing, taste it regularly to gauge its progress, and make sure you package it at its peak.","contributed_by":"Sam Mason "},{"id":53,"name":"Baby Dogma","tagline":"Session Scotch Ale.","first_brewed":"09/2013","description":"A baby Scotch ale with dry and toasty malt flavours and hints of smoke. Toffee, biscuit and fudge abound with a spicy bitterness from the pan-global hops.","image_url":"https://images.punkapi.com/v2/keg.png","abv":4.5,"ibu":35,"target_fg":1013,"target_og":1048,"ebc":40,"srm":20,"ph":4.4,"attenuation_level":72.9,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":66,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":1.75,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.48,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.56,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":0.56,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 3","amount":{"value":0.13,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Weyermann Beech Smoked","amount":{"value":0.06,"unit":"kilograms"}}],"hops":[{"name":"First Gold","amount":{"value":18.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Willamette","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Hallertauer Mittelfrüh","amount":{"value":6,"unit":"grams"},"add":"start","attribute":"bitter"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["French onion soup","Braised pheasant","Caramel sauce and hot fudge"],"brewers_tips":"The addition of Weyermann Beech Smoked malt creates a beer with a delicate smoke character.","contributed_by":"Ali Skinner "},{"id":54,"name":"Albino Squid Assasin","tagline":"Red Rye IPA","first_brewed":"11/2015","description":"This tentacled terminator packs a punch - ten punches to be precise. Each hop addition adds to the intense layers of depth in this red rye IPA. Toasty caramel & cinder toffee from crystal malts, cacao richness from intensely roasted malt and the spiciness of rye. Zesty pithiness from Citra and the robust resin of Chinook. This small batch exclusive brew is up-front intensity matched with twisted complexity. The can features awesome custom art from Joe Wilson.","image_url":"https://images.punkapi.com/v2/54.png","abv":7.4,"ibu":65,"target_fg":1012,"target_og":1069,"ebc":60,"srm":30,"ph":4.2,"attenuation_level":82.6,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":18,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Pale Ale","amount":{"value":5,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.38,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.13,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 1","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Rye","amount":{"value":0.5,"unit":"kilograms"}}],"hops":[{"name":"Magnum","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Chinook","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Citra","amount":{"value":6.25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Chinook","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Citra","amount":{"value":18.75,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Chinook","amount":{"value":100,"unit":"grams"},"add":"fv","attribute":"aroma"},{"name":"Citra","amount":{"value":75,"unit":"grams"},"add":"fv","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Rocket and mozzarella salad with a cracked pepper dressing","Fried halibut with sweet potato fritters","Grapefruit and blood orange tart"],"brewers_tips":"20% specialty malts in this grist can create problems in the run off. Be careful not to pull the bed down onto the plates.","contributed_by":"Matt Ball "},{"id":55,"name":"Amarillo - IPA Is Dead","tagline":"Single Hop India Pale Ale.","first_brewed":"01/2013","description":"Citrus fruit. Lots of citrus fruit. Think blood orange, orange zest and grapefruit, tangerine and lemon; the fruit is balanced by floral notes in the most classic of new wave IPA hops. Amarillo adds a zesty, pithy character that sits beautifully alongside hints of toffee and honeycomb.","image_url":"https://images.punkapi.com/v2/55.png","abv":7.2,"ibu":70,"target_fg":1012,"target_og":1067,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":82.1,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":4.88,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.06,"unit":"kilograms"}}],"hops":[{"name":"Amarillo","amount":{"value":20,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Amarillo","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":250,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Bratwurst sausage with spicy mustard","Fried American bacon with chilli flakes added to the top","Dark chocolate chip cookies"],"brewers_tips":"Use the freshest hops for the most impact. It seems obvious but in a single hop beer, you want the hops to be at their best.","contributed_by":"Sam Mason "},{"id":56,"name":"Black Eyed King Imp","tagline":"Barrel-Aged Prototype Cocoa Psycho.","first_brewed":"11/2012","description":"An early Cocoa Psycho recipe that we loved, but didn't fit what we were looking for. We locked this chocolate coffee stout away in barrels for two years, imparting toasted marshmallow, spicy vanilla, molasses and boozy warmth.","image_url":"https://images.punkapi.com/v2/56.png","abv":9.5,"ibu":85,"target_fg":1022,"target_og":1095,"ebc":250,"srm":125,"ph":4.4,"attenuation_level":76.8,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":50}],"fermentation":{"temp":{"value":18,"unit":"celsius"}},"twist":"Coffee Beans: 12.5g at end, Lactose: 125g"},"ingredients":{"malt":[{"name":"Extra Pale - Spring Blend","amount":{"value":6.25,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Crystal","amount":{"value":1.56,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Brown","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Roasted Barley","amount":{"value":0.31,"unit":"kilograms"}}],"hops":[{"name":"Magnum","amount":{"value":62.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Willamette","amount":{"value":31.25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"First Gold","amount":{"value":31.25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Beef chilli made with cocoa powder","Dark chocolate covered bacon","Rich espresso tiramisu"],"brewers_tips":"There is a huge amount of roasted malts in this grist. Be careful not to pulverise the malt into powder during the milling process.","contributed_by":"Sam Mason "},{"id":57,"name":"Prototype 27","tagline":"Vibrant Smoky Pink IPA.","first_brewed":"04/2010","description":"Hardcore IPA with raspberries aged in Caol Ila casks. Full-bodied and compelling, the robust malt base provides an initial layer of honey, cinnamon and biscuity malt sweetness. Soon the Scottish berries are in on the act, a dominating tug of war between sweet and tart with an overbearing zest. As the beer slips back across your tongue the hops demand and definitely get your attention. At 100 IBUs the bitterness smashes into the back of your throat as the resinous, spiced orange peel flavours add depth to the berry fruitiness.","image_url":"https://images.punkapi.com/v2/57.png","abv":9.2,"ibu":149,"target_fg":1014,"target_og":1083,"ebc":19.5,"srm":9.8,"ph":4.4,"attenuation_level":83,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Pale Ale Malt","amount":{"value":8.13,"unit":"kilograms"}},{"name":"Crystal Malt 150","amount":{"value":0.28,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.56,"unit":"kilograms"}}],"hops":[{"name":"Columbus","amount":{"value":50,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Centennial","amount":{"value":50,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Columbus","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Centennial","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Columbus","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Centennial","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Strong blue cheese","Cranachan","Chicago style hot links"],"brewers_tips":"Soak some oak chips in Caol Ila whisky to get barrel character. Freeze raspberries before adding them to secondary.","contributed_by":"Sam Mason "},{"id":58,"name":"Coffee Imperial Stout","tagline":"Beats a Cup of Joe.","first_brewed":"11/2008","description":"This beer was released as both as Danish Beerhouse Coffee Imperial Stout and BrewDog Coffee Imperial Stout. Deep, dark, roasted flavours make this a perfect Sunday brunch beer.","image_url":"https://images.punkapi.com/v2/58.png","abv":9,"ibu":65,"target_fg":1019,"target_og":1080,"ebc":97,"srm":49,"ph":4.4,"attenuation_level":76,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":64,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":"Coffee added after boil. Aged on French oak chips., Dark muscovado sugar: 312.5g for 20mins"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":7.5,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Roast Barley","amount":{"value":0.31,"unit":"kilograms"}}],"hops":[{"name":"Chinook","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"First Gold","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Coffee","amount":{"value":9.4,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Coffee","amount":{"value":9.4,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Gooey chocolate brownies","Chicken fried steak with cheesy mash","Spicy chicken empanadas"],"brewers_tips":"Grind the coffee as if making an espresso to really get the most out of it.","contributed_by":"Sam Mason "},{"id":59,"name":"Mandarina Bavaria - IPA Is Dead","tagline":"Single Hop India Pale Ale.","first_brewed":"03/2015","description":"From the central European plains of Germany, comes something very different. A blast of tangerine and orange, Mandarina Bavaria brings a highly distinctive backbone of flavour. This is down to its parent – Cascade – and a frankly enormous 70% myrcene oil content. If equate Germany solely with earthy, spicy Noble hops, Mandarina Bavaria will make you think again.","image_url":"https://images.punkapi.com/v2/59.png","abv":7.2,"ibu":100,"target_fg":1010,"target_og":1064,"ebc":12,"srm":6,"ph":4.4,"attenuation_level":84,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":6.39,"unit":"kilograms"}}],"hops":[{"name":"Mandarina Bavaria","amount":{"value":41.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Mandarina Bavaria","amount":{"value":41.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Mandarina Bavaria","amount":{"value":41.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Lavender and thyme roast beef","Spicy kung po chicken","Caramel and rose essence cheesecake"],"brewers_tips":"We've mentioned the importance of fresh hops previously but this one really demands that your hops are the absolute freshest.","contributed_by":"Sam Mason "},{"id":60,"name":"Dogma","tagline":"Revamped Wee Heavy. Luscious. Malty. Fruity.","first_brewed":"07/2013","description":"Brewed with over ten different types of malt, and blended together with Scottish heather honey, it is a pantheon to the gods of intricacy and nuance; a beer that celebratesa confluence of ideas. Complex, indulgent and encapsulating, Dogma gives more than a cursory nod to history, to make you ponder the very nature of beer itself.","image_url":"https://images.punkapi.com/v2/60.png","abv":7.5,"ibu":30,"target_fg":1023,"target_og":1080,"ebc":46,"srm":23,"ph":4.5,"attenuation_level":70,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":12,"unit":"celsius"}},"twist":"Heather Honey: 125g"},"ingredients":{"malt":[{"name":"Pale Ale","amount":{"value":3.5,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.75,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Crystal","amount":{"value":0.38,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":1,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":1,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Smoked","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Brown","amount":{"value":0.25,"unit":"kilograms"}}],"hops":[{"name":"Saaz","amount":{"value":75,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"First Gold","amount":{"value":10,"unit":"grams"},"add":"start","attribute":"bitter"}],"yeast":"Wyeast 2007 - Pilsen Lager™"},"food_pairing":["Mature cheddar with red onion chutney","Honey glazed ham","Chocolate caramel drizzled sponge cake"],"brewers_tips":"There's a lot of specialty malt in the mash. Make sure you take the run off nice and steady – increase the flow too much and pull in the bed at your peril.","contributed_by":"Ali Skinner "},{"id":61,"name":"Magic Stone Dog (w/Magic Rock & Stone Brewing Co.)","tagline":"Session Farmhouse IPA - Stone / Magic Rock Collab.","first_brewed":"06/2014","description":"A session IPA brewed with a diverse grain bill, hopped with Simcoe and Amarillo and fermented with saison yeast, for an incredible level of depth in a low ABV beer. Spicy, fruity, complex, refreshing and dry.","image_url":"https://images.punkapi.com/v2/61.png","abv":4.6,"ibu":30,"target_fg":1008,"target_og":1043,"ebc":15,"srm":7.5,"ph":4.4,"attenuation_level":81.4,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":23,"unit":"celsius"}},"twist":"Cumin: 0.5g at end, Caraway: 1g at end, Peppercorns (Pink): 5g at end, Grains of Paradise: 5g at end"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":2.38,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.44,"unit":"kilograms"}},{"name":"Torrified Wheat","amount":{"value":0.44,"unit":"kilograms"}},{"name":"Rye","amount":{"value":0.19,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":0.44,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.19,"unit":"kilograms"}}],"hops":[{"name":"Simcoe","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 3711 - French Saison™"},"food_pairing":["Halibut with caper brown butter","Creamy gorgonzola and satsuma salad","Spicy Daal with garlic naan bread"],"brewers_tips":"Start the fermentation off at 20 ̊C and allow it to rise as high as 25 ̊C. This will increase the fruity character of the yeast.","contributed_by":"Sam Mason "},{"id":62,"name":"AB:08","tagline":"Deconstructed Blonde Imperial Stout.","first_brewed":"11/2011","description":"Flavours and aromas you'd expect from a Stout, but brewed without dark malts. The full mouthfeel comes courtesy of wheat and oats, while smoked malt and the twist additions add the complex flavours normally provided by highly kilned malts.","image_url":"https://images.punkapi.com/v2/62.png","abv":10.43,"ibu":65,"target_fg":1016,"target_og":1095,"ebc":23,"srm":11.5,"ph":4.4,"attenuation_level":83.2,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Cacao: 25g at FV, Coffee Beans: 37.5g at FV, Oak Chips: 5g at FV, Vanilla Pods: 10 split pods, Liquorice: 5g at FV"},"ingredients":{"malt":[{"name":"Maris Otter Extra Pale","amount":{"value":9.25,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":1.88,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":1.88,"unit":"kilograms"}},{"name":"Smoked Peaty","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"First Gold","amount":{"value":81.25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"First Gold","amount":{"value":62.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Coffee Beans","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Caramelised scallops with burnt apple puree","Blackened Cajun chicken","Blondies with chocolate fudge sauce"],"brewers_tips":"Add all twist ingredients to Fermentation Vessel once fermentation is complete. Don’t be afraid to add a little at a time and taste as you go. During mashing in first start with pale malt. Afterwards mix all malts evenly. Go with flaked oats during second half of mashing in process.","contributed_by":"Sam Mason "},{"id":63,"name":"Sunk Punk","tagline":"Ocean Fermented Lager.","first_brewed":"09/2011","description":"It's rumoured just a drop can calm the fiercest of storms. A balance of sweet, salt and savoury, citrus, spruce and caramel. Fermented at the bottom of the North Sea, which just so happens to be the perfect temperature for lagers to ferment.","image_url":"https://images.punkapi.com/v2/63.png","abv":7.1,"ibu":68,"target_fg":1010,"target_og":1056,"ebc":14,"srm":7,"ph":4.4,"attenuation_level":82.1,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":10,"unit":"celsius"}},"twist":"Seabuckthorn: 25g at end, Sea Salt: 20g at middle, Rum: 25ml at end"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":5.21,"unit":"kilograms"}}],"hops":[{"name":"Chinook","amount":{"value":20,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Ahtanum","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Chinook","amount":{"value":20,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Ahtanum","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Chinook","amount":{"value":30,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Ahtanum","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Nelson Sauvin","amount":{"value":140,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 2007 - Pilsen Lager™"},"food_pairing":["Salt baked cod with lemon and dill butter","Beef, oyster and ale pie","Apple and rosemary tart"],"brewers_tips":"Keep the fermentation temperature as steady as possible to allow the lager yeast to do its thing.","contributed_by":"Sam Mason "},{"id":64,"name":"Sub Hop","tagline":"Hopped-Up Imperial Pilsner.","first_brewed":"06/2014","description":"Brewed for the opening of our first bar in Italy, BrewDog Firenze. A mega-hoppy Imperial Pilsner, with toasty malt complexity and tropical New World hops.","image_url":"https://images.punkapi.com/v2/64.png","abv":8,"ibu":35,"target_fg":1016,"target_og":1077,"ebc":15,"srm":7.5,"ph":4.4,"attenuation_level":79.2,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":9,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":6.25,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Dextrose","amount":{"value":0.38,"unit":"kilograms"}}],"hops":[{"name":"Saaz","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Hallertauer Mittelfrüh","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Pacifica","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Pacific Jade","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Pacifica","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Pacific Jade","amount":{"value":75,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Pacifica","amount":{"value":37.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 2007- Pilsen Lager™"},"food_pairing":["Seared lemon and herb salmon","Crab linguine","Almond biscotti"],"brewers_tips":"Sit this beer aside for a month to allow it to mellow.","contributed_by":"Sam Mason "},{"id":65,"name":"Bracken's Porter","tagline":"A Tribute To Our Favourite 4 Pawed Friend.","first_brewed":"03/2013","description":"The beer was named Bracken’s Porter as a tribute to our favourite four pawed friend who sadly passed in 2013. Chocolately, robust, warming, laid back and lots of fun - there are plenty of similarities between the two. Bracken we miss you and we hope you like your beer. Long live the original BrewDog.","image_url":"https://images.punkapi.com/v2/keg.png","abv":5,"ibu":50,"target_fg":1010,"target_og":1049,"ebc":110,"srm":55,"ph":4.4,"attenuation_level":79,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":3.63,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.19,"unit":"kilograms"}},{"name":"Roasted Barley","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Black Malt","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"Vic Secret","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Bramling Cross","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"aroma"},{"name":"Challenger","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Grilled vegetable and chicken teriyaki skewers","Chilli covered burger (Sloppy Joe)","Candied bacon topped chocolate cheesecake"],"brewers_tips":"Try to replicate London’s highly carbonated water to really emphasise the dark malt profile.","contributed_by":"Sam Mason "},{"id":66,"name":"Tokyo Rising Sun - Lowland","tagline":"A Beautiful Accident.","first_brewed":"06/2009","description":"A forgotten gem in the deepest, darkest corner of the warehouse. Aged in a Lowland whisky cask resulting in decadent chocolate, toasted vanilla, indulgent spiced fruit, a mesmerizingly hypnotic mouthfeel and new layers that emerge on every sip.","image_url":"https://images.punkapi.com/v2/66.png","abv":13.2,"ibu":85,"target_fg":1023,"target_og":1125,"ebc":140,"srm":71,"ph":4.4,"attenuation_level":82.17,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Cranberry: 25g at end, Jasmine: 25g at end, Muscovado sugar: 300g at start, Oak chips soaked in lowland whisky: 15g at dry hop"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":7.6,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":1.75,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Roasted Barley","amount":{"value":0.5,"unit":"kilograms"}}],"hops":[{"name":"Chinook","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Chinook","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"First Gold","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Chinook","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"WLP099 Super High Gravity Ale"},"food_pairing":["Duck liver paté","Mutton stew","Kirsch chocolate truffles"],"brewers_tips":"Leave on wood for as long as you dare. If possible forget about it for four years.","contributed_by":"Sam Mason "},{"id":67,"name":"Hunter Foundation Pale Ale","tagline":"American Pale Ale.","first_brewed":"05/2012","description":"This straight-up US style pale ale uses some of our favourite hops against a toasty malt base. We brewed this with Sir Tom Hunter at our Fraserburgh brewery - to add a charitable element to your own version, feel free to share this citrusy pale ale with your friends. Or don't, it's your choice.","image_url":"https://images.punkapi.com/v2/67.png","abv":5.4,"ibu":35,"target_fg":1008,"target_og":1050,"ebc":11.5,"srm":5.75,"ph":4.4,"attenuation_level":84,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":63,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Maris Otter Extra Pale","amount":{"value":4.3,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.8,"unit":"kilograms"}}],"hops":[{"name":"Amarillo","amount":{"value":10,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Simcoe","amount":{"value":15,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Citra","amount":{"value":20,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Monterey Jack stuffed grilled jalepenos","Barbecue corn and steak fajita seasoned wrap","Cinnamon & white chocolate churro"],"brewers_tips":"To dry the beer out, mash at a slightly lower temp (62° - 63°C), this will increase the ratio of fermentable sugars in the beer.","contributed_by":"Sam Mason "},{"id":68,"name":"Hype","tagline":"New Zealand Pale Ale.","first_brewed":"08/2007","description":"A perfect pale ale showcase for the tropical profile of New Zealand hops and the intense citrus of US hops.","image_url":"https://images.punkapi.com/v2/keg.png","abv":4.1,"ibu":65,"target_fg":1010,"target_og":1042,"ebc":17,"srm":8.5,"ph":4.4,"attenuation_level":76.2,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Maris Otter Extra Pale","amount":{"value":4.02,"unit":"kilograms"}}],"hops":[{"name":"Nelson Sauvin","amount":{"value":2,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Nelson Sauvin","amount":{"value":5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":2.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Quince cheese","Shredded chicken and mango salsa taquitos","Poached pear"],"brewers_tips":"After the beer has fermented, leave it to rest for 2 – 3 days at the lowest temperature possible (ideally 0 – 2'C). This will allow the flavours to marry together, and will transform it into a balanced and amazing beer.","contributed_by":"Sam Mason "},{"id":69,"name":"AB:16","tagline":"Coffee-Infused Belgian Quad.","first_brewed":"02/2014","description":"On the nose, clove and nutmeg, cafe au lait, subtle dark fruit notes, and hints of candied lemon peel. On the palate, smooth & fruity espresso, milk chocolate, and warm brandy-soaked currants are in the middle of a high-class dance-off against the spicy and peppery Belgian character. The overall impression evokes malt loaf or ginger cake.","image_url":"https://images.punkapi.com/v2/69.png","abv":10.6,"ibu":55,"target_fg":1012,"target_og":1090,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":86.7,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Coffee Beans: 250g FV. Raisins: 90g at end. Dark Sugar:140g at end."},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":7.75,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.38,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"Waimea","amount":{"value":15,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Saaz","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Fuggles","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"}],"yeast":"Wyeast 3787 - Trappist High Gravity™"},"food_pairing":["Roasted duck","Gorgonzola and rye nut bread with smoked honey ham","Raspberry coffee cheesecake"],"brewers_tips":"For the traditional cellering, age this beer in vessel or bottle for 2 - 3 months at cellar temperature.","contributed_by":"Ali Skinner "},{"id":70,"name":"Sunmaid Stout","tagline":"Rum & Raisin Imperial Stout.","first_brewed":"12/2011","description":"Brewed by Chris Sartori from Stone Brewing Company in 2010. A dark chocolate stout with dried dark fruit finish. Simcoe provides bitterness with subtle fruity supporting notes, contrasting the chocolate and coffee-laden malt profile. The finish is warming with vanilla and rich dark fruit depth.","image_url":"https://images.punkapi.com/v2/keg.png","abv":10.2,"ibu":50,"target_fg":1102,"target_og":1026,"ebc":197,"srm":100,"ph":4.4,"attenuation_level":74.5,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":55}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Age in whisky casks with rum soaked raisins"},"ingredients":{"malt":[{"name":"Pale Ale - Tipple","amount":{"value":10,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 3","amount":{"value":0.94,"unit":"kilograms"}},{"name":"Crystal","amount":{"value":0.94,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":1.56,"unit":"kilograms"}}],"hops":[{"name":"Simcoe","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Challenger","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Lapin aux pruneaux (braised rabbit with prunes)","Gouda cheese","Dark chocolate truffles"],"brewers_tips":"Take small volume of wort out of the run off and steep the raisins in it, then crush them up. This will help to release the dark fruit aromas into the wort.","contributed_by":"Sam Mason "},{"id":71,"name":"Pale - Russian Doll","tagline":"Nesting Hop Bomb.","first_brewed":"08/2014","description":"The levels of hops vary throughout the range. We love hops, so all four beers are big, bitter badasses, but by tweaking the amount of each hop used later in the boil and during dry- hopping, we can balance the malty backbone with some unexpected flavours. Simcoe is used in the whirlpool for all four beers, and yet still lends different characters to each.","image_url":"https://images.punkapi.com/v2/71.png","abv":4,"ibu":35,"target_fg":1010,"target_og":1041,"ebc":45,"srm":22.5,"ph":5.2,"attenuation_level":75.6,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":3.63,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"Cascade","amount":{"value":7.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Centennial","amount":{"value":5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Citra","amount":{"value":5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Simcoe","amount":{"value":17.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":62.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Cascade","amount":{"value":62.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Centennial","amount":{"value":62.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Citra","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Roast chicken with vegetables and wild rice","Fresh pico de gallo with corn tortilla","Carrot cake"],"brewers_tips":"Create balance through experimentation with the hop amounts and malt backbone.","contributed_by":"Sam Mason "},{"id":72,"name":"Whisky Sour - B-Sides","tagline":"Pilot Brew - Deconstructed Whisky Sour.","first_brewed":"03/2015","description":"Deconstructed whisky sour, reconstructed as a beer.","image_url":"https://images.punkapi.com/v2/keg.png","abv":7,"ibu":20,"target_fg":1021,"target_og":1081,"ebc":12,"srm":6,"ph":3.2,"attenuation_level":74,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":60,"unit":"celsius"},"duration":10},{"temp":{"value":65,"unit":"celsius"},"duration":30},{"temp":{"value":72,"unit":"celsius"},"duration":10},{"temp":{"value":78,"unit":"celsius"},"duration":5}],"fermentation":{"temp":{"value":null,"unit":"celsius"}},"twist":"Kettle Soured"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":6.88,"unit":"kilograms"}},{"name":"Acidulated Malt","amount":{"value":1.88,"unit":"kilograms"}},{"name":"Wheat Malt","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Rye Malt","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Special W","amount":{"value":0.05,"unit":"kilograms"}}],"hops":[{"name":"Amarillo","amount":{"value":8.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Citra","amount":{"value":8.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Simcoe","amount":{"value":8.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Citra","amount":{"value":5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":1.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Citra","amount":{"value":1.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Simcoe","amount":{"value":1.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Potted fresh & smoked salmon","Spiced nut loaf","Lemon poppyseed donuts"],"brewers_tips":"Lemon poppyseed donuts.","contributed_by":"Sam Mason "},{"id":73,"name":"Black Eyed King Imp - Vietnamese Coffee Edition","tagline":"Vietnamese Coffee Edition.","first_brewed":"12/2014","description":"This is the Vietnamese Coffee Edition. At 12.7% ABV, Black Eyed King Imp is a super intense and twistedly complex brew, with intense notes of sweet vanilla, rich espresso, smooth molasses and bitter chocolate barely contained by the whatever container it's in.","image_url":"https://images.punkapi.com/v2/73.png","abv":12.7,"ibu":85,"target_fg":1038,"target_og":1113.5,"ebc":250,"srm":125,"ph":5.2,"attenuation_level":76.8,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":50}],"fermentation":{"temp":{"value":18,"unit":"celsius"}},"twist":"Coffee Beans: 12.5g at end, Lactose: 125g at FV, Bourbon barrel aged"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":6.25,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Cara","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Crystal","amount":{"value":1.5625,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.625,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.625,"unit":"kilograms"}},{"name":"Brown","amount":{"value":0.625,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.625,"unit":"kilograms"}},{"name":"Roasted Barley","amount":{"value":0.3125,"unit":"kilograms"}}],"hops":[{"name":"Magnum","amount":{"value":62.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Willamette","amount":{"value":31.25,"unit":"grams"},"add":"end","attribute":"bitter"},{"name":"First Gold","amount":{"value":31.25,"unit":"grams"},"add":"end","attribute":"aroma / bitter"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Bacon sandwich with brown sauce","20hr smoked brisket","Chocolate fudge ice cream"],"brewers_tips":"Buying top notch coffee beans make a huge difference here. Give them a very course grind to get the most out of them.","contributed_by":"Sam Mason "},{"id":74,"name":"Eurotrash","tagline":"Belgian Blonde.","first_brewed":"10/2009","description":"Trashy Blonde with a Belgian Twist. Clove oil, red apples and a drier mouthfeel set this beer apart from its older sister.","image_url":"https://images.punkapi.com/v2/keg.png","abv":4.1,"ibu":52,"target_fg":1010,"target_og":1041,"ebc":17,"srm":8.5,"ph":5.2,"attenuation_level":76,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":66,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":"Fermented with Belgian yeast for signature character"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":3.25,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.38,"unit":"kilograms"}}],"hops":[{"name":"Simcoe","amount":{"value":5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":6.3,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Simcoe","amount":{"value":2.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Amarillo","amount":{"value":5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Motueka","amount":{"value":5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Simcoe","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Motueka","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Amarillo","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Motueka","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 3522 - Belgian Ardennes™"},"food_pairing":["Grilled fish salad","Angelfood cake","Pad Thai"],"brewers_tips":"Don't be scared to let the fermentation temperature climb up another couple of degrees to really emphasize the Belgian character.","contributed_by":"Sam Mason "},{"id":75,"name":"Never Mind The Anabolics","tagline":"Performance-Enhancing India Pale Ale.","first_brewed":"06/2012","description":"Never Mind the Anabolics, a 6.5% India Pale Ale brewed with copious amounts of performance-enhancing natural ingredients. Brewed to commemorate the 2012 Olympics and its merry marketing bandwagon.","image_url":"https://images.punkapi.com/v2/75.png","abv":6.5,"ibu":35,"target_fg":1012,"target_og":1050,"ebc":23,"srm":11.5,"ph":4.4,"attenuation_level":76,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":68,"unit":"celsius"},"duration":30}],"fermentation":{"temp":{"value":18,"unit":"celsius"}},"twist":"Lycii Berries: 7.5g at end, Ginseng: 5.625g at end, Guarana: 25g at end, Kolabu: 25g at end, Gingko: 6.25g at end, Matcha Tea: 12.5g at end, Maca Powder: 16.25g at end"},"ingredients":{"malt":[{"name":"Extra Pale - Spring Blend","amount":{"value":4.38,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.31,"unit":"kilograms"}}],"hops":[{"name":"Motueka","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Motueka","amount":{"value":18.75,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Grilled chicken salad with bacon and avocado","Red pepper houmous and flat bread","Matcha green tea cake"],"brewers_tips":"Mix the powders into a paste before adding to the wort kettle. This will prevent the powders from balling up and not bringing the full flavour effect.","contributed_by":"Sam Mason "}] +""" +} diff --git a/Example/Tests/BeersRequestParametersTests.swift b/Example/Tests/BeersRequestParametersTests.swift new file mode 100644 index 0000000..4e3949d --- /dev/null +++ b/Example/Tests/BeersRequestParametersTests.swift @@ -0,0 +1,125 @@ +// +// BeersRequestTests.swift +// PunkAPI_Example +// +// Created by Andrea Altea on 02/03/2019. +// Copyright © 2019 CocoaPods. All rights reserved. +// + +import XCTest +@testable import PunkAPI + +class BeersRequestParametersTests: XCTestCase { + + func testABVParameterGreater() { + let parameter = getParameter(.abv(condition: .more, value: 1.2)) + XCTAssert(parameter.key == "abv_gt") + XCTAssert(1 == parameter.value as? Int) + } + + func testABVParameterLessThan() { + let parameter = getParameter(.abv(condition: .less, value: 1.2)) + XCTAssert(parameter.key == "abv_lt") + XCTAssert(1 == parameter.value as? Int) + } + + func testIBUParameterGreater() { + let parameter = getParameter(.ibu(condition: .more, value: 1.2)) + XCTAssert(parameter.key == "ibu_gt") + XCTAssert(1 == parameter.value as? Int) + } + + func testIBUParameterLessThan() { + let parameter = getParameter(.ibu(condition: .less, value: 1.2)) + XCTAssert(parameter.key == "ibu_lt") + XCTAssert(1 == parameter.value as? Int) + } + + func testEBCParameterGreater() { + let parameter = getParameter(.ebc(condition: .more, value: 1.2)) + XCTAssert(parameter.key == "ebc_gt") + XCTAssert(1 == parameter.value as? Int) + } + + func testEBCParameterLessThan() { + let parameter = getParameter(.ebc(condition: .less, value: 1.2)) + XCTAssert(parameter.key == "ebc_lt") + XCTAssert(1 == parameter.value as? Int) + } + + func testBeerNameParameter() { + let parameter = getParameter(.beerName(value: "PunkIPA")) + XCTAssert(parameter.key == "beer_name") + XCTAssert("PunkIPA" == parameter.value as? String) + } + + func testBeerNameParameterWithSpace() { + let parameter = getParameter(.beerName(value: "Punk IPA")) + XCTAssert(parameter.key == "beer_name") + XCTAssert("Punk_IPA" == parameter.value as? String) + } + + func testYeastParameter() { + let parameter = getParameter(.yeast(value: "AmericanAle")) + XCTAssert(parameter.key == "yeast") + XCTAssert("AmericanAle" == parameter.value as? String) + } + + func testYeastParameterWithSpace() { + let parameter = getParameter(.yeast(value: "American Ale")) + XCTAssert(parameter.key == "yeast") + XCTAssert("American_Ale" == parameter.value as? String) + } + + func testBrewedParameterBefore() { + let parameter = getParameter(.brewed(condition: .less, value: Date(timeIntervalSinceReferenceDate: 5184000))) + XCTAssert(parameter.key == "brewed_before") + XCTAssert("03-2001" == parameter.value as? String) + } + + func testBrewedParameterAfter() { + let parameter = getParameter(.brewed(condition: .more, value: Date(timeIntervalSinceReferenceDate: 2592000))) + XCTAssert(parameter.key == "brewed_after") + XCTAssert("01-2001" == parameter.value as? String) + } + + func testHopsParameter() { + let parameter = getParameter(.hops(value: "Ahtanum")) + XCTAssert(parameter.key == "hops") + XCTAssert("Ahtanum" == parameter.value as? String) + } + + func testHopsParameterWithSpace() { + let parameter = getParameter(.hops(value: "Chi nook")) + XCTAssert(parameter.key == "hops") + XCTAssert("Chi_nook" == parameter.value as? String) + } + + func testFoodParameter() { + let parameter = getParameter(.food(value: "Cheesecake")) + XCTAssert(parameter.key == "food") + XCTAssert("Cheesecake" == parameter.value as? String) + } + + func testFoodParameterWithSpace() { + let parameter = getParameter(.food(value: "Spicy carne")) + XCTAssert(parameter.key == "food") + XCTAssert("Spicy_carne" == parameter.value as? String) + } + + func testIdsParameterSingle() { + let parameter = getParameter(.ids(value: [34])) + XCTAssert(parameter.key == "ids") + XCTAssert("34" == parameter.value as? String) + } + + func testIdsParameterMultiple() { + let parameter = getParameter(.ids(value: [34, 5, 21, 9])) + XCTAssert(parameter.key == "ids") + XCTAssert("34|5|21|9" == parameter.value as? String) + } + + private func getParameter(_ requestParameter: BeersRequest.Parameter) -> RequestParameter { + return requestParameter.parameter + } +} diff --git a/Example/Tests/BeersRequestTests.swift b/Example/Tests/BeersRequestTests.swift new file mode 100644 index 0000000..3c89e4f --- /dev/null +++ b/Example/Tests/BeersRequestTests.swift @@ -0,0 +1,49 @@ +// +// BeersRequestTests.swift +// PunkAPI_Tests +// +// Created by Andrea Altea on 02/03/2019. +// Copyright © 2019 CocoaPods. All rights reserved. +// + +import XCTest +@testable import PunkAPI + +class BeersRequestTests: XCTestCase { + + override func 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. + } + + func testSingleParameter() { + let request = BeersRequest(filter: [.abv(condition: .more, value: 34)]) + XCTAssert(request.path == "beers") + XCTAssert(1 == request.parameters?.count) + XCTAssert(34 == request.parameters?["abv_gt"] as? Int) + } + + func testPageParameter() { + let request = BeersRequest(page: 1) + XCTAssert(request.path == "beers") + XCTAssert(1 == request.parameters?.count) + XCTAssert(1 == request.parameters?["page"] as? Int) + } + + func testInvalidPageParameter() { + let request = BeersRequest(page: 0) + XCTAssert(request.path == "beers") + XCTAssert(request.parameters == nil) + } + + func testPageWithSingleParameter() { + let request = BeersRequest(filter: [.abv(condition: .more, value: 34)], page: 1) + XCTAssert(request.path == "beers") + XCTAssert(2 == request.parameters?.count) + XCTAssert(1 == request.parameters?["page"] as? Int) + XCTAssert(34 == request.parameters?["abv_gt"] as? Int) + } +} diff --git a/Example/Tests/ConfigurationTests.swift b/Example/Tests/ConfigurationTests.swift new file mode 100644 index 0000000..c9e9395 --- /dev/null +++ b/Example/Tests/ConfigurationTests.swift @@ -0,0 +1,27 @@ +// +// ConfigurationTests.swift +// PunkAPI_Tests +// +// Created by Andrea Altea on 24/02/2019. +// Copyright © 2019 CocoaPods. All rights reserved. +// + +import XCTest +@testable import PunkAPI + +class ConfigurationTests: XCTestCase { + + func testConfigurationBuild() { + + let baseURL = URL(string: "test://api.test.it/")! + let configuration = Configuration(sessionConfiguration: .ephemeral, baseURL: baseURL) + + XCTAssert(configuration.baseURL == baseURL) + } + + func testDefaultConfiguration() { + + let configuration = Configuration.default + XCTAssert(configuration.baseURL.absoluteString == "https://api.punkapi.com/v2/") + } +} diff --git a/Example/Tests/MockSession.swift b/Example/Tests/MockSession.swift new file mode 100644 index 0000000..f87b155 --- /dev/null +++ b/Example/Tests/MockSession.swift @@ -0,0 +1,65 @@ +// +// MockSession.swift +// PunkAPI_Tests +// +// Created by Andrea Altea on 24/02/2019. +// Copyright © 2019 CocoaPods. All rights reserved. +// + +import Foundation + +class MockURLSession: URLSession { + + var urlCheckBlock: ((_ url: URL) -> Void)? + + var responseConfig: (data: Data?, response: HTTPURLResponse?, error: Error?)? + + override func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask { + + if let urlCheckBlock = self.urlCheckBlock { + urlCheckBlock(url) + } + + return MockSessionDataTask(config: self.responseConfig, completionHandler: completionHandler) + } +} + +class MockSessionDataTask: URLSessionDataTask { + + enum DataError: String, ConvertibleError { + + case notConfigured = "Not Configured" + } + + var config: (data: Data?, response: HTTPURLResponse?, error: Error?)? + + var completionHandler: (Data?, URLResponse?, Error?) -> Void + + init(config: (data: Data?, response: HTTPURLResponse?, error: Error?)?, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) { + + self.config = config + self.completionHandler = completionHandler + } + + override func resume() { + + guard let config = self.config else { + + completionHandler(nil, nil, DataError.notConfigured) + return + } + completionHandler(config.data, config.response, config.error) + } +} + +protocol ConvertibleError: Error { + + var message: String { get } +} + +extension ConvertibleError where Self: RawRepresentable, Self.RawValue == String{ + + var message: String { + return self.rawValue + } +} diff --git a/Example/Tests/Tests.swift b/Example/Tests/Tests.swift deleted file mode 100644 index 26fbadd..0000000 --- a/Example/Tests/Tests.swift +++ /dev/null @@ -1,28 +0,0 @@ -import XCTest -import PunkAPI - -class Tests: 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. - XCTAssert(true, "Pass") - } - - func testPerformanceExample() { - // This is an example of a performance test case. - self.measure() { - // Put the code you want to measure the time of here. - } - } - -} diff --git a/Example/Tests/URLBuildTests.swift b/Example/Tests/URLBuildTests.swift new file mode 100644 index 0000000..850073d --- /dev/null +++ b/Example/Tests/URLBuildTests.swift @@ -0,0 +1,57 @@ +// +// URLBuildTests.swift +// PunkAPI_Example +// +// Created by Andrea Altea on 24/02/2019. +// Copyright © 2019 CocoaPods. All rights reserved. +// + +import XCTest +@testable import PunkAPI + +class URLBuildTests: XCTestCase { + + var baseURL: URL! + + override func setUp() { + super.setUp() + + self.baseURL = URL(string: "https://api.test.it/v2") + } + + func testBaseURLBuilding() { + + let request = MockRequest(path: "beer/1", parameters: nil) + let url = self.baseURL.url(request: request) + XCTAssert(url?.absoluteString == "https://api.test.it/v2/beer/1") + } + + func testWrongRelativePathURLBuilding() { + + let request = MockRequest(path: "/beer/1", parameters: nil) + let url = self.baseURL.url(request: request) + XCTAssert(url?.absoluteString == "https://api.test.it/v2/beer/1") + } + + func testParametersURLBuilding() { + + let request = MockRequest(path: "/beer", + parameters: ["integer": 1, "string": "text", "object": NSNumber(value: 3)]) + guard let url = self.baseURL.url(request: request) else { + return XCTFail("undefined url") + } + guard let queryItems = URLComponents(url: url, resolvingAgainstBaseURL: true)?.queryItems else { + return XCTFail("undefined query") + } + XCTAssert(queryItems.count == 3) + XCTAssert(queryItems.contains(URLQueryItem(name: "integer", value: "1"))) + XCTAssert(queryItems.contains(URLQueryItem(name: "string", value: "text"))) + XCTAssert(queryItems.contains(URLQueryItem(name: "object", value: "3"))) + } +} + +struct MockRequest: Request { + + var path: String + var parameters: [String : Any]? = nil +} diff --git a/PunkAPI/Classes/ReplaceMe.swift b/Example/fastlane/Appfile similarity index 100% rename from PunkAPI/Classes/ReplaceMe.swift rename to Example/fastlane/Appfile diff --git a/Example/fastlane/Fastfile b/Example/fastlane/Fastfile new file mode 100644 index 0000000..368968b --- /dev/null +++ b/Example/fastlane/Fastfile @@ -0,0 +1,71 @@ +# This file contains the fastlane.tools configuration +# You can find the documentation at https://docs.fastlane.tools +# +# For a list of all available actions, check out +# +# https://docs.fastlane.tools/actions +# +# For a list of all available plugins, check out +# +# https://docs.fastlane.tools/plugins/available-plugins +# + +update_fastlane + +default_platform(:ios) + +platform :ios do + + desc "Default CI lane" + lane :ci do + test + coverage + end + + desc "SwiftLint linting" + lane :lint do + swiftlint( + mode: :lint, + ignore_exit_status: false + ) + end + + desc "Pod lib lint" + lane :pod_lint do + Dir.chdir("../..") do + sh("pod lib lint") + end + end + + desc "Runs all the tests" + lane :test do + scan( + scheme: "PunkAPI-Example", + device: "iPhone XS", + code_coverage: true + ) + end + + desc "Slather sends coverage to Coveralls" + lane :coverage do + slather( + travis: true, + workspace: "PunkAPI.xcworkspace", + proj: "PunkAPI.xcodeproj", + scheme: "PunkAPI-Example", + binary_basename: "PunkAPI", + source_directory: "../PunkAPI/*", + simple_output: true, + coveralls: true + ) + end + + desc "Clean environment after all operations" + lane :clean do + clean_build_artifacts + end + + after_all do |lane| + clean + end +end diff --git a/Example/fastlane/README.md b/Example/fastlane/README.md new file mode 100644 index 0000000..e9d099b --- /dev/null +++ b/Example/fastlane/README.md @@ -0,0 +1,54 @@ +fastlane documentation +================ +# Installation + +Make sure you have the latest version of the Xcode command line tools installed: + +``` +xcode-select --install +``` + +Install _fastlane_ using +``` +[sudo] gem install fastlane -NV +``` +or alternatively using `brew cask install fastlane` + +# Available Actions +## iOS +### ios ci +``` +fastlane ios ci +``` +Default CI lane +### ios lint +``` +fastlane ios lint +``` +SwiftLint linting +### ios pod_lint +``` +fastlane ios pod_lint +``` +Pod lib lint +### ios test +``` +fastlane ios test +``` +Runs all the tests +### ios coverage +``` +fastlane ios coverage +``` +Slather sends coverage to Coveralls +### ios clean +``` +fastlane ios clean +``` +Clean environment after all operations + +---- + +This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run. +More information about fastlane can be found on [fastlane.tools](https://fastlane.tools). +The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools). diff --git a/Example/fastlane/report.xml b/Example/fastlane/report.xml new file mode 100644 index 0000000..cbcccbe --- /dev/null +++ b/Example/fastlane/report.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..85ba602 --- /dev/null +++ b/Gemfile @@ -0,0 +1,5 @@ +source "https://rubygems.org" + +gem "fastlane" +gem "cocoapods" +gem "slather" diff --git a/PunkAPI.podspec b/PunkAPI.podspec index a698767..660fbad 100644 --- a/PunkAPI.podspec +++ b/PunkAPI.podspec @@ -9,26 +9,20 @@ Pod::Spec.new do |s| s.name = 'PunkAPI' s.version = '0.1.0' - s.summary = 'A short description of PunkAPI.' - -# This description is used to generate tags and improve search results. -# * Think: What does it do? Why did you write it? What is the focus? -# * Try to keep it short, snappy and to the point. -# * Write the description between the DESC delimiters below. -# * Finally, don't worry about the indent, CocoaPods strips it! - + s.summary = 'A little swift wrapper for PunkAPI by @samjbmason' + s.swift_version = '4.2' + s.description = <<-DESC -TODO: Add long description of the pod here. + "Have you ever wanted to search through Brewdog's expansive back catalogue of beer in a programmatic way? Maybe build a tool that pairs beer with food, or search beers with an abv of more than 4%? Well now your prayers have been answered!" DESC - s.homepage = 'https://github.com/acct=/PunkAPI' - # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' + s.homepage = 'https://github.com/Oni-zerone/PunkAPI' s.license = { :type => 'MIT', :file => 'LICENSE' } - s.author = { 'acct=' => 'oni.zerone@gmail.com' } - s.source = { :git => 'https://github.com/acct=/PunkAPI.git', :tag => s.version.to_s } - # s.social_media_url = 'https://twitter.com/' + s.author = { 'Andrea Altea' => 'oni.zerone@gmail.com' } + s.source = { :git => 'https://github.com/Oni-zerone/PunkAPI.git', :tag => s.version.to_s } + s.social_media_url = 'https://twitter.com/Oni_zerone' - s.ios.deployment_target = '8.0' + s.ios.deployment_target = '10.0' s.source_files = 'PunkAPI/Classes/**/*' diff --git a/PunkAPI/Classes/Configuration.swift b/PunkAPI/Classes/Configuration.swift new file mode 100644 index 0000000..e0ef4a9 --- /dev/null +++ b/PunkAPI/Classes/Configuration.swift @@ -0,0 +1,27 @@ +// +// Configuration.swift +// PunkAPI +// +// Created by Andrea Altea on 17/02/2019. +// + +import Foundation + +public struct Configuration { + + var session: URLSession + + var baseURL: URL + + public init(sessionConfiguration: URLSessionConfiguration, baseURL: URL) { + + self.session = URLSession(configuration: sessionConfiguration) + self.baseURL = baseURL + } +} + +public extension Configuration { + + public static let `default` = Configuration(sessionConfiguration: .default, + baseURL: URL(string: "https://api.punkapi.com/v2/")!) +} diff --git a/PunkAPI/Classes/Content/Beer.swift b/PunkAPI/Classes/Content/Beer.swift new file mode 100644 index 0000000..ff47cbc --- /dev/null +++ b/PunkAPI/Classes/Content/Beer.swift @@ -0,0 +1,37 @@ +// +// Beer.swift +// PunkAPI +// +// Created by Andrea Altea on 17/02/2019. +// + +import Foundation + +public struct Beer: Codable { + + public var id: Int + public var name: String? + public var tagline: String? + public var firstBrewed: String? + public var description: String? + public var imageUrl: String? + + public var abv: Float? + public var ibu: Float? + + public var targetFg: Float? + public var targetOg: Float? + + public var ebc: Float? + public var srm: Float? + public var ph: Float? + + public var attenuationLevel: Float? + public var volume: Volume? + public var boilVolume: Volume? + public var method: Method? + public var ingredients: Recipe? + public var foodPairing: [String] + public var brewersTips: String? + public var contributedBy: String? +} diff --git a/PunkAPI/Classes/Content/Method.swift b/PunkAPI/Classes/Content/Method.swift new file mode 100644 index 0000000..115e75c --- /dev/null +++ b/PunkAPI/Classes/Content/Method.swift @@ -0,0 +1,20 @@ +// +// Method.swift +// PunkAPI +// +// Created by Andrea Altea on 22/02/2019. +// + +import Foundation + +public struct Method: Codable { + + public struct Step: Codable { + public var temp: Temperature? + public var duration: Float? + } + + public var mashTemp: [Step]? + public var fermentation: Temperature? + public var twist: String? +} diff --git a/PunkAPI/Classes/Content/Quantity.swift b/PunkAPI/Classes/Content/Quantity.swift new file mode 100644 index 0000000..7aeaefc --- /dev/null +++ b/PunkAPI/Classes/Content/Quantity.swift @@ -0,0 +1,19 @@ +// +// Quantity.swift +// PunkAPI +// +// Created by Andrea Altea on 22/02/2019. +// + +import Foundation + +public struct Quantity: Codable { + public var value: Float? + public var unit: String? +} + +public typealias Temperature = Quantity + +public typealias Mass = Quantity + +public typealias Volume = Quantity diff --git a/PunkAPI/Classes/Content/Recipe.swift b/PunkAPI/Classes/Content/Recipe.swift new file mode 100644 index 0000000..1b525fc --- /dev/null +++ b/PunkAPI/Classes/Content/Recipe.swift @@ -0,0 +1,20 @@ +// +// Recipe.swift +// Pods-PunkAPI_Example +// +// Created by Andrea Altea on 22/02/2019. +// + +import Foundation + +public struct Recipe: Codable { + + public struct Ingredient: Codable { + public var name: String? + public var amount: Mass? + } + + public var malt: [Ingredient] + public var hops: [Ingredient] + public var yeast: String? +} diff --git a/PunkAPI/Classes/PunkAPI.swift b/PunkAPI/Classes/PunkAPI.swift new file mode 100644 index 0000000..f3b00c1 --- /dev/null +++ b/PunkAPI/Classes/PunkAPI.swift @@ -0,0 +1,57 @@ +// +// PunkAPI.swift +// Pods-PunkAPI_Example +// +// Created by Andrea Altea on 17/02/2019. +// + +import Foundation + +public class PunkAPI { + + var configuration: Configuration + + public init(configuration: Configuration = .default) { + + self.configuration = configuration + } + + public func get(_ request: Request, queue: DispatchQueue = .global(qos: .background), completion: @escaping (Result<[Beer]>) -> Void) { + + guard let url = configuration.baseURL.url(request: request) else { + queue.async { completion(.failure(APIError.invalidURL)) } + return + } + + self.configuration.session.dataTask(with: url) { (result: Result<[Beer]>) in + queue.async { completion(result) } + }.resume() + } +} + +extension URLSession { + + func dataTask(with url: URL, completion: @escaping (Result) -> Void) -> URLSessionDataTask { + return self.dataTask(with: url) { (data, response, error) in + + do { + if let error = error { + throw error + } + + guard let data = data else { + throw APIError.emptyResponse + } + + let decoder = JSONDecoder() + decoder.keyDecodingStrategy = .convertFromSnakeCase + + let beers = try decoder.decode(Value.self, from: data) + completion(.success(beers)) + + } catch let error { + completion(.failure(error)) + } + } + } +} diff --git a/PunkAPI/Classes/Request/BeerRequest.swift b/PunkAPI/Classes/Request/BeerRequest.swift new file mode 100644 index 0000000..2cad065 --- /dev/null +++ b/PunkAPI/Classes/Request/BeerRequest.swift @@ -0,0 +1,21 @@ +// +// BeerRequest.swift +// PunkAPI +// +// Created by Andrea Altea on 17/02/2019. +// + +import Foundation + +public struct BeerRequest: Request { + + public var id: Int + + public var path: String { + return "beers/\(self.id)" + } + + public init(id: Int) { + self.id = id + } +} diff --git a/PunkAPI/Classes/Request/BeersRequest.swift b/PunkAPI/Classes/Request/BeersRequest.swift new file mode 100644 index 0000000..f45da1d --- /dev/null +++ b/PunkAPI/Classes/Request/BeersRequest.swift @@ -0,0 +1,49 @@ +// +// BeersRequest.swift +// PunkAPI +// +// Created by Andrea Altea on 25/02/2019. +// + +import UIKit + +public struct BeersRequest { + + public var page: Int + public var filter: [BeersRequest.Parameter] + + public init(filter:[BeersRequest.Parameter] = [], page: Int = 0) { + self.filter = filter + self.page = page + } +} + +extension BeersRequest: Request { + + public var path: String { + return "beers" + } + + public var parameters: [String: Any]? { + + guard page > 0 else { return filterParameters } + + var parameters = filterParameters ?? [:] + parameters["page"] = page + return parameters + } +} + +extension BeersRequest { + + var filterParameters: [String: Any]? { + + if filter.isEmpty { return nil } + + return filter.map { parameter -> RequestParameter in + return parameter.parameter + }.reduce(into: [:], { (result, parameter) in + result[parameter.key] = parameter.value + }) + } +} diff --git a/PunkAPI/Classes/Request/Parameter/BeersRequestParameter.swift b/PunkAPI/Classes/Request/Parameter/BeersRequestParameter.swift new file mode 100644 index 0000000..c617592 --- /dev/null +++ b/PunkAPI/Classes/Request/Parameter/BeersRequestParameter.swift @@ -0,0 +1,63 @@ +// +// BeersRequestParameter.swift +// PunkAPI +// +// Created by Andrea Altea on 02/03/2019. +// + +import Foundation + +extension BeersRequest { + + public enum Parameter { + + case abv(condition: Condition, value: Float) + case ibu(condition: Condition, value: Float) + case ebc(condition: Condition, value: Float) + + case beerName(value: String) + case yeast(value: String) + + case brewed(condition: Condition, value: Date) + + case hops(value: String) + case malt(value: String) + case food(value: String) + + case ids(value: [Int]) + } +} + +extension BeersRequest.Parameter { + + + internal var parameter: RequestParameter { + switch self { + case let .abv(condition, value): + return IntParameter(key: "abv", condition: condition, value: value) + case let .ibu(condition, value): + return IntParameter(key: "ibu", condition: condition, value: value) + case let .ebc(condition, value): + return IntParameter(key: "ebc", condition: condition, value: value) + + case let .beerName(value): + return StringParameter(key: "beer_name", value: value) + case let .yeast(value): + return StringParameter(key: "yeast", value: value) + + case let .brewed(condition, value): + return DateParameter(type: "brewed", condition: condition, dateValue: value) + + case let .hops(value): + return StringParameter(key: "hops", value: value) + case let .malt(value): + return StringParameter(key: "malt", value: value) + case let .food(value): + return StringParameter(key: "food", value: value) + + case let .ids(value): + let ids = value.map { "\($0)" }.reduce("", { $0.isEmpty ? $1 : $0 + "|" + $1 }) + return StringParameter(key: "ids", value: ids) + } + } +} diff --git a/PunkAPI/Classes/Request/Parameter/DateParameter.swift b/PunkAPI/Classes/Request/Parameter/DateParameter.swift new file mode 100644 index 0000000..d6c8f74 --- /dev/null +++ b/PunkAPI/Classes/Request/Parameter/DateParameter.swift @@ -0,0 +1,30 @@ +// +// DateParameter.swift +// PunkAPI +// +// Created by Andrea Altea on 02/03/2019. +// + +import Foundation + +struct DateParameter: RequestParameter { + + static var formatter: DateFormatter = { + let formatter = DateFormatter() + formatter.locale = Locale.current + formatter.dateFormat = "MM-yyyy" + return formatter + }() + + var type: String + var condition: Condition + var dateValue: Date + + var key: String { + return "\(type)_\(condition.time)" + } + + var value: Any { + return DateParameter.formatter.string(from: dateValue) + } +} diff --git a/PunkAPI/Classes/Request/Parameter/FloatParameter.swift b/PunkAPI/Classes/Request/Parameter/FloatParameter.swift new file mode 100644 index 0000000..02ea838 --- /dev/null +++ b/PunkAPI/Classes/Request/Parameter/FloatParameter.swift @@ -0,0 +1,23 @@ +// +// IntParameter.swift +// PunkAPI +// +// Created by Andrea Altea on 02/03/2019. +// + +import Foundation + +struct IntParameter: RequestParameter { + + var type: String + var condition: Condition + var value: Any + init(key: String, condition: Condition, value: Float) { + self.type = key + self.condition = condition + self.value = Int(value) + } + var key: String { + return "\(type)_\(condition.dimension)" + } +} diff --git a/PunkAPI/Classes/Request/Parameter/RequestParameter.swift b/PunkAPI/Classes/Request/Parameter/RequestParameter.swift new file mode 100644 index 0000000..407ef9a --- /dev/null +++ b/PunkAPI/Classes/Request/Parameter/RequestParameter.swift @@ -0,0 +1,36 @@ +// +// RequestParameter.swift +// PunkAPI +// +// Created by Andrea Altea on 02/03/2019. +// + +import Foundation + +protocol RequestParameter { + + var key: String { get } + var value: Any { get } +} + +public enum Condition { + case more + case less +} + +extension Condition { + + var dimension: String { + switch self { + case .more: return "gt" + case .less: return "lt" + } + } + + var time: String { + switch self { + case .more: return "after" + case .less: return "before" + } + } +} diff --git a/PunkAPI/Classes/Request/Parameter/StringParameter.swift b/PunkAPI/Classes/Request/Parameter/StringParameter.swift new file mode 100644 index 0000000..ac25395 --- /dev/null +++ b/PunkAPI/Classes/Request/Parameter/StringParameter.swift @@ -0,0 +1,19 @@ +// +// StringParameter.swift +// PunkAPI +// +// Created by Andrea Altea on 02/03/2019. +// + +import Foundation + +struct StringParameter: RequestParameter { + + var key: String + var value: Any + + init(key: String, value: String) { + self.key = key + self.value = value.replacingOccurrences(of: " ", with: "_") + } +} diff --git a/PunkAPI/Classes/Request/RandomBeerRequest.swift b/PunkAPI/Classes/Request/RandomBeerRequest.swift new file mode 100644 index 0000000..c75fd15 --- /dev/null +++ b/PunkAPI/Classes/Request/RandomBeerRequest.swift @@ -0,0 +1,17 @@ +// +// RandomBeerRequest.swift +// PunkAPI +// +// Created by Andrea Altea on 24/02/2019. +// + +import Foundation + +public struct RandomBeerRequest: Request { + + public var path: String { + return "beers/random" + } + + public init() { } +} diff --git a/PunkAPI/Classes/Request/Request.swift b/PunkAPI/Classes/Request/Request.swift new file mode 100644 index 0000000..fca3280 --- /dev/null +++ b/PunkAPI/Classes/Request/Request.swift @@ -0,0 +1,22 @@ +// +// Request.swift +// Pods-PunkAPI_Example +// +// Created by Andrea Altea on 17/02/2019. +// + +import Foundation + +public protocol Request { + + var path: String { get } + + var parameters: [String: Any]? { get } +} + +public extension Request { + + var parameters: [String: Any]? { + return nil + } +} diff --git a/PunkAPI/Classes/Request/URLBuilder.swift b/PunkAPI/Classes/Request/URLBuilder.swift new file mode 100644 index 0000000..1722a90 --- /dev/null +++ b/PunkAPI/Classes/Request/URLBuilder.swift @@ -0,0 +1,19 @@ +// +// URLBuilder.swift +// PunkAPI +// +// Created by Andrea Altea on 24/02/2019. +// + +import Foundation + +extension URL { + + func url(request: Request) -> URL? { + + let url = self.appendingPathComponent(request.path) + guard var components = URLComponents(url: url, resolvingAgainstBaseURL: true) else { return nil } + components.queryItems = request.parameters?.map { URLQueryItem(name: $0, value: "\($1)") } + return components.url + } +} diff --git a/PunkAPI/Classes/Results/Errors.swift b/PunkAPI/Classes/Results/Errors.swift new file mode 100644 index 0000000..3e69681 --- /dev/null +++ b/PunkAPI/Classes/Results/Errors.swift @@ -0,0 +1,14 @@ +// +// Errors.swift +// PunkAPI +// +// Created by Andrea Altea on 17/02/2019. +// + +import Foundation + +public enum APIError: Error { + + case invalidURL + case emptyResponse +} diff --git a/PunkAPI/Classes/Results/Result.swift b/PunkAPI/Classes/Results/Result.swift new file mode 100644 index 0000000..e038c5e --- /dev/null +++ b/PunkAPI/Classes/Results/Result.swift @@ -0,0 +1,14 @@ +// +// Result.swift +// PunkAPI +// +// Created by Andrea Altea on 17/02/2019. +// + +import Foundation + +public enum Result { + + case success(Value) + case failure(Error) +} diff --git a/README.md b/README.md index cc0f28c..bdac100 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,19 @@ # PunkAPI -[![CI Status](https://img.shields.io/travis/acct=/PunkAPI.svg?style=flat)](https://travis-ci.org/acct=/PunkAPI) [![Version](https://img.shields.io/cocoapods/v/PunkAPI.svg?style=flat)](https://cocoapods.org/pods/PunkAPI) +[![Build Status](https://travis-ci.com/Oni-zerone/PunkAPI.svg?branch=develop)](https://travis-ci.com/Oni-zerone/PunkAPI) +[![Coverage Status](https://coveralls.io/repos/github/Oni-zerone/PunkAPI/badge.svg?branch=feature%2FRandom-beer-request)](https://coveralls.io/github/Oni-zerone/PunkAPI?branch=feature%2FRandom-beer-request) +[![codebeat badge](https://codebeat.co/badges/bfe75f4d-ac1f-4e09-8a25-4f836bb93428)](https://codebeat.co/projects/github-com-oni-zerone-punkapi-develop) +[![Language](https://img.shields.io/badge/language-swift-orange.svg)](https://cocoapods.org/pods/PowerTools) [![License](https://img.shields.io/cocoapods/l/PunkAPI.svg?style=flat)](https://cocoapods.org/pods/PunkAPI) [![Platform](https://img.shields.io/cocoapods/p/PunkAPI.svg?style=flat)](https://cocoapods.org/pods/PunkAPI) +**This is a wrapper around PunkAPI v2 by [@samjbmason](https://twitter.com/samjbmason) you can find more informations about those APIs at https://punkapi.com/** + +_Have you ever wanted to search through Brewdog's expansive back catalogue of beer in a programmatic way? Maybe build a tool that pairs beer with food, or search beers with an abv of more than 4%? Well now your prayers have been answered!_ + +_The Punk API takes Brewdog's DIY Dog and turns it into a searchable, filterable API that's completely free and open source._ + ## Example To run the example project, clone the repo, and run `pod install` from the Example directory first. @@ -22,7 +31,7 @@ pod 'PunkAPI' ## Author -acct=, oni.zerone@gmail.com +[@Oni_zerone](https://twitter.com/Oni_zerone), oni.zerone@gmail.com ## License